{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "mapjsx", "type": "registry:ui", "title": "Map", "description": "A MapLibre-powered map component for React Vite with markers, popups, tooltips, routes, and controls.", "dependencies": [ "maplibre-gl", "lucide-react" ], "registryDependencies": [], "files": [ { "path": "components/ui/map.jsx", "type": "registry:ui", "content": "\"use client\";\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport MapLibreGL from \"maplibre-gl\";\nimport \"maplibre-gl/dist/maplibre-gl.css\";\nimport { X, Minus, Plus, Locate, Maximize, Loader2 } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Custom hook for Vite to detect dark mode without next-themes\n */\nfunction useResolvedTheme() {\n const [theme, setTheme] = useState(\n typeof document !== \"undefined\" && document.documentElement.classList.contains(\"dark\")\n ? \"dark\"\n : \"light\"\n );\n\n useEffect(() => {\n const observer = new MutationObserver(() => {\n const isDark = document.documentElement.classList.contains(\"dark\");\n setTheme(isDark ? \"dark\" : \"light\");\n });\n\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n\n return () => observer.disconnect();\n }, []);\n\n return theme;\n}\n\nconst MapContext = createContext(null);\n\nexport function useMap() {\n const context = useContext(MapContext);\n if (!context) {\n throw new Error(\"useMap must be used within a Map component\");\n }\n return context;\n}\n\nconst defaultStyles = {\n dark: \"https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json\",\n light: \"https://basemaps.cartocdn.com/gl/positron-gl-style/style.json\",\n};\n\nconst DefaultLoader = () => (\n