import { useAtom } from "jotai"; import { useDrag, useDrop, DndProvider } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import { ActiveLayer, activeLayersAtom, disableAllLayersAtom, enableAllLayersAtom, removeAllLayersAtom, reorderLayersAtom, } from "../../../state/active-layers"; import EmptyState from "../empty-state"; import { mapAtom } from "../../../state/map"; import L from "leaflet"; import { LayerControlItem } from "./layer-control-item"; import { useCallback, useRef, useState } from "react"; import { leafletLayerInstancesAtom } from "../../../state/leaflet-layer-instances"; import { Eye, EyeOff, Trash2 } from "lucide-react"; const DraggableLayerItem = ({ layer, layerInstance, index, moveLayer, onZoom, }: { layer: ActiveLayer; layerInstance?: L.Layer; index: number; moveLayer: (dragIndex: number, hoverIndex: number) => void; onZoom: (bounds?: L.LatLngBoundsExpression | null) => void; }) => { const ref = useRef(null); const [{ isDragging }, drag] = useDrag({ type: "LAYER", item: { id: layer.id, index }, collect: (monitor) => ({ isDragging: monitor.isDragging(), }), }); const [, drop] = useDrop({ accept: "LAYER", drop(item: { id: string; index: number }) { if (!ref.current) return; const dragIndex = item.index; const hoverIndex = index; if (dragIndex === hoverIndex) return; moveLayer(dragIndex, hoverIndex); // Update the item's index so it's correct for future operations item.index = hoverIndex; }, }); drag(drop(ref)); return (
); }; export default function LayerControls() { const [activeLayers] = useAtom(activeLayersAtom); const [, reorderLayers] = useAtom(reorderLayersAtom); const [, enableAllLayers] = useAtom(enableAllLayersAtom); const [, disableAllLayers] = useAtom(disableAllLayersAtom); const [, removeAllLayers] = useAtom(removeAllLayersAtom); const [map] = useAtom(mapAtom); const [layerInstances] = useAtom(leafletLayerInstancesAtom); const [allLayersVisible, setAllLayersVisible] = useState(true); const handleZoomToLayer = (bounds?: L.LatLngBoundsExpression | null) => { if (!map) return; if (bounds) { map.fitBounds(bounds, { padding: [50, 50] }); } else { map.setZoom(map.getZoom() + 1); } }; const moveLayer = useCallback( (dragIndex: number, hoverIndex: number) => { reorderLayers({ fromIndex: dragIndex, toIndex: hoverIndex }); }, [reorderLayers] ); const toggleAllLayers = () => { if (allLayersVisible) { disableAllLayers(); activeLayers.forEach((layer) => { const instance = layerInstances.get(layer.id); if (instance) instance.remove(); }); } else { enableAllLayers(); activeLayers.forEach((layer) => { const instance = layerInstances.get(layer.id); if (instance && map) instance.addTo(map); }); } setAllLayersVisible(!allLayersVisible); }; if (activeLayers.length === 0) { return ; } return (
{/* Dataset Count */}
Dataset{" "} {activeLayers.length}
{/* Buttons Below Dataset Text */}
{/* Layer List */}
{[...activeLayers].reverse().map((layer, i) => { const index = activeLayers.length - 1 - i; const layerInstance = layerInstances.get(layer.id); return ( ); })}
); }