import { CRIME_RATE_COLORS } from "@/app/_utils/const/map" 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 MapLegendProps { position?: ControlPosition isFullscreen?: boolean } // React component for legend content const LegendContent = () => { return (
Low
Medium
High
) } class MapLegendControl implements IControl { private container: HTMLElement; private map?: Map; private props: MapLegendProps; private root: ReturnType | null = null; private isUnmounting: boolean = false; constructor(props: MapLegendProps) { 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-legend'; this.render(); return this.container; } onRemove(): void { // Prevent multiple unmounting attempts if (this.isUnmounting) return; this.isUnmounting = true; // Schedule unmounting to happen after current render cycle completes 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: MapLegendProps): void { this.props = props; this.render(); } render(): void { // Only render if in fullscreen or if isFullscreen prop is not provided if (this.props.isFullscreen === false) { if (this.container.style.display !== 'none') { this.container.style.display = 'none'; } return; } else { this.container.style.display = 'block'; } // Create a root if it doesn't exist if (!this.root) { this.root = createRoot(this.container); } // Render using the createRoot API this.root.render(); } } export function MapLegend({ position = 'bottom-right', isFullscreen }: MapLegendProps) { const control = useControl( () => new MapLegendControl({ position, isFullscreen }), { position } ); // Update control when props change useEffect(() => { control.updateProps({ position, isFullscreen }); }, [control, position, isFullscreen]); return null; }