127 lines
4.1 KiB
TypeScript
127 lines
4.1 KiB
TypeScript
import { Checkbox } from "../../ui/checkbox";
|
|
import { Label } from "../../ui/label";
|
|
import { RadioGroup, RadioGroupItem } from "../../ui/radio-group";
|
|
import { ControlPosition, IControl, Map } from "mapbox-gl"
|
|
import { useControl } from "react-map-gl/mapbox"
|
|
import React, { useEffect } from "react"
|
|
import { createRoot } from "react-dom/client"
|
|
|
|
interface MapLayerControlProps {
|
|
position?: ControlPosition
|
|
isFullscreen?: boolean
|
|
}
|
|
|
|
// React component for layer control content
|
|
const LayerControlContent = () => {
|
|
return (
|
|
<div className="space-y-3">
|
|
<div className="text-sm font-medium">Lapisan peta</div>
|
|
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox id="sambaran-petir" />
|
|
<Label htmlFor="sambaran-petir" className="text-xs text-white">
|
|
Sambaran petir
|
|
</Label>
|
|
</div>
|
|
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox id="jalur-badai" defaultChecked />
|
|
<Label htmlFor="jalur-badai" className="text-xs text-white">
|
|
Jalur badai guntur
|
|
</Label>
|
|
</div>
|
|
|
|
<div className="mt-4">
|
|
<div className="text-sm font-medium mb-2">Waktu</div>
|
|
<RadioGroup defaultValue="4jam">
|
|
<div className="flex items-center space-x-2">
|
|
<RadioGroupItem value="4jam" id="4jam" />
|
|
<Label htmlFor="4jam" className="text-xs text-white">
|
|
4 Jam
|
|
</Label>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<RadioGroupItem value="10hari" id="10hari" />
|
|
<Label htmlFor="10hari" className="text-xs text-white">
|
|
10 Hari
|
|
</Label>
|
|
</div>
|
|
</RadioGroup>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
class LayerControlMapboxControl implements IControl {
|
|
private container: HTMLElement;
|
|
private map?: Map;
|
|
private props: MapLayerControlProps;
|
|
private root: ReturnType<typeof createRoot> | null = null;
|
|
private isUnmounting: boolean = false;
|
|
|
|
constructor(props: MapLayerControlProps) {
|
|
this.props = props;
|
|
this.container = document.createElement("div");
|
|
this.container.className = "mapboxgl-ctrl";
|
|
}
|
|
|
|
onAdd(map: Map): HTMLElement {
|
|
this.map = map;
|
|
this.container.className = 'mapboxgl-ctrl mapboxgl-ctrl-layer absolute bottom-36 left-0 z-20 bg-black/70 text-white p-3 rounded-tr-lg';
|
|
this.render();
|
|
return this.container;
|
|
}
|
|
|
|
onRemove(): void {
|
|
if (this.isUnmounting) return;
|
|
|
|
this.isUnmounting = true;
|
|
requestAnimationFrame(() => {
|
|
if (this.root) {
|
|
this.root.unmount();
|
|
this.root = null;
|
|
}
|
|
if (this.container.parentNode) {
|
|
this.container.parentNode.removeChild(this.container);
|
|
}
|
|
this.map = undefined;
|
|
this.isUnmounting = false;
|
|
});
|
|
}
|
|
|
|
updateProps(props: MapLayerControlProps): void {
|
|
this.props = props;
|
|
this.render();
|
|
}
|
|
|
|
render(): void {
|
|
if (this.props.isFullscreen === false) {
|
|
if (this.container.style.display !== 'none') {
|
|
this.container.style.display = 'none';
|
|
}
|
|
return;
|
|
} else {
|
|
this.container.style.display = 'block';
|
|
}
|
|
|
|
if (!this.root) {
|
|
this.root = createRoot(this.container);
|
|
}
|
|
|
|
this.root.render(<LayerControlContent />);
|
|
}
|
|
}
|
|
|
|
export function MapLayerControl({ position = 'bottom-left', isFullscreen }: MapLayerControlProps) {
|
|
const control = useControl<LayerControlMapboxControl>(
|
|
() => new LayerControlMapboxControl({ position, isFullscreen }),
|
|
{ position }
|
|
);
|
|
|
|
useEffect(() => {
|
|
control.updateProps({ position, isFullscreen });
|
|
}, [control, position, isFullscreen]);
|
|
|
|
return null;
|
|
}
|