@seed-ship/mcp-ui-solid 6.15.0 → 6.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/README.md +20 -3
- package/dist/_virtual/leaflet.markercluster-src.cjs +30 -7
- package/dist/_virtual/leaflet.markercluster-src.cjs.map +1 -1
- package/dist/_virtual/leaflet.markercluster-src.js +28 -5
- package/dist/_virtual/leaflet.markercluster-src.js.map +1 -1
- package/dist/_virtual/{leaflet.markercluster-src2.cjs → leaflet2.markercluster-src.cjs} +1 -1
- package/dist/_virtual/leaflet2.markercluster-src.cjs.map +1 -0
- package/dist/_virtual/{leaflet.markercluster-src2.js → leaflet2.markercluster-src.js} +1 -1
- package/dist/_virtual/leaflet2.markercluster-src.js.map +1 -0
- package/dist/adapters/connector.js +1 -1
- package/dist/components/ActionGroupRenderer.js +1 -1
- package/dist/components/ActionRenderer.js +1 -1
- package/dist/components/AgentCard.js +1 -1
- package/dist/components/AgentHandoff.js +1 -1
- package/dist/components/ArtifactRenderer.js +1 -1
- package/dist/components/AutocompleteDropdown.cjs +1 -2
- package/dist/components/AutocompleteDropdown.cjs.map +1 -1
- package/dist/components/AutocompleteDropdown.js +2 -3
- package/dist/components/AutocompleteFormField.cjs +1 -2
- package/dist/components/AutocompleteFormField.cjs.map +1 -1
- package/dist/components/AutocompleteFormField.js +2 -3
- package/dist/components/BriefingDiff.js +1 -1
- package/dist/components/CarouselRenderer.js +1 -1
- package/dist/components/ChartJSRenderer.js +1 -1
- package/dist/components/ChatPrompt.js +1 -1
- package/dist/components/CodeBlockRenderer.js +1 -1
- package/dist/components/ComponentToolbar.js +1 -1
- package/dist/components/DataPreviewSection.js +1 -1
- package/dist/components/DegradedFallback.cjs.map +1 -1
- package/dist/components/DegradedFallback.d.ts +1 -1
- package/dist/components/DegradedFallback.js +1 -1
- package/dist/components/DegradedFallback.js.map +1 -1
- package/dist/components/DraggableGridItem.cjs +1 -2
- package/dist/components/DraggableGridItem.cjs.map +1 -1
- package/dist/components/DraggableGridItem.js +2 -3
- package/dist/components/EditableUIResourceRenderer.cjs +1 -2
- package/dist/components/EditableUIResourceRenderer.cjs.map +1 -1
- package/dist/components/EditableUIResourceRenderer.js +2 -3
- package/dist/components/ExpandableWrapper.js +2 -2
- package/dist/components/FeedbackInline.js +1 -1
- package/dist/components/FooterRenderer.js +1 -1
- package/dist/components/FormFieldRenderer.js +1 -1
- package/dist/components/FormRenderer.js +1 -1
- package/dist/components/GenerativeUIErrorBoundary.js +1 -1
- package/dist/components/GhostText.cjs +1 -2
- package/dist/components/GhostText.cjs.map +1 -1
- package/dist/components/GhostText.js +2 -3
- package/dist/components/GraphRenderer.cjs +2 -19
- package/dist/components/GraphRenderer.cjs.map +1 -1
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +2 -19
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/components/GridRenderer.cjs +1 -2
- package/dist/components/GridRenderer.cjs.map +1 -1
- package/dist/components/GridRenderer.js +2 -3
- package/dist/components/ImageGalleryRenderer.js +1 -1
- package/dist/components/LightboxOverlay.js +1 -1
- package/dist/components/MapRenderer.cjs +10 -11
- package/dist/components/MapRenderer.cjs.map +1 -1
- package/dist/components/MapRenderer.d.ts +6 -1
- package/dist/components/MapRenderer.d.ts.map +1 -1
- package/dist/components/MapRenderer.js +7 -8
- package/dist/components/MapRenderer.js.map +1 -1
- package/dist/components/ModalRenderer.js +1 -1
- package/dist/components/PortalDropdownMenu.js +1 -1
- package/dist/components/PresentationFeedback.js +1 -1
- package/dist/components/RenderContext.js +1 -1
- package/dist/components/ResizeHandle.cjs +1 -2
- package/dist/components/ResizeHandle.cjs.map +1 -1
- package/dist/components/ResizeHandle.js +2 -3
- package/dist/components/ScratchpadPanel.js +1 -1
- package/dist/components/SplitStepper.js +1 -1
- package/dist/components/StreamingUIRenderer.js +1 -1
- package/dist/components/UIResourceRenderer.cjs +12 -1
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +13 -2
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/VerifiedText.js +1 -1
- package/dist/components/VideoRenderer.js +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/core/component.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/core/component.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/axis.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/axis.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/constant.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/constant.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/grid.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/grid.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/labels.cjs +6 -6
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/labels.js +6 -6
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/line.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/line.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/ticks.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/ticks.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/title.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/title.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/utils.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/axis/guides/utils.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/grid/index.cjs +3 -3
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/grid/index.js +3 -3
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/indicator/indicator.cjs +4 -4
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/indicator/indicator.js +4 -4
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/category/item.cjs +5 -5
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/category/item.js +5 -5
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/category/items.cjs +5 -5
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/category/items.js +5 -5
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/category.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/category.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/continuous/handle.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/continuous/handle.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/title/index.cjs +3 -3
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/legend/title/index.js +3 -3
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/marker/utils.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/marker/utils.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/navigator/index.cjs +5 -5
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/navigator/index.js +5 -5
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/poptip/index.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/poptip/index.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/select/option.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/select/option.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/select/select.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/select/select.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/slider/handle.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/slider/handle.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/slider/index.cjs +4 -4
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/slider/index.js +4 -4
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/sparkline/columns.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/sparkline/columns.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/sparkline/index.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/sparkline/index.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/sparkline/lines.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/sparkline/lines.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/sparkline/utils.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/sparkline/utils.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/timebar/controller.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/timebar/controller.js +2 -2
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/timebar/handle.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/timebar/handle.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/timebar/icons.cjs +4 -4
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/timebar/icons.js +4 -4
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/timebar/timebar.cjs +3 -3
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/timebar/timebar.js +3 -3
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/tooltip/index.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/ui/tooltip/index.js +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/util/selection.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_component@2.1.11/node_modules/@antv/component/esm/util/selection.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g-lite@2.7.0/node_modules/@antv/g-lite/dist/index.esm.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/behaviors/scroll-canvas.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/behaviors/scroll-canvas.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/elements/combos/base-combo.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/elements/combos/base-combo.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/elements/edges/base-edge.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/elements/edges/base-edge.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/index.cjs +58 -58
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/plugins/legend.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/plugins/legend.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/plugins/minimap/index.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/plugins/minimap/index.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/plugins/snapline/index.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/plugins/snapline/index.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/plugins/tooltip.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/plugins/tooltip.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/registry/build-in.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/registry/build-in.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/data.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/data.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/element.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/element.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/graph.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/graph.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/layout.cjs +2 -2
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/layout.js +2 -2
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/viewport.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/runtime/viewport.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/utils/element.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/utils/element.js +1 -1
- package/dist/node_modules/.pnpm/@antv_g6@5.1.0/node_modules/@antv/g6/esm/utils/point.js +1 -1
- package/dist/node_modules/.pnpm/@antv_layout@2.0.0/node_modules/@antv/layout/lib/algorithm/antv-dagre/rank/index.js +1 -1
- package/dist/node_modules/.pnpm/@antv_layout@2.0.0/node_modules/@antv/layout/lib/algorithm/concentric/index.js +1 -1
- package/dist/node_modules/.pnpm/@antv_scale@0.4.16/node_modules/@antv/scale/esm/scales/continuous.cjs +1 -1
- package/dist/node_modules/.pnpm/@antv_scale@0.4.16/node_modules/@antv/scale/esm/scales/continuous.js +1 -1
- package/dist/node_modules/.pnpm/@tanstack_solid-virtual@3.13.18_solid-js@1.9.11/node_modules/@tanstack/solid-virtual/dist/esm/index.cjs +13 -0
- package/dist/node_modules/.pnpm/@tanstack_solid-virtual@3.13.18_solid-js@1.9.11/node_modules/@tanstack/solid-virtual/dist/esm/index.cjs.map +1 -1
- package/dist/node_modules/.pnpm/@tanstack_solid-virtual@3.13.18_solid-js@1.9.11/node_modules/@tanstack/solid-virtual/dist/esm/index.js +15 -2
- package/dist/node_modules/.pnpm/@tanstack_solid-virtual@3.13.18_solid-js@1.9.11/node_modules/@tanstack/solid-virtual/dist/esm/index.js.map +1 -1
- package/dist/node_modules/.pnpm/@tanstack_virtual-core@3.13.18/node_modules/@tanstack/virtual-core/dist/esm/index.cjs +64 -0
- package/dist/node_modules/.pnpm/@tanstack_virtual-core@3.13.18/node_modules/@tanstack/virtual-core/dist/esm/index.cjs.map +1 -1
- package/dist/node_modules/.pnpm/@tanstack_virtual-core@3.13.18/node_modules/@tanstack/virtual-core/dist/esm/index.js +66 -2
- package/dist/node_modules/.pnpm/@tanstack_virtual-core@3.13.18/node_modules/@tanstack/virtual-core/dist/esm/index.js.map +1 -1
- package/dist/node_modules/.pnpm/@tanstack_virtual-core@3.13.18/node_modules/@tanstack/virtual-core/dist/esm/utils.cjs +1 -1
- package/dist/node_modules/.pnpm/@tanstack_virtual-core@3.13.18/node_modules/@tanstack/virtual-core/dist/esm/utils.cjs.map +1 -1
- package/dist/node_modules/.pnpm/@tanstack_virtual-core@3.13.18/node_modules/@tanstack/virtual-core/dist/esm/utils.js +1 -1
- package/dist/node_modules/.pnpm/@tanstack_virtual-core@3.13.18/node_modules/@tanstack/virtual-core/dist/esm/utils.js.map +1 -1
- package/dist/node_modules/.pnpm/color-string@1.9.1/node_modules/color-string/index.cjs +6 -6
- package/dist/node_modules/.pnpm/{dompurify@3.4.1 → dompurify@3.4.13}/node_modules/dompurify/dist/purify.es.cjs +671 -233
- package/dist/node_modules/.pnpm/dompurify@3.4.13/node_modules/dompurify/dist/purify.es.cjs.map +1 -0
- package/dist/node_modules/.pnpm/{dompurify@3.4.1 → dompurify@3.4.13}/node_modules/dompurify/dist/purify.es.js +671 -233
- package/dist/node_modules/.pnpm/dompurify@3.4.13/node_modules/dompurify/dist/purify.es.js.map +1 -0
- package/dist/node_modules/.pnpm/leaflet.markercluster@1.5.3_leaflet@1.9.4/node_modules/leaflet.markercluster/dist/leaflet.markercluster-src.cjs +7 -7
- package/dist/node_modules/.pnpm/leaflet.markercluster@1.5.3_leaflet@1.9.4/node_modules/leaflet.markercluster/dist/leaflet.markercluster-src.cjs.map +1 -1
- package/dist/node_modules/.pnpm/leaflet.markercluster@1.5.3_leaflet@1.9.4/node_modules/leaflet.markercluster/dist/leaflet.markercluster-src.js +7 -7
- package/dist/node_modules/.pnpm/leaflet.markercluster@1.5.3_leaflet@1.9.4/node_modules/leaflet.markercluster/dist/leaflet.markercluster-src.js.map +1 -1
- package/dist/node_modules/.pnpm/leaflet@1.9.4/node_modules/leaflet/dist/leaflet-src.cjs +83 -83
- package/dist/node_modules/.pnpm/leaflet@1.9.4/node_modules/leaflet/dist/leaflet-src.cjs.map +1 -1
- package/dist/node_modules/.pnpm/leaflet@1.9.4/node_modules/leaflet/dist/leaflet-src.js +83 -83
- package/dist/node_modules/.pnpm/leaflet@1.9.4/node_modules/leaflet/dist/leaflet-src.js.map +1 -1
- package/dist/plugins/groq.cjs +1 -2
- package/dist/plugins/groq.cjs.map +1 -1
- package/dist/plugins/groq.js +1 -2
- package/dist/plugins/rest.cjs +1 -2
- package/dist/plugins/rest.cjs.map +1 -1
- package/dist/plugins/rest.js +1 -2
- package/dist/plugins/supabase.cjs +1 -2
- package/dist/plugins/supabase.cjs.map +1 -1
- package/dist/plugins/supabase.js +1 -2
- package/dist/services/component-registry.cjs +223 -7
- package/dist/services/component-registry.cjs.map +1 -1
- package/dist/services/component-registry.d.ts +0 -3
- package/dist/services/component-registry.d.ts.map +1 -1
- package/dist/services/component-registry.js +223 -7
- package/dist/services/component-registry.js.map +1 -1
- package/dist/services/validation.cjs +1 -23
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +2 -24
- package/dist/services/validation.js.map +1 -1
- package/dist/types/index.d.ts +12 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types.d.cts +12 -6
- package/dist/types.d.ts +12 -6
- package/dist/utils/escape-html.cjs +10 -0
- package/dist/utils/escape-html.cjs.map +1 -0
- package/dist/utils/escape-html.d.ts +13 -0
- package/dist/utils/escape-html.d.ts.map +1 -0
- package/dist/utils/escape-html.js +10 -0
- package/dist/utils/escape-html.js.map +1 -0
- package/docs/briefs/BRIEF-graph-component-g6.md +10 -0
- package/package.json +2 -2
- package/src/components/DegradedFallback.tsx +1 -1
- package/src/components/GraphRenderer.tsx +1 -19
- package/src/components/MapRenderer.security.test.ts +55 -2
- package/src/components/MapRenderer.tsx +15 -13
- package/src/components/UIResourceRenderer.tsx +8 -0
- package/src/components/UnsupportedComponent.test.tsx +28 -1
- package/src/components/index.ts +3 -0
- package/src/hooks/useStreamingUI.test.ts +194 -0
- package/src/index.ts +1 -0
- package/src/services/component-registry.test.ts +104 -2
- package/src/services/component-registry.ts +236 -7
- package/src/services/validation.test.ts +26 -0
- package/src/services/validation.ts +12 -24
- package/src/types/index.ts +12 -26
- package/src/types/map-types.test.ts +20 -0
- package/src/utils/escape-html.test.ts +30 -0
- package/src/utils/escape-html.ts +24 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/_virtual/leaflet.markercluster-src2.cjs.map +0 -1
- package/dist/_virtual/leaflet.markercluster-src2.js.map +0 -1
- package/dist/node_modules/.pnpm/dompurify@3.4.1/node_modules/dompurify/dist/purify.es.cjs.map +0 -1
- package/dist/node_modules/.pnpm/dompurify@3.4.1/node_modules/dompurify/dist/purify.es.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapRenderer.cjs","sources":["../../src/components/MapRenderer.tsx"],"sourcesContent":["/**\n * MapRenderer - Interactive map Component\n * Sprint 6: Markers + clustering\n * v3.1.0: GeoJSON, choropleth, popups, multi-layer, PMTiles\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js';\nimport { isServer } from 'solid-js/web';\nimport type {\n UIComponent,\n MapComponentParams,\n MapClusterOptions,\n MapGeoJSONStyle,\n MapPopupConfig,\n MapLayer,\n MapPMTilesConfig,\n} from '../types';\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper';\nimport { DegradedFallback } from './DegradedFallback';\nimport { mapToDegradedTable } from '../utils/degraded-projections';\nimport { useTelemetry } from '../context/MCPUITelemetryContext';\n\n// Lazy load leaflet (it doesn't support SSR well)\nlet L: any = null;\n// Track if marker cluster CSS has been loaded\nlet clusterCssLoaded = false;\n\nexport interface MapRendererProps {\n /**\n * UIComponent containing map params\n */\n component?: UIComponent;\n\n /**\n * Direct map params\n */\n params?: MapComponentParams;\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible';\n\n /**\n * Trust marker / popup content as raw HTML (v6.10.0, audit P1.2).\n *\n * Leaflet renders bound tooltip/popup strings as HTML, so `marker.tooltip`,\n * `marker.popup` and a GeoJSON `popup.template` are XSS vectors when the\n * payload is untrusted (the default for an LLM/connector-driven public\n * package). **Default `false`** → those are escaped as plain text, and\n * `popup.template` is ignored in favour of the safe auto-generated popup.\n *\n * This is a **host-level** trust decision, deliberately NOT a payload field\n * (a malicious payload could just set its own flag). The\n * `<UIResourceRenderer>` path never sets it, so payload-driven maps are\n * always text-safe. A host rendering `<MapRenderer>` directly with trusted\n * data may set `allowHtmlPopups` to restore rich HTML popups. The\n * auto-generated popup (`titleField` / `fields`) is safe-by-construction\n * and unaffected either way.\n */\n allowHtmlPopups?: boolean;\n}\n\n// ─── Helpers ────────────────────────────────────────────────\n\n/**\n * Resolve choropleth color for a feature based on property value and scale stops.\n */\nfunction getChoroplethColor(\n value: unknown,\n scale: Array<[number, string]>,\n fallback: string\n): string {\n if (value == null || typeof value !== 'number' || !isFinite(value)) return fallback;\n\n // Scale is sorted ascending: [[0, '#eff3ff'], [100, '#084594']]\n if (scale.length === 0) return fallback;\n if (value <= scale[0][0]) return scale[0][1];\n if (value >= scale[scale.length - 1][0]) return scale[scale.length - 1][1];\n\n // Find surrounding stops and interpolate (use upper bracket color)\n for (let i = 1; i < scale.length; i++) {\n if (value <= scale[i][0]) return scale[i][1];\n }\n return scale[scale.length - 1][1];\n}\n\n/**\n * Build a Leaflet style function from MapGeoJSONStyle config.\n */\nfunction buildStyleFn(\n style: MapGeoJSONStyle | undefined\n): (feature: any) => Record<string, unknown> {\n if (!style) {\n return () => ({\n fillColor: '#3388ff',\n fillOpacity: 0.6,\n color: '#333',\n weight: 1,\n opacity: 1,\n });\n }\n\n return (feature: any) => {\n let fillColor = style.fillColor || '#3388ff';\n\n // Choropleth: override fillColor based on feature property\n if (style.choroplethField && style.choroplethScale && feature?.properties) {\n const val = feature.properties[style.choroplethField];\n fillColor = getChoroplethColor(\n val,\n style.choroplethScale,\n style.choroplethFallback || '#ccc'\n );\n }\n\n return {\n fillColor,\n fillOpacity: style.fillOpacity ?? 0.6,\n color: style.strokeColor || '#333',\n weight: style.strokeWeight ?? 1,\n opacity: style.strokeOpacity ?? 1,\n };\n };\n}\n\n/**\n * Build popup HTML from a feature's properties using popup config.\n *\n * `allowHtml` (audit P1.2) gates the raw-HTML `popup.template`: it is honored\n * only when the host trusts the payload. On the default (untrusted) path the\n * template is ignored and we fall through to the auto-generated popup, whose\n * structure is renderer-authored and whose values are always escaped — safe\n * by construction. Even in the trusted path, substituted `{{prop}}` values\n * are escaped (they are data, not markup).\n */\nexport function buildPopupContent(\n feature: any,\n popup: MapPopupConfig | undefined,\n allowHtml = false\n): string | null {\n if (!popup || !feature?.properties) return null;\n const props = feature.properties;\n\n // Custom template — raw HTML, so trusted-host only.\n if (allowHtml && popup.template) {\n return popup.template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\n const val = props[key];\n return val != null ? escapeHtml(String(val)) : '';\n });\n }\n\n // Auto-generated popup\n const parts: string[] = [];\n\n if (popup.titleField && props[popup.titleField] != null) {\n parts.push(`<strong>${escapeHtml(String(props[popup.titleField]))}</strong>`);\n }\n\n const fields = popup.fields || Object.keys(props).slice(0, 8);\n for (const key of fields) {\n if (key === popup.titleField) continue;\n const val = props[key];\n if (val == null) continue;\n const formatted = typeof val === 'number' ? val.toLocaleString('fr-FR') : String(val);\n parts.push(\n `<span style=\"color:#666;font-size:11px\">${escapeHtml(key)}</span>: ${escapeHtml(formatted)}`\n );\n }\n\n return parts.join('<br/>');\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\n/**\n * Resolve a marker's tooltip/popup string for binding (audit P1.2). Leaflet\n * renders bound strings as HTML; `marker.tooltip` / `marker.popup` come from\n * the (untrusted) payload, so they are escaped to plain text unless the host\n * has opted into raw HTML via `allowHtmlPopups`. Pure + exported for tests.\n */\nexport function popupSafeText(value: string | undefined, allowHtml = false): string | undefined {\n if (value == null) return undefined;\n return allowHtml ? value : escapeHtml(value);\n}\n\n/** Bind a marker's tooltip + popup, escaping by default (see popupSafeText). */\nexport function bindMarkerContent(\n m: any,\n marker: { tooltip?: string; popup?: string },\n allowHtml: boolean\n): void {\n const tooltip = popupSafeText(marker.tooltip, allowHtml);\n if (tooltip) m.bindTooltip(tooltip);\n const popup = popupSafeText(marker.popup, allowHtml);\n if (popup) m.bindPopup(popup);\n}\n\n/**\n * Add a GeoJSON layer to the map with style and popup support.\n * Returns the layer for bounds calculation.\n */\nfunction addGeoJSONLayer(\n mapInst: any,\n leaflet: any,\n geojson: unknown,\n style?: MapGeoJSONStyle,\n popup?: MapPopupConfig\n): any {\n const styleFn = buildStyleFn(style);\n\n const layer = leaflet.geoJSON(geojson, {\n style: styleFn,\n pointToLayer: (feature: any, latlng: any) => {\n // Render points as circle markers for consistency\n const s = styleFn(feature);\n return leaflet.circleMarker(latlng, {\n radius: 6,\n fillColor: s.fillColor,\n fillOpacity: s.fillOpacity,\n color: s.color,\n weight: s.weight,\n opacity: s.opacity,\n });\n },\n onEachFeature: (feature: any, featureLayer: any) => {\n const html = buildPopupContent(feature, popup);\n if (html) {\n featureLayer.bindPopup(html, { maxWidth: 300 });\n }\n },\n });\n\n layer.addTo(mapInst);\n return layer;\n}\n\n// ─── Component ──────────────────────────────────────────────\n\n/**\n * Build a GeoJSON FeatureCollection from the map's `markers` (and any\n * inlined GeoJSON layers, when present). Used by the \"Copy data\" button\n * shipped via `<ExpandableWrapper>` (v6.2.0). Best-effort — clusters,\n * tile layers, and choropleth-only data don't get round-tripped.\n */\nfunction mapToGeoJSON(p: MapComponentParams | undefined): string {\n if (!p) return '{\"type\":\"FeatureCollection\",\"features\":[]}';\n const features: any[] = [];\n for (const marker of p.markers ?? []) {\n const pos: any = marker.position as any;\n // Accept both [lat, lng] tuple and {lat, lng} object shapes (v5.0.2 spec)\n const lat = Array.isArray(pos) ? pos[0] : pos?.lat;\n const lng = Array.isArray(pos) ? pos[1] : pos?.lng;\n if (typeof lat !== 'number' || typeof lng !== 'number') continue;\n features.push({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [lng, lat] },\n properties: {\n ...(marker.tooltip ? { tooltip: marker.tooltip } : {}),\n ...(marker.popup ? { popup: marker.popup } : {}),\n },\n });\n }\n return JSON.stringify({ type: 'FeatureCollection', features }, null, 2);\n}\n\nexport const MapRenderer: Component<MapRendererProps> = (props) => {\n let mapContainer: HTMLDivElement | undefined;\n let mapInstance: any = null;\n const [isLeafletLoaded, setIsLeafletLoaded] = createSignal(false);\n const [error, setError] = createSignal<string | null>(null);\n // PMTiles is an optional overlay on top of the base map. When it fails we\n // keep the base map but surface a visible notice (audit P1.3) instead of a\n // silent console.warn that leaves the user with an unexplained empty layer.\n const [pmtilesError, setPmtilesError] = createSignal<string | null>(null);\n const isExpanded = useExpanded();\n const telemetry = useTelemetry();\n // Host-level trust for raw HTML in marker/popup content (audit P1.2).\n // Default false → tooltip/popup escaped, GeoJSON `popup.template` ignored.\n const allowHtml = () => props.allowHtmlPopups === true;\n\n const params = () => props.params || (props.component?.params as MapComponentParams);\n\n // v6.2.0 — Leaflet has to be told to re-measure when its container\n // resizes (e.g. transitioning to fullscreen via ExpandableWrapper).\n // We give the DOM a tick to settle the new dimensions, then ask\n // Leaflet to reflow tiles.\n createEffect(() => {\n const expanded = isExpanded();\n if (!mapInstance) return;\n // Read the signal so the effect re-runs on toggle ; the value is\n // observed for its side effects on layout.\n void expanded;\n setTimeout(() => mapInstance?.invalidateSize?.(), 100);\n });\n\n // Initialize Map\n createEffect(async () => {\n if (isServer) return; // Don't run on server\n\n if (!L) {\n try {\n const module = await import('leaflet');\n L = module.default || module;\n await import('leaflet/dist/leaflet.css'); // Import CSS\n setIsLeafletLoaded(true);\n } catch (e) {\n console.warn('Failed to load leaflet', e);\n setError('Map library could not be loaded.');\n return;\n }\n } else {\n setIsLeafletLoaded(true);\n }\n\n if (isLeafletLoaded() && mapContainer && !mapInstance) {\n const p = params();\n const center = p?.center || [51.505, -0.09]; // Default to London\n const zoom = p?.zoom || 13;\n\n mapInstance = L.map(mapContainer, {\n zoomControl: p?.zoomControl !== false,\n scrollWheelZoom: p?.scrollWheelZoom !== false,\n attributionControl: false,\n }).setView(center, zoom);\n\n // Add OpenStreetMap tile layer\n const tileLayerUrl = p?.tileLayer || 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';\n L.tileLayer(tileLayerUrl, {\n attribution:\n p?.attribution ||\n '© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors',\n }).addTo(mapInstance);\n\n if (p?.attribution !== '') {\n L.control.attribution({ prefix: false }).addTo(mapInstance);\n }\n\n // Fix marker icons (Leaflet issue with bundlers)\n delete (L.Icon.Default.prototype as any)._getIconUrl;\n L.Icon.Default.mergeOptions({\n iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',\n iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',\n shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',\n });\n }\n\n // Update markers and view\n if (mapInstance && L) {\n try {\n const p = params();\n const allBoundsLayers: any[] = [];\n\n // Clear existing layers (markers, cluster groups, GeoJSON)\n mapInstance.eachLayer((layer: any) => {\n if (\n layer instanceof L.Marker ||\n layer instanceof L.GeoJSON ||\n layer instanceof L.CircleMarker ||\n layer._group ||\n layer._featureGroup\n ) {\n mapInstance.removeLayer(layer);\n }\n });\n\n // ─── Markers (legacy) ────────────────────────\n const markers: any[] = [];\n const shouldCluster = p?.clustering && p?.markers && p.markers.length > 0;\n\n if (shouldCluster) {\n try {\n await import('leaflet.markercluster');\n if (!clusterCssLoaded) {\n await import('leaflet.markercluster/dist/MarkerCluster.css');\n await import('leaflet.markercluster/dist/MarkerCluster.Default.css');\n clusterCssLoaded = true;\n }\n const clusterOpts: MapClusterOptions =\n typeof p.clustering === 'object' ? p.clustering : {};\n const clusterGroup = (L as any).markerClusterGroup({\n maxClusterRadius: clusterOpts.maxClusterRadius ?? 80,\n spiderfyOnMaxZoom: clusterOpts.spiderfyOnMaxZoom ?? true,\n showCoverageOnHover: clusterOpts.showCoverageOnHover ?? true,\n disableClusteringAtZoom: clusterOpts.disableClusteringAtZoom,\n animate: clusterOpts.animateAddingMarkers ?? true,\n });\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position);\n bindMarkerContent(m, marker, allowHtml());\n clusterGroup.addLayer(m);\n markers.push(m);\n });\n mapInstance.addLayer(clusterGroup);\n } catch {\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position).addTo(mapInstance);\n bindMarkerContent(m, marker, allowHtml());\n markers.push(m);\n });\n }\n } else {\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position).addTo(mapInstance);\n bindMarkerContent(m, marker, allowHtml());\n markers.push(m);\n });\n }\n\n if (markers.length > 0) {\n allBoundsLayers.push(...markers);\n }\n\n // ─── GeoJSON (v3.1.0) ───────────────────────\n if (p?.geojson) {\n const geoLayer = addGeoJSONLayer(mapInstance, L, p.geojson, p.geojsonStyle, p.popup);\n allBoundsLayers.push(geoLayer);\n }\n\n // ─── Named layers (v3.1.0) ──────────────────\n if (p?.layers && p.layers.length > 0) {\n const overlays: Record<string, any> = {};\n\n for (const layerDef of p.layers) {\n const geoLayer = addGeoJSONLayer(\n mapInstance,\n L,\n layerDef.geojson,\n layerDef.style || p?.geojsonStyle,\n layerDef.popup || p?.popup\n );\n\n overlays[layerDef.name] = geoLayer;\n allBoundsLayers.push(geoLayer);\n\n // Respect initial visibility\n if (layerDef.visible === false) {\n mapInstance.removeLayer(geoLayer);\n }\n }\n\n // Add layer control if multiple layers\n if (Object.keys(overlays).length > 1) {\n L.control.layers(null, overlays, { collapsed: true }).addTo(mapInstance);\n }\n }\n\n // ─── PMTiles (v3.1.0) ────────────────────────\n setPmtilesError(null);\n if (p?.pmtiles) {\n try {\n // @ts-ignore — optional peer dependency, may not be installed\n const protomaps = await import(/* @vite-ignore */ 'protomaps-leaflet');\n const pmConfig = p.pmtiles;\n\n const paintRules =\n pmConfig.paintRules?.map((rule) => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any)[\n rule.symbolizer === 'polygon'\n ? 'PolygonSymbolizer'\n : rule.symbolizer === 'line'\n ? 'LineSymbolizer'\n : 'CircleSymbolizer'\n ]({\n fill: rule.color || '#3388ff',\n stroke: rule.color || '#333',\n width: rule.width ?? 1,\n opacity: rule.opacity ?? 0.6,\n }),\n })) || [];\n\n const labelRules =\n pmConfig.labelRules?.map((rule) => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any).TextSymbolizer({\n label_props: [rule.textField],\n fontSize: rule.fontSize ?? 12,\n }),\n })) || [];\n\n const pmLayer = (protomaps as any).leafletLayer({\n url: pmConfig.url,\n attribution: pmConfig.attribution,\n paintRules,\n labelRules,\n maxZoom: pmConfig.maxZoom,\n minZoom: pmConfig.minZoom,\n });\n\n pmLayer.addTo(mapInstance);\n } catch (e) {\n // P1.3 — do NOT fail silently. Keep the base map, but surface a\n // visible notice and report a renderer error via telemetry. The\n // most common cause is the optional `protomaps-leaflet` peer not\n // being installed.\n const detail = e instanceof Error ? e.message : String(e);\n const message =\n 'PMTiles layer unavailable — the optional \"protomaps-leaflet\" ' +\n 'peer dependency failed to load or render.';\n console.warn('[MCP-UI] ' + message, e);\n setPmtilesError(message);\n telemetry?.dispatch({\n type: 'render:error',\n errorMessage: `${message} (${detail})`,\n id: props.component?.id ?? '',\n componentType: 'map',\n ts: Date.now(),\n });\n }\n }\n\n // ─── Fit bounds ─────────────────────────────\n if (p?.fitBounds && allBoundsLayers.length > 0) {\n const group = L.featureGroup(allBoundsLayers);\n const bounds = group.getBounds();\n if (bounds.isValid()) {\n mapInstance.fitBounds(bounds.pad(0.1));\n }\n } else if (p?.center) {\n mapInstance.setView(p.center, p.zoom || mapInstance.getZoom());\n }\n } catch (err) {\n // Fallback ladder (P2.5): a Leaflet drawing failure degrades to\n // the coordinate table below instead of a blank/partial map.\n const message = err instanceof Error ? err.message : 'Failed to render map';\n setError(message);\n telemetry?.dispatch({\n type: 'render:error',\n errorMessage: message,\n id: props.component?.id ?? '',\n componentType: 'map',\n ts: Date.now(),\n });\n }\n }\n });\n\n // Cleanup\n onCleanup(() => {\n if (mapInstance) {\n mapInstance.remove();\n mapInstance = null;\n }\n });\n\n return (\n <ExpandableWrapper\n title={'Map'}\n copyData={mapToGeoJSON(params())}\n copyLabel=\"Copy markers as GeoJSON\"\n toolbarVariant={props.toolbarVariant}\n >\n <div\n class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${params()?.className || ''} ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}\n >\n <Show when={error()}>\n {/* Fallback ladder (P2.5): degrade to a coordinate table\n rather than a bare error string. */}\n <div class=\"p-3\">\n <DegradedFallback\n message={`Map rendering failed: ${error()}`}\n caption=\"Showing the map data as a coordinate table — the interactive map is unavailable.\"\n {...mapToDegradedTable(params() ?? {})}\n />\n </div>\n </Show>\n <Show when={!error()}>\n {/* P1.3 — visible notice when the PMTiles overlay fails but the\n base map is still usable. */}\n <Show when={pmtilesError()}>\n <div\n role=\"alert\"\n class=\"m-2 rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200\"\n >\n {pmtilesError()} The base map is still shown.\n </div>\n </Show>\n <div\n ref={mapContainer}\n style={\n isExpanded()\n ? { height: '100%', width: '100%', 'z-index': 0 }\n : { height: params()?.height || '400px', width: '100%', 'z-index': 0 }\n }\n class={`relative z-0 ${isExpanded() ? 'flex-1 min-h-0' : ''}`}\n />\n </Show>\n </div>\n </ExpandableWrapper>\n );\n};\n"],"names":["L","clusterCssLoaded","getChoroplethColor","value","scale","fallback","isFinite","length","i","buildStyleFn","style","fillColor","fillOpacity","color","weight","opacity","feature","choroplethField","choroplethScale","properties","val","choroplethFallback","strokeColor","strokeWeight","strokeOpacity","buildPopupContent","popup","allowHtml","props","template","replace","_","key","escapeHtml","String","parts","titleField","push","fields","Object","keys","slice","formatted","toLocaleString","join","str","popupSafeText","undefined","bindMarkerContent","m","marker","tooltip","bindTooltip","bindPopup","addGeoJSONLayer","mapInst","leaflet","geojson","styleFn","layer","geoJSON","pointToLayer","latlng","s","circleMarker","radius","onEachFeature","featureLayer","html","maxWidth","addTo","mapToGeoJSON","p","features","markers","pos","position","lat","Array","isArray","lng","type","geometry","coordinates","JSON","stringify","MapRenderer","mapContainer","mapInstance","isLeafletLoaded","setIsLeafletLoaded","createSignal","error","setError","pmtilesError","setPmtilesError","isExpanded","useExpanded","telemetry","useTelemetry","allowHtmlPopups","params","component","createEffect","setTimeout","invalidateSize","isServer","module","default","e","console","warn","center","zoom","map","zoomControl","scrollWheelZoom","attributionControl","setView","tileLayerUrl","tileLayer","attribution","control","prefix","Icon","Default","prototype","_getIconUrl","mergeOptions","iconRetinaUrl","iconUrl","shadowUrl","allBoundsLayers","eachLayer","Marker","GeoJSON","CircleMarker","_group","_featureGroup","removeLayer","shouldCluster","clustering","clusterOpts","clusterGroup","markerClusterGroup","maxClusterRadius","spiderfyOnMaxZoom","showCoverageOnHover","disableClusteringAtZoom","animate","animateAddingMarkers","forEach","addLayer","geoLayer","geojsonStyle","layers","overlays","layerDef","name","visible","collapsed","pmtiles","protomaps","pmConfig","paintRules","rule","dataLayer","symbolizer","fill","stroke","width","labelRules","TextSymbolizer","label_props","textField","fontSize","pmLayer","leafletLayer","url","maxZoom","minZoom","detail","Error","message","dispatch","errorMessage","id","componentType","ts","Date","now","fitBounds","group","featureGroup","bounds","getBounds","isValid","pad","getZoom","err","onCleanup","remove","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$2","_$getNextMarker","nextSibling","_el$0","_el$1","_co$3","_$insert","Show","when","_el$2","_tmpl$","DegradedFallback","_$mergeProps","caption","mapToDegradedTable","_el$3","_tmpl$2","_el$5","_el$6","_co$","_el$7","_tmpl$3","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","_$style","t","_$className","className"],"mappings":";;;;;;;;;AAuBA,IAAIA,IAAS;AAEb,IAAIC,mBAAmB;AA4CvB,SAASC,mBACPC,OACAC,OACAC,UACQ;AACR,MAAIF,SAAS,QAAQ,OAAOA,UAAU,YAAY,CAACG,SAASH,KAAK,EAAG,QAAOE;AAG3E,MAAID,MAAMG,WAAW,EAAG,QAAOF;AAC/B,MAAIF,SAASC,MAAM,CAAC,EAAE,CAAC,EAAG,QAAOA,MAAM,CAAC,EAAE,CAAC;AAC3C,MAAID,SAASC,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC,EAAG,QAAOH,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC;AAGzE,WAASC,IAAI,GAAGA,IAAIJ,MAAMG,QAAQC,KAAK;AACrC,QAAIL,SAASC,MAAMI,CAAC,EAAE,CAAC,EAAG,QAAOJ,MAAMI,CAAC,EAAE,CAAC;AAAA,EAC7C;AACA,SAAOJ,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC;AAClC;AAKA,SAASE,aACPC,OAC2C;AAC3C,MAAI,CAACA,OAAO;AACV,WAAO,OAAO;AAAA,MACZC,WAAW;AAAA,MACXC,aAAa;AAAA,MACbC,OAAO;AAAA,MACPC,QAAQ;AAAA,MACRC,SAAS;AAAA,IAAA;AAAA,EAEb;AAEA,SAAO,CAACC,YAAiB;AACvB,QAAIL,YAAYD,MAAMC,aAAa;AAGnC,QAAID,MAAMO,mBAAmBP,MAAMQ,oBAAmBF,mCAASG,aAAY;AACzE,YAAMC,MAAMJ,QAAQG,WAAWT,MAAMO,eAAe;AACpDN,kBAAYT,mBACVkB,KACAV,MAAMQ,iBACNR,MAAMW,sBAAsB,MAC9B;AAAA,IACF;AAEA,WAAO;AAAA,MACLV;AAAAA,MACAC,aAAaF,MAAME,eAAe;AAAA,MAClCC,OAAOH,MAAMY,eAAe;AAAA,MAC5BR,QAAQJ,MAAMa,gBAAgB;AAAA,MAC9BR,SAASL,MAAMc,iBAAiB;AAAA,IAAA;AAAA,EAEpC;AACF;AAYO,SAASC,kBACdT,SACAU,OACAC,YAAY,OACG;AACf,MAAI,CAACD,SAAS,EAACV,mCAASG,YAAY,QAAO;AAC3C,QAAMS,QAAQZ,QAAQG;AAGtB,MAAIQ,aAAaD,MAAMG,UAAU;AAC/B,WAAOH,MAAMG,SAASC,QAAQ,kBAAkB,CAACC,GAAGC,QAAQ;AAC1D,YAAMZ,MAAMQ,MAAMI,GAAG;AACrB,aAAOZ,OAAO,OAAOa,WAAWC,OAAOd,GAAG,CAAC,IAAI;AAAA,IACjD,CAAC;AAAA,EACH;AAGA,QAAMe,QAAkB,CAAA;AAExB,MAAIT,MAAMU,cAAcR,MAAMF,MAAMU,UAAU,KAAK,MAAM;AACvDD,UAAME,KAAK,WAAWJ,WAAWC,OAAON,MAAMF,MAAMU,UAAU,CAAC,CAAC,CAAC,WAAW;AAAA,EAC9E;AAEA,QAAME,SAASZ,MAAMY,UAAUC,OAAOC,KAAKZ,KAAK,EAAEa,MAAM,GAAG,CAAC;AAC5D,aAAWT,OAAOM,QAAQ;AACxB,QAAIN,QAAQN,MAAMU,WAAY;AAC9B,UAAMhB,MAAMQ,MAAMI,GAAG;AACrB,QAAIZ,OAAO,KAAM;AACjB,UAAMsB,YAAY,OAAOtB,QAAQ,WAAWA,IAAIuB,eAAe,OAAO,IAAIT,OAAOd,GAAG;AACpFe,UAAME,KACJ,2CAA2CJ,WAAWD,GAAG,CAAC,YAAYC,WAAWS,SAAS,CAAC,EAC7F;AAAA,EACF;AAEA,SAAOP,MAAMS,KAAK,OAAO;AAC3B;AAEA,SAASX,WAAWY,KAAqB;AACvC,SAAOA,IACJf,QAAQ,MAAM,OAAO,EACrBA,QAAQ,MAAM,MAAM,EACpBA,QAAQ,MAAM,MAAM,EACpBA,QAAQ,MAAM,QAAQ;AAC3B;AAQO,SAASgB,cAAc3C,OAA2BwB,YAAY,OAA2B;AAC9F,MAAIxB,SAAS,KAAM,QAAO4C;AAC1B,SAAOpB,YAAYxB,QAAQ8B,WAAW9B,KAAK;AAC7C;AAGO,SAAS6C,kBACdC,GACAC,QACAvB,WACM;AACN,QAAMwB,UAAUL,cAAcI,OAAOC,SAASxB,SAAS;AACvD,MAAIwB,QAASF,GAAEG,YAAYD,OAAO;AAClC,QAAMzB,QAAQoB,cAAcI,OAAOxB,OAAOC,SAAS;AACnD,MAAID,MAAOuB,GAAEI,UAAU3B,KAAK;AAC9B;AAMA,SAAS4B,gBACPC,SACAC,SACAC,SACA/C,OACAgB,OACK;AACL,QAAMgC,UAAUjD,aAAaC,KAAK;AAElC,QAAMiD,QAAQH,QAAQI,QAAQH,SAAS;AAAA,IACrC/C,OAAOgD;AAAAA,IACPG,cAAcA,CAAC7C,SAAc8C,WAAgB;AAE3C,YAAMC,IAAIL,QAAQ1C,OAAO;AACzB,aAAOwC,QAAQQ,aAAaF,QAAQ;AAAA,QAClCG,QAAQ;AAAA,QACRtD,WAAWoD,EAAEpD;AAAAA,QACbC,aAAamD,EAAEnD;AAAAA,QACfC,OAAOkD,EAAElD;AAAAA,QACTC,QAAQiD,EAAEjD;AAAAA,QACVC,SAASgD,EAAEhD;AAAAA,MAAAA,CACZ;AAAA,IACH;AAAA,IACAmD,eAAeA,CAAClD,SAAcmD,iBAAsB;AAClD,YAAMC,OAAO3C,kBAAkBT,SAASU,KAAK;AAC7C,UAAI0C,MAAM;AACRD,qBAAad,UAAUe,MAAM;AAAA,UAAEC,UAAU;AAAA,QAAA,CAAK;AAAA,MAChD;AAAA,IACF;AAAA,EAAA,CACD;AAEDV,QAAMW,MAAMf,OAAO;AACnB,SAAOI;AACT;AAUA,SAASY,aAAaC,GAA2C;AAC/D,MAAI,CAACA,EAAG,QAAO;AACf,QAAMC,WAAkB,CAAA;AACxB,aAAWvB,UAAUsB,EAAEE,WAAW,CAAA,GAAI;AACpC,UAAMC,MAAWzB,OAAO0B;AAExB,UAAMC,MAAMC,MAAMC,QAAQJ,GAAG,IAAIA,IAAI,CAAC,IAAIA,2BAAKE;AAC/C,UAAMG,MAAMF,MAAMC,QAAQJ,GAAG,IAAIA,IAAI,CAAC,IAAIA,2BAAKK;AAC/C,QAAI,OAAOH,QAAQ,YAAY,OAAOG,QAAQ,SAAU;AACxDP,aAASpC,KAAK;AAAA,MACZ4C,MAAM;AAAA,MACNC,UAAU;AAAA,QAAED,MAAM;AAAA,QAASE,aAAa,CAACH,KAAKH,GAAG;AAAA,MAAA;AAAA,MACjD1D,YAAY;AAAA,QACV,GAAI+B,OAAOC,UAAU;AAAA,UAAEA,SAASD,OAAOC;AAAAA,QAAAA,IAAY,CAAA;AAAA,QACnD,GAAID,OAAOxB,QAAQ;AAAA,UAAEA,OAAOwB,OAAOxB;AAAAA,QAAAA,IAAU,CAAA;AAAA,MAAC;AAAA,IAChD,CACD;AAAA,EACH;AACA,SAAO0D,KAAKC,UAAU;AAAA,IAAEJ,MAAM;AAAA,IAAqBR;AAAAA,EAAAA,GAAY,MAAM,CAAC;AACxE;AAEO,MAAMa,cAA4C1D,CAAAA,UAAU;AACjE,MAAI2D;AACJ,MAAIC,cAAmB;AACvB,QAAM,CAACC,iBAAiBC,kBAAkB,IAAIC,QAAAA,aAAa,KAAK;AAChE,QAAM,CAACC,OAAOC,QAAQ,IAAIF,QAAAA,aAA4B,IAAI;AAI1D,QAAM,CAACG,cAAcC,eAAe,IAAIJ,QAAAA,aAA4B,IAAI;AACxE,QAAMK,aAAaC,kBAAAA,YAAAA;AACnB,QAAMC,YAAYC,sBAAAA,aAAAA;AAGlB,QAAMxE,YAAYA,MAAMC,MAAMwE,oBAAoB;AAElD,QAAMC,SAASA,MAAAA;;AAAMzE,iBAAMyE,YAAWzE,WAAM0E,cAAN1E,mBAAiByE;AAAAA;AAMvDE,UAAAA,aAAa,MAAM;AACAP,eAAAA;AACjB,QAAI,CAACR,YAAa;AAIlBgB,eAAW,MAAA;;AAAMhB,8DAAaiB,mBAAbjB;AAAAA,OAAiC,GAAG;AAAA,EACvD,CAAC;AAGDe,UAAAA,aAAa,YAAY;;AACvB,QAAIG,aAAU;AAEd,QAAI,CAAC1G,GAAG;AACN,UAAI;AACF,cAAM2G,UAAS,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,6BAAS,CAAA,EAAA,KAAA,OAAA,EAAA,UAAA;AACrC3G,YAAI2G,QAAOC,WAAWD;AACtB,cAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,+EAA0B,CAAA;AACvCjB,2BAAmB,IAAI;AAAA,MACzB,SAASmB,GAAG;AACVC,gBAAQC,KAAK,0BAA0BF,CAAC;AACxChB,iBAAS,kCAAkC;AAC3C;AAAA,MACF;AAAA,IACF,OAAO;AACLH,yBAAmB,IAAI;AAAA,IACzB;AAEA,QAAID,gBAAAA,KAAqBF,gBAAgB,CAACC,aAAa;AACrD,YAAMhB,IAAI6B,OAAAA;AACV,YAAMW,UAASxC,uBAAGwC,WAAU,CAAC,QAAQ,KAAK;AAC1C,YAAMC,QAAOzC,uBAAGyC,SAAQ;AAExBzB,oBAAcxF,EAAEkH,IAAI3B,cAAc;AAAA,QAChC4B,cAAa3C,uBAAG2C,iBAAgB;AAAA,QAChCC,kBAAiB5C,uBAAG4C,qBAAoB;AAAA,QACxCC,oBAAoB;AAAA,MAAA,CACrB,EAAEC,QAAQN,QAAQC,IAAI;AAGvB,YAAMM,gBAAe/C,uBAAGgD,cAAa;AACrCxH,QAAEwH,UAAUD,cAAc;AAAA,QACxBE,cACEjD,uBAAGiD,gBACH;AAAA,MAAA,CACH,EAAEnD,MAAMkB,WAAW;AAEpB,WAAIhB,uBAAGiD,iBAAgB,IAAI;AACzBzH,UAAE0H,QAAQD,YAAY;AAAA,UAAEE,QAAQ;AAAA,QAAA,CAAO,EAAErD,MAAMkB,WAAW;AAAA,MAC5D;AAGA,aAAQxF,EAAE4H,KAAKC,QAAQC,UAAkBC;AACzC/H,QAAE4H,KAAKC,QAAQG,aAAa;AAAA,QAC1BC,eAAe;AAAA,QACfC,SAAS;AAAA,QACTC,WAAW;AAAA,MAAA,CACZ;AAAA,IACH;AAGA,QAAI3C,eAAexF,GAAG;AACpB,UAAI;AACF,cAAMwE,IAAI6B,OAAAA;AACV,cAAM+B,kBAAyB,CAAA;AAG/B5C,oBAAY6C,UAAU,CAAC1E,UAAe;AACpC,cACEA,iBAAiB3D,EAAEsI,UACnB3E,iBAAiB3D,EAAEuI,WACnB5E,iBAAiB3D,EAAEwI,gBACnB7E,MAAM8E,UACN9E,MAAM+E,eACN;AACAlD,wBAAYmD,YAAYhF,KAAK;AAAA,UAC/B;AAAA,QACF,CAAC;AAGD,cAAMe,UAAiB,CAAA;AACvB,cAAMkE,iBAAgBpE,uBAAGqE,gBAAcrE,uBAAGE,YAAWF,EAAEE,QAAQnE,SAAS;AAExE,YAAIqI,eAAe;AACjB,cAAI;AACF,kBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,2CAAuB,CAAA,EAAA,KAAA,OAAA,EAAA,wBAAA;AACpC,gBAAI,CAAC3I,kBAAkB;AACrB,oBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,+HAA8C,CAAA;AAC3D,oBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,uIAAsD,CAAA;AACnEA,iCAAmB;AAAA,YACrB;AACA,kBAAM6I,cACJ,OAAOtE,EAAEqE,eAAe,WAAWrE,EAAEqE,aAAa,CAAA;AACpD,kBAAME,eAAgB/I,EAAUgJ,mBAAmB;AAAA,cACjDC,kBAAkBH,YAAYG,oBAAoB;AAAA,cAClDC,mBAAmBJ,YAAYI,qBAAqB;AAAA,cACpDC,qBAAqBL,YAAYK,uBAAuB;AAAA,cACxDC,yBAAyBN,YAAYM;AAAAA,cACrCC,SAASP,YAAYQ,wBAAwB;AAAA,YAAA,CAC9C;AACD9E,yCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,oBAAMD,IAAIjD,EAAEkD,OAAOA,OAAO0B,QAAQ;AAClC5B,gCAAkBC,GAAGC,QAAQvB,WAAW;AACxCoH,2BAAaS,SAASvG,CAAC;AACvByB,sBAAQrC,KAAKY,CAAC;AAAA,YAChB;AACAuC,wBAAYgE,SAAST,YAAY;AAAA,UACnC,QAAQ;AACNvE,yCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,oBAAMD,IAAIjD,EAAEkD,OAAOA,OAAO0B,QAAQ,EAAEN,MAAMkB,WAAW;AACrDxC,gCAAkBC,GAAGC,QAAQvB,WAAW;AACxC+C,sBAAQrC,KAAKY,CAAC;AAAA,YAChB;AAAA,UACF;AAAA,QACF,OAAO;AACLuB,uCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,kBAAMD,IAAIjD,EAAEkD,OAAOA,OAAO0B,QAAQ,EAAEN,MAAMkB,WAAW;AACrDxC,8BAAkBC,GAAGC,QAAQvB,WAAW;AACxC+C,oBAAQrC,KAAKY,CAAC;AAAA,UAChB;AAAA,QACF;AAEA,YAAIyB,QAAQnE,SAAS,GAAG;AACtB6H,0BAAgB/F,KAAK,GAAGqC,OAAO;AAAA,QACjC;AAGA,YAAIF,uBAAGf,SAAS;AACd,gBAAMgG,WAAWnG,gBAAgBkC,aAAaxF,GAAGwE,EAAEf,SAASe,EAAEkF,cAAclF,EAAE9C,KAAK;AACnF0G,0BAAgB/F,KAAKoH,QAAQ;AAAA,QAC/B;AAGA,aAAIjF,uBAAGmF,WAAUnF,EAAEmF,OAAOpJ,SAAS,GAAG;AACpC,gBAAMqJ,WAAgC,CAAA;AAEtC,qBAAWC,YAAYrF,EAAEmF,QAAQ;AAC/B,kBAAMF,WAAWnG,gBACfkC,aACAxF,GACA6J,SAASpG,SACToG,SAASnJ,UAAS8D,uBAAGkF,eACrBG,SAASnI,UAAS8C,uBAAG9C,MACvB;AAEAkI,qBAASC,SAASC,IAAI,IAAIL;AAC1BrB,4BAAgB/F,KAAKoH,QAAQ;AAG7B,gBAAII,SAASE,YAAY,OAAO;AAC9BvE,0BAAYmD,YAAYc,QAAQ;AAAA,YAClC;AAAA,UACF;AAGA,cAAIlH,OAAOC,KAAKoH,QAAQ,EAAErJ,SAAS,GAAG;AACpCP,cAAE0H,QAAQiC,OAAO,MAAMC,UAAU;AAAA,cAAEI,WAAW;AAAA,YAAA,CAAM,EAAE1F,MAAMkB,WAAW;AAAA,UACzE;AAAA,QACF;AAGAO,wBAAgB,IAAI;AACpB,YAAIvB,uBAAGyF,SAAS;AACd,cAAI;AAEF,kBAAMC,YAAY,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA;AAAA;AAAA,cAA0B;AAAA,YAAmB,CAAA;AACrE,kBAAMC,WAAW3F,EAAEyF;AAEnB,kBAAMG,eACJD,cAASC,eAATD,mBAAqBjD,IAAKmD,CAAAA,UAAU;AAAA,cAClCC,WAAWD,KAAKC;AAAAA,cAChBC,YAAY,IAAKL,UACfG,KAAKE,eAAe,YAChB,sBACAF,KAAKE,eAAe,SAClB,mBACA,kBAAkB,EACxB;AAAA,gBACAC,MAAMH,KAAKxJ,SAAS;AAAA,gBACpB4J,QAAQJ,KAAKxJ,SAAS;AAAA,gBACtB6J,OAAOL,KAAKK,SAAS;AAAA,gBACrB3J,SAASsJ,KAAKtJ,WAAW;AAAA,cAAA,CAC1B;AAAA,YAAA,QACI,CAAA;AAET,kBAAM4J,eACJR,cAASQ,eAATR,mBAAqBjD,IAAKmD,CAAAA,UAAU;AAAA,cAClCC,WAAWD,KAAKC;AAAAA,cAChBC,YAAY,IAAKL,UAAkBU,eAAe;AAAA,gBAChDC,aAAa,CAACR,KAAKS,SAAS;AAAA,gBAC5BC,UAAUV,KAAKU,YAAY;AAAA,cAAA,CAC5B;AAAA,YAAA,QACI,CAAA;AAET,kBAAMC,UAAWd,UAAkBe,aAAa;AAAA,cAC9CC,KAAKf,SAASe;AAAAA,cACdzD,aAAa0C,SAAS1C;AAAAA,cACtB2C;AAAAA,cACAO;AAAAA,cACAQ,SAAShB,SAASgB;AAAAA,cAClBC,SAASjB,SAASiB;AAAAA,YAAAA,CACnB;AAEDJ,oBAAQ1G,MAAMkB,WAAW;AAAA,UAC3B,SAASqB,GAAG;AAKV,kBAAMwE,SAASxE,aAAayE,QAAQzE,EAAE0E,UAAUrJ,OAAO2E,CAAC;AACxD,kBAAM0E,UACJ;AAEFzE,oBAAQC,KAAK,cAAcwE,SAAS1E,CAAC;AACrCd,4BAAgBwF,OAAO;AACvBrF,mDAAWsF,SAAS;AAAA,cAClBvG,MAAM;AAAA,cACNwG,cAAc,GAAGF,OAAO,KAAKF,MAAM;AAAA,cACnCK,MAAI9J,WAAM0E,cAAN1E,mBAAiB8J,OAAM;AAAA,cAC3BC,eAAe;AAAA,cACfC,IAAIC,KAAKC,IAAAA;AAAAA,YAAI;AAAA,UAEjB;AAAA,QACF;AAGA,aAAItH,uBAAGuH,cAAa3D,gBAAgB7H,SAAS,GAAG;AAC9C,gBAAMyL,QAAQhM,EAAEiM,aAAa7D,eAAe;AAC5C,gBAAM8D,SAASF,MAAMG,UAAAA;AACrB,cAAID,OAAOE,WAAW;AACpB5G,wBAAYuG,UAAUG,OAAOG,IAAI,GAAG,CAAC;AAAA,UACvC;AAAA,QACF,WAAW7H,uBAAGwC,QAAQ;AACpBxB,sBAAY8B,QAAQ9C,EAAEwC,QAAQxC,EAAEyC,QAAQzB,YAAY8G,SAAS;AAAA,QAC/D;AAAA,MACF,SAASC,KAAK;AAGZ,cAAMhB,UAAUgB,eAAejB,QAAQiB,IAAIhB,UAAU;AACrD1F,iBAAS0F,OAAO;AAChBrF,+CAAWsF,SAAS;AAAA,UAClBvG,MAAM;AAAA,UACNwG,cAAcF;AAAAA,UACdG,MAAI9J,WAAM0E,cAAN1E,mBAAiB8J,OAAM;AAAA,UAC3BC,eAAe;AAAA,UACfC,IAAIC,KAAKC,IAAAA;AAAAA,QAAI;AAAA,MAEjB;AAAA,IACF;AAAA,EACF,CAAC;AAGDU,UAAAA,UAAU,MAAM;AACd,QAAIhH,aAAa;AACfA,kBAAYiH,OAAAA;AACZjH,oBAAc;AAAA,IAChB;AAAA,EACF,CAAC;AAED,SAAAkH,IAAAA,gBACGC,kBAAAA,mBAAiB;AAAA,IAChBC,OAAO;AAAA,IAAK,IACZC,WAAQ;AAAA,aAAEtI,aAAa8B,QAAQ;AAAA,IAAC;AAAA,IAChCyG,WAAS;AAAA,IAAA,IACTC,iBAAc;AAAA,aAAEnL,MAAMmL;AAAAA,IAAc;AAAA,IAAA,IAAAC,WAAA;AAAA,UAAAC,OAAAC,IAAAA,eAAAC,OAAA,GAAAC,QAAAH,KAAAI,YAAA,CAAAC,OAAAC,KAAA,IAAAC,IAAAA,cAAAJ,MAAAK,WAAA,GAAAC,QAAAJ,MAAAG,aAAA,CAAAE,OAAAC,KAAA,IAAAJ,IAAAA,cAAAE,MAAAD,WAAA;AAAAI,iBAAAZ,MAAAP,IAAAA,gBAOjCoB,cAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAEnI,MAAAA;AAAAA,QAAO;AAAA,QAAA,IAAAoH,WAAA;AAAA,cAAAgB,QAAAd,IAAAA,eAAAe,MAAA;AAAAJ,cAAAA,OAAAG,OAAAtB,oBAIdwB,iBAAAA,kBAAgBC,IAAAA,WAAA;AAAA,YAAA,IACf5C,UAAO;AAAA,qBAAE,yBAAyB3F,OAAO;AAAA,YAAE;AAAA,YAC3CwI,SAAO;AAAA,UAAA,GAAA,MACHC,oBAAAA,mBAAmBhI,OAAAA,KAAY,CAAA,CAAE,CAAC,CAAA,CAAA;AAAA,iBAAA2H;AAAAA,QAAA;AAAA,MAAA,CAAA,GAAAV,OAAAC,KAAA;AAAAM,iBAAAZ,MAAAP,IAAAA,gBAI3CoB,cAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAE,CAACnI,MAAAA;AAAAA,QAAO;AAAA,QAAA,IAAAoH,WAAA;AAAA,iBAAA,CAAAN,IAAAA,gBAGjBoB,cAAI;AAAA,YAAA,IAACC,OAAI;AAAA,qBAAEjI,aAAAA;AAAAA,YAAc;AAAA,YAAA,IAAAkH,WAAA;AAAA,kBAAAsB,QAAApB,IAAAA,eAAAqB,OAAA,GAAAC,QAAAF,MAAAjB,YAAA,CAAAoB,OAAAC,IAAA,IAAAlB,IAAAA,cAAAgB,MAAAf,WAAA;AAAAgB,oBAAAhB;AAAAI,kBAAAA,OAAAS,OAKrBxI,cAAY2I,OAAAC,IAAA;AAAA,qBAAAJ;AAAAA,YAAA;AAAA,UAAA,CAAA,IAAA,MAAA;AAAA,gBAAAK,QAAAzB,IAAAA,eAAA0B,OAAA;AAAA,gBAAAC,QAIVtJ;AAAY,mBAAAsJ,UAAA,aAAAC,IAAAA,IAAAD,OAAAF,KAAA,IAAZpJ,eAAYoJ;AAAAI,gBAAAA,OAAAC,CAAAA,QAAA;;AAAA,kBAAAC,MAEfjJ,eACI;AAAA,gBAAEkJ,QAAQ;AAAA,gBAAQxE,OAAO;AAAA,gBAAQ,WAAW;AAAA,cAAA,IAC5C;AAAA,gBAAEwE,UAAQ7I,kBAAAA,mBAAU6I,WAAU;AAAA,gBAASxE,OAAO;AAAA,gBAAQ,WAAW;AAAA,cAAA,GAAGyE,OAEnE,gBAAgBnJ,WAAAA,IAAe,mBAAmB,EAAE;AAAEgJ,kBAAAnI,IAAAuI,IAAAA,MAAAT,OAAAM,KAAAD,IAAAnI,CAAA;AAAAsI,uBAAAH,IAAAK,KAAAC,IAAAA,UAAAX,OAAAK,IAAAK,IAAAF,IAAA;AAAA,qBAAAH;AAAAA,YAAA,GAAA;AAAA,cAAAnI,GAAA9D;AAAAA,cAAAsM,GAAAtM;AAAAA,YAAAA,CAAA;AAAA,mBAAA4L;AAAAA,UAAA,IAAA;AAAA,QAAA;AAAA,MAAA,CAAA,GAAAhB,OAAAC,KAAA;AAAAmB,UAAAA,OAAA,MAAA;;AAAAO,mBAAAA,UAAArC,MAjC1D,uHAAqH5G,kBAAAA,mBAAUkJ,cAAa,EAAE,IACnJvJ,WAAAA,IAAe,iCAAiC,EAAE,EAClD;AAAA,OAAA;AAAA,aAAAiH;AAAAA,IAAA;AAAA,EAAA,CAAA;AAqCV;;;;;"}
|
|
1
|
+
{"version":3,"file":"MapRenderer.cjs","sources":["../../src/components/MapRenderer.tsx"],"sourcesContent":["/**\n * MapRenderer - Interactive map Component\n * Sprint 6: Markers + clustering\n * v3.1.0: GeoJSON, choropleth, popups, multi-layer, PMTiles\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js';\nimport { isServer } from 'solid-js/web';\nimport type {\n UIComponent,\n MapComponentParams,\n MapClusterOptions,\n MapGeoJSONStyle,\n MapPopupConfig,\n MapLayer,\n MapPMTilesConfig,\n} from '../types';\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper';\nimport { DegradedFallback } from './DegradedFallback';\nimport { mapToDegradedTable } from '../utils/degraded-projections';\nimport { escapeHtml } from '../utils/escape-html';\nimport { useTelemetry } from '../context/MCPUITelemetryContext';\n\n// Lazy load leaflet (it doesn't support SSR well)\nlet L: any = null;\n// Track if marker cluster CSS has been loaded\nlet clusterCssLoaded = false;\n\nexport interface MapRendererProps {\n /**\n * UIComponent containing map params\n */\n component?: UIComponent;\n\n /**\n * Direct map params\n */\n params?: MapComponentParams;\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible';\n\n /**\n * Trust marker / popup content as raw HTML (v6.10.0, audit P1.2).\n *\n * Leaflet renders bound tooltip/popup strings as HTML, so `marker.tooltip`,\n * `marker.popup` and a GeoJSON `popup.template` are XSS vectors when the\n * payload is untrusted (the default for an LLM/connector-driven public\n * package). **Default `false`** → those are escaped as plain text, and\n * `popup.template` is ignored in favour of the safe auto-generated popup.\n *\n * This is a **host-level** trust decision, deliberately NOT a payload field\n * (a malicious payload could just set its own flag). The\n * `<UIResourceRenderer>` path never sets it, so payload-driven maps are\n * always text-safe. A host rendering `<MapRenderer>` directly with trusted\n * data may set `allowHtmlPopups` to restore rich HTML popups. The\n * auto-generated popup (`titleField` / `fields`) is safe-by-construction\n * and unaffected either way.\n */\n allowHtmlPopups?: boolean;\n}\n\n// ─── Helpers ────────────────────────────────────────────────\n\n/**\n * Resolve choropleth color for a feature based on property value and scale stops.\n */\nfunction getChoroplethColor(\n value: unknown,\n scale: Array<[number, string]>,\n fallback: string\n): string {\n if (value == null || typeof value !== 'number' || !isFinite(value)) return fallback;\n\n // Scale is sorted ascending: [[0, '#eff3ff'], [100, '#084594']]\n if (scale.length === 0) return fallback;\n if (value <= scale[0][0]) return scale[0][1];\n if (value >= scale[scale.length - 1][0]) return scale[scale.length - 1][1];\n\n // Find surrounding stops and interpolate (use upper bracket color)\n for (let i = 1; i < scale.length; i++) {\n if (value <= scale[i][0]) return scale[i][1];\n }\n return scale[scale.length - 1][1];\n}\n\n/**\n * Build a Leaflet style function from MapGeoJSONStyle config.\n */\nfunction buildStyleFn(\n style: MapGeoJSONStyle | undefined\n): (feature: any) => Record<string, unknown> {\n if (!style) {\n return () => ({\n fillColor: '#3388ff',\n fillOpacity: 0.6,\n color: '#333',\n weight: 1,\n opacity: 1,\n });\n }\n\n return (feature: any) => {\n let fillColor = style.fillColor || '#3388ff';\n\n // Choropleth: override fillColor based on feature property\n if (style.choroplethField && style.choroplethScale && feature?.properties) {\n const val = feature.properties[style.choroplethField];\n fillColor = getChoroplethColor(\n val,\n style.choroplethScale,\n style.choroplethFallback || '#ccc'\n );\n }\n\n return {\n fillColor,\n fillOpacity: style.fillOpacity ?? 0.6,\n color: style.strokeColor || '#333',\n weight: style.strokeWeight ?? 1,\n opacity: style.strokeOpacity ?? 1,\n };\n };\n}\n\n/**\n * Build popup HTML from a feature's properties using popup config.\n *\n * `allowHtml` (audit P1.2) gates the raw-HTML `popup.template`: it is honored\n * only when the host trusts the payload. On the default (untrusted) path the\n * template is ignored and we fall through to the auto-generated popup, whose\n * structure is renderer-authored and whose values are always escaped — safe\n * by construction. Even in the trusted path, substituted `{{prop}}` values\n * are escaped (they are data, not markup).\n */\nexport function buildPopupContent(\n feature: any,\n popup: MapPopupConfig | undefined,\n allowHtml = false\n): string | null {\n if (!popup || !feature?.properties) return null;\n const props = feature.properties;\n\n // Custom template — raw HTML, so trusted-host only.\n if (allowHtml && popup.template) {\n return popup.template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\n const val = props[key];\n return val != null ? escapeHtml(String(val)) : '';\n });\n }\n\n // Auto-generated popup\n const parts: string[] = [];\n\n if (popup.titleField && props[popup.titleField] != null) {\n parts.push(`<strong>${escapeHtml(String(props[popup.titleField]))}</strong>`);\n }\n\n const fields = popup.fields || Object.keys(props).slice(0, 8);\n for (const key of fields) {\n if (key === popup.titleField) continue;\n const val = props[key];\n if (val == null) continue;\n const formatted = typeof val === 'number' ? val.toLocaleString('fr-FR') : String(val);\n parts.push(\n `<span style=\"color:#666;font-size:11px\">${escapeHtml(key)}</span>: ${escapeHtml(formatted)}`\n );\n }\n\n return parts.join('<br/>');\n}\n\n/**\n * Resolve a marker's tooltip/popup string for binding (audit P1.2). Leaflet\n * renders bound strings as HTML; `marker.tooltip` / `marker.popup` come from\n * the (untrusted) payload, so they are escaped to plain text unless the host\n * has opted into raw HTML via `allowHtmlPopups`. Pure + exported for tests.\n */\nexport function popupSafeText(value: string | undefined, allowHtml = false): string | undefined {\n if (value == null) return undefined;\n return allowHtml ? value : escapeHtml(value);\n}\n\n/** Bind a marker's tooltip + popup, escaping by default (see popupSafeText). */\nexport function bindMarkerContent(\n m: any,\n marker: { tooltip?: string; popup?: string },\n allowHtml: boolean\n): void {\n const tooltip = popupSafeText(marker.tooltip, allowHtml);\n if (tooltip) m.bindTooltip(tooltip);\n const popup = popupSafeText(marker.popup, allowHtml);\n if (popup) m.bindPopup(popup);\n}\n\n/**\n * Add a GeoJSON layer to the map with style and popup support.\n * Returns the layer for bounds calculation.\n */\nexport function addGeoJSONLayer(\n mapInst: any,\n leaflet: any,\n geojson: unknown,\n style?: MapGeoJSONStyle,\n popup?: MapPopupConfig,\n allowHtml = false\n): any {\n const styleFn = buildStyleFn(style);\n\n const layer = leaflet.geoJSON(geojson, {\n style: styleFn,\n pointToLayer: (feature: any, latlng: any) => {\n // Render points as circle markers for consistency\n const s = styleFn(feature);\n return leaflet.circleMarker(latlng, {\n radius: 6,\n fillColor: s.fillColor,\n fillOpacity: s.fillOpacity,\n color: s.color,\n weight: s.weight,\n opacity: s.opacity,\n });\n },\n onEachFeature: (feature: any, featureLayer: any) => {\n const html = buildPopupContent(feature, popup, allowHtml);\n if (html) {\n featureLayer.bindPopup(html, { maxWidth: 300 });\n }\n },\n });\n\n layer.addTo(mapInst);\n return layer;\n}\n\n// ─── Component ──────────────────────────────────────────────\n\n/**\n * Build a GeoJSON FeatureCollection from the map's `markers` (and any\n * inlined GeoJSON layers, when present). Used by the \"Copy data\" button\n * shipped via `<ExpandableWrapper>` (v6.2.0). Best-effort — clusters,\n * tile layers, and choropleth-only data don't get round-tripped.\n */\nfunction mapToGeoJSON(p: MapComponentParams | undefined): string {\n if (!p) return '{\"type\":\"FeatureCollection\",\"features\":[]}';\n const features: any[] = [];\n for (const marker of p.markers ?? []) {\n const pos: any = marker.position as any;\n // Accept both [lat, lng] tuple and {lat, lng} object shapes (v5.0.2 spec)\n const lat = Array.isArray(pos) ? pos[0] : pos?.lat;\n const lng = Array.isArray(pos) ? pos[1] : pos?.lng;\n if (typeof lat !== 'number' || typeof lng !== 'number') continue;\n features.push({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [lng, lat] },\n properties: {\n ...(marker.tooltip ? { tooltip: marker.tooltip } : {}),\n ...(marker.popup ? { popup: marker.popup } : {}),\n },\n });\n }\n return JSON.stringify({ type: 'FeatureCollection', features }, null, 2);\n}\n\nexport const MapRenderer: Component<MapRendererProps> = (props) => {\n let mapContainer: HTMLDivElement | undefined;\n let mapInstance: any = null;\n const [isLeafletLoaded, setIsLeafletLoaded] = createSignal(false);\n const [error, setError] = createSignal<string | null>(null);\n // PMTiles is an optional overlay on top of the base map. When it fails we\n // keep the base map but surface a visible notice (audit P1.3) instead of a\n // silent console.warn that leaves the user with an unexplained empty layer.\n const [pmtilesError, setPmtilesError] = createSignal<string | null>(null);\n const isExpanded = useExpanded();\n const telemetry = useTelemetry();\n // Host-level trust for raw HTML in marker/popup content (audit P1.2).\n // Default false → tooltip/popup escaped, GeoJSON `popup.template` ignored.\n const allowHtml = () => props.allowHtmlPopups === true;\n\n const params = () => props.params || (props.component?.params as MapComponentParams);\n\n // v6.2.0 — Leaflet has to be told to re-measure when its container\n // resizes (e.g. transitioning to fullscreen via ExpandableWrapper).\n // We give the DOM a tick to settle the new dimensions, then ask\n // Leaflet to reflow tiles.\n createEffect(() => {\n const expanded = isExpanded();\n if (!mapInstance) return;\n // Read the signal so the effect re-runs on toggle ; the value is\n // observed for its side effects on layout.\n void expanded;\n setTimeout(() => mapInstance?.invalidateSize?.(), 100);\n });\n\n // Initialize Map\n createEffect(async () => {\n if (isServer) return; // Don't run on server\n\n if (!L) {\n try {\n const module = await import('leaflet');\n L = module.default || module;\n await import('leaflet/dist/leaflet.css'); // Import CSS\n setIsLeafletLoaded(true);\n } catch (e) {\n console.warn('Failed to load leaflet', e);\n setError('Map library could not be loaded.');\n return;\n }\n } else {\n setIsLeafletLoaded(true);\n }\n\n if (isLeafletLoaded() && mapContainer && !mapInstance) {\n const p = params();\n const center = p?.center || [51.505, -0.09]; // Default to London\n const zoom = p?.zoom || 13;\n\n mapInstance = L.map(mapContainer, {\n zoomControl: p?.zoomControl !== false,\n scrollWheelZoom: p?.scrollWheelZoom !== false,\n attributionControl: false,\n }).setView(center, zoom);\n\n // Add OpenStreetMap tile layer\n const tileLayerUrl = p?.tileLayer || 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';\n L.tileLayer(tileLayerUrl, {\n attribution:\n p?.attribution ||\n '© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors',\n }).addTo(mapInstance);\n\n if (p?.attribution !== '') {\n L.control.attribution({ prefix: false }).addTo(mapInstance);\n }\n\n // Fix marker icons (Leaflet issue with bundlers)\n delete (L.Icon.Default.prototype as any)._getIconUrl;\n L.Icon.Default.mergeOptions({\n iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',\n iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',\n shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',\n });\n }\n\n // Update markers and view\n if (mapInstance && L) {\n try {\n const p = params();\n const allBoundsLayers: any[] = [];\n\n // Clear existing layers (markers, cluster groups, GeoJSON)\n mapInstance.eachLayer((layer: any) => {\n if (\n layer instanceof L.Marker ||\n layer instanceof L.GeoJSON ||\n layer instanceof L.CircleMarker ||\n layer._group ||\n layer._featureGroup\n ) {\n mapInstance.removeLayer(layer);\n }\n });\n\n // ─── Markers (legacy) ────────────────────────\n const markers: any[] = [];\n const shouldCluster = p?.clustering && p?.markers && p.markers.length > 0;\n\n if (shouldCluster) {\n try {\n await import('leaflet.markercluster');\n if (!clusterCssLoaded) {\n await import('leaflet.markercluster/dist/MarkerCluster.css');\n await import('leaflet.markercluster/dist/MarkerCluster.Default.css');\n clusterCssLoaded = true;\n }\n const clusterOpts: MapClusterOptions =\n typeof p.clustering === 'object' ? p.clustering : {};\n const clusterGroup = (L as any).markerClusterGroup({\n maxClusterRadius: clusterOpts.maxClusterRadius ?? 80,\n spiderfyOnMaxZoom: clusterOpts.spiderfyOnMaxZoom ?? true,\n showCoverageOnHover: clusterOpts.showCoverageOnHover ?? true,\n disableClusteringAtZoom: clusterOpts.disableClusteringAtZoom,\n animate: clusterOpts.animateAddingMarkers ?? true,\n });\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position);\n bindMarkerContent(m, marker, allowHtml());\n clusterGroup.addLayer(m);\n markers.push(m);\n });\n mapInstance.addLayer(clusterGroup);\n } catch {\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position).addTo(mapInstance);\n bindMarkerContent(m, marker, allowHtml());\n markers.push(m);\n });\n }\n } else {\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position).addTo(mapInstance);\n bindMarkerContent(m, marker, allowHtml());\n markers.push(m);\n });\n }\n\n if (markers.length > 0) {\n allBoundsLayers.push(...markers);\n }\n\n // ─── GeoJSON (v3.1.0) ───────────────────────\n if (p?.geojson) {\n const geoLayer = addGeoJSONLayer(\n mapInstance,\n L,\n p.geojson,\n p.geojsonStyle,\n p.popup,\n allowHtml()\n );\n allBoundsLayers.push(geoLayer);\n }\n\n // ─── Named layers (v3.1.0) ──────────────────\n if (p?.layers && p.layers.length > 0) {\n const overlays: Record<string, any> = {};\n\n for (const layerDef of p.layers) {\n const geoLayer = addGeoJSONLayer(\n mapInstance,\n L,\n layerDef.geojson,\n layerDef.style || p?.geojsonStyle,\n layerDef.popup || p?.popup,\n allowHtml()\n );\n\n overlays[layerDef.name] = geoLayer;\n allBoundsLayers.push(geoLayer);\n\n // Respect initial visibility\n if (layerDef.visible === false) {\n mapInstance.removeLayer(geoLayer);\n }\n }\n\n // Add layer control if multiple layers\n if (Object.keys(overlays).length > 1) {\n L.control.layers(null, overlays, { collapsed: true }).addTo(mapInstance);\n }\n }\n\n // ─── PMTiles (v3.1.0) ────────────────────────\n setPmtilesError(null);\n if (p?.pmtiles) {\n try {\n // @ts-ignore — optional peer dependency, may not be installed\n const protomaps = await import(/* @vite-ignore */ 'protomaps-leaflet');\n const pmConfig = p.pmtiles;\n\n const paintRules =\n pmConfig.paintRules?.map((rule) => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any)[\n rule.symbolizer === 'polygon'\n ? 'PolygonSymbolizer'\n : rule.symbolizer === 'line'\n ? 'LineSymbolizer'\n : 'CircleSymbolizer'\n ]({\n fill: rule.color || '#3388ff',\n stroke: rule.color || '#333',\n width: rule.width ?? 1,\n opacity: rule.opacity ?? 0.6,\n }),\n })) || [];\n\n const labelRules =\n pmConfig.labelRules?.map((rule) => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any).TextSymbolizer({\n label_props: [rule.textField],\n fontSize: rule.fontSize ?? 12,\n }),\n })) || [];\n\n const pmLayer = (protomaps as any).leafletLayer({\n url: pmConfig.url,\n attribution: pmConfig.attribution,\n paintRules,\n labelRules,\n maxZoom: pmConfig.maxZoom,\n minZoom: pmConfig.minZoom,\n });\n\n pmLayer.addTo(mapInstance);\n } catch (e) {\n // P1.3 — do NOT fail silently. Keep the base map, but surface a\n // visible notice and report a renderer error via telemetry. The\n // most common cause is the optional `protomaps-leaflet` peer not\n // being installed.\n const detail = e instanceof Error ? e.message : String(e);\n const message =\n 'PMTiles layer unavailable — the optional \"protomaps-leaflet\" ' +\n 'peer dependency failed to load or render.';\n console.warn('[MCP-UI] ' + message, e);\n setPmtilesError(message);\n telemetry?.dispatch({\n type: 'render:error',\n errorMessage: `${message} (${detail})`,\n id: props.component?.id ?? '',\n componentType: 'map',\n ts: Date.now(),\n });\n }\n }\n\n // ─── Fit bounds ─────────────────────────────\n if (p?.fitBounds && allBoundsLayers.length > 0) {\n const group = L.featureGroup(allBoundsLayers);\n const bounds = group.getBounds();\n if (bounds.isValid()) {\n mapInstance.fitBounds(bounds.pad(0.1));\n }\n } else if (p?.center) {\n mapInstance.setView(p.center, p.zoom || mapInstance.getZoom());\n }\n } catch (err) {\n // Fallback ladder (P2.5): a Leaflet drawing failure degrades to\n // the coordinate table below instead of a blank/partial map.\n const message = err instanceof Error ? err.message : 'Failed to render map';\n setError(message);\n telemetry?.dispatch({\n type: 'render:error',\n errorMessage: message,\n id: props.component?.id ?? '',\n componentType: 'map',\n ts: Date.now(),\n });\n }\n }\n });\n\n // Cleanup\n onCleanup(() => {\n if (mapInstance) {\n mapInstance.remove();\n mapInstance = null;\n }\n });\n\n return (\n <ExpandableWrapper\n title={'Map'}\n copyData={mapToGeoJSON(params())}\n copyLabel=\"Copy markers as GeoJSON\"\n toolbarVariant={props.toolbarVariant}\n >\n <div\n class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${params()?.className || ''} ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}\n >\n <Show when={error()}>\n {/* Fallback ladder (P2.5): degrade to a coordinate table\n rather than a bare error string. */}\n <div class=\"p-3\">\n <DegradedFallback\n message={`Map rendering failed: ${error()}`}\n caption=\"Showing the map data as a coordinate table — the interactive map is unavailable.\"\n {...mapToDegradedTable(params() ?? {})}\n />\n </div>\n </Show>\n <Show when={!error()}>\n {/* P1.3 — visible notice when the PMTiles overlay fails but the\n base map is still usable. */}\n <Show when={pmtilesError()}>\n <div\n role=\"alert\"\n class=\"m-2 rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200\"\n >\n {pmtilesError()} The base map is still shown.\n </div>\n </Show>\n <div\n ref={mapContainer}\n style={\n isExpanded()\n ? { height: '100%', width: '100%', 'z-index': 0 }\n : { height: params()?.height || '400px', width: '100%', 'z-index': 0 }\n }\n class={`relative z-0 ${isExpanded() ? 'flex-1 min-h-0' : ''}`}\n />\n </Show>\n </div>\n </ExpandableWrapper>\n );\n};\n"],"names":["L","clusterCssLoaded","getChoroplethColor","value","scale","fallback","isFinite","length","i","buildStyleFn","style","fillColor","fillOpacity","color","weight","opacity","feature","choroplethField","choroplethScale","properties","val","choroplethFallback","strokeColor","strokeWeight","strokeOpacity","buildPopupContent","popup","allowHtml","props","template","replace","_","key","escapeHtml","String","parts","titleField","push","fields","Object","keys","slice","formatted","toLocaleString","join","popupSafeText","undefined","bindMarkerContent","m","marker","tooltip","bindTooltip","bindPopup","addGeoJSONLayer","mapInst","leaflet","geojson","styleFn","layer","geoJSON","pointToLayer","latlng","s","circleMarker","radius","onEachFeature","featureLayer","html","maxWidth","addTo","mapToGeoJSON","p","features","markers","pos","position","lat","Array","isArray","lng","type","geometry","coordinates","JSON","stringify","MapRenderer","mapContainer","mapInstance","isLeafletLoaded","setIsLeafletLoaded","createSignal","error","setError","pmtilesError","setPmtilesError","isExpanded","useExpanded","telemetry","useTelemetry","allowHtmlPopups","params","component","createEffect","setTimeout","invalidateSize","isServer","module","default","e","console","warn","center","zoom","map","zoomControl","scrollWheelZoom","attributionControl","setView","tileLayerUrl","tileLayer","attribution","control","prefix","Icon","Default","prototype","_getIconUrl","mergeOptions","iconRetinaUrl","iconUrl","shadowUrl","allBoundsLayers","eachLayer","Marker","GeoJSON","CircleMarker","_group","_featureGroup","removeLayer","shouldCluster","clustering","clusterOpts","clusterGroup","markerClusterGroup","maxClusterRadius","spiderfyOnMaxZoom","showCoverageOnHover","disableClusteringAtZoom","animate","animateAddingMarkers","forEach","addLayer","geoLayer","geojsonStyle","layers","overlays","layerDef","name","visible","collapsed","pmtiles","protomaps","pmConfig","paintRules","rule","dataLayer","symbolizer","fill","stroke","width","labelRules","TextSymbolizer","label_props","textField","fontSize","pmLayer","leafletLayer","url","maxZoom","minZoom","detail","Error","message","dispatch","errorMessage","id","componentType","ts","Date","now","fitBounds","group","featureGroup","bounds","getBounds","isValid","pad","getZoom","err","onCleanup","remove","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$2","_$getNextMarker","nextSibling","_el$0","_el$1","_co$3","_$insert","Show","when","_el$2","_tmpl$","DegradedFallback","_$mergeProps","caption","mapToDegradedTable","_el$3","_tmpl$2","_el$5","_el$6","_co$","_el$7","_tmpl$3","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","_$style","t","_$className","className"],"mappings":";;;;;;;;;;AAwBA,IAAIA,IAAS;AAEb,IAAIC,mBAAmB;AA4CvB,SAASC,mBACPC,OACAC,OACAC,UACQ;AACR,MAAIF,SAAS,QAAQ,OAAOA,UAAU,YAAY,CAACG,SAASH,KAAK,EAAG,QAAOE;AAG3E,MAAID,MAAMG,WAAW,EAAG,QAAOF;AAC/B,MAAIF,SAASC,MAAM,CAAC,EAAE,CAAC,EAAG,QAAOA,MAAM,CAAC,EAAE,CAAC;AAC3C,MAAID,SAASC,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC,EAAG,QAAOH,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC;AAGzE,WAASC,IAAI,GAAGA,IAAIJ,MAAMG,QAAQC,KAAK;AACrC,QAAIL,SAASC,MAAMI,CAAC,EAAE,CAAC,EAAG,QAAOJ,MAAMI,CAAC,EAAE,CAAC;AAAA,EAC7C;AACA,SAAOJ,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC;AAClC;AAKA,SAASE,aACPC,OAC2C;AAC3C,MAAI,CAACA,OAAO;AACV,WAAO,OAAO;AAAA,MACZC,WAAW;AAAA,MACXC,aAAa;AAAA,MACbC,OAAO;AAAA,MACPC,QAAQ;AAAA,MACRC,SAAS;AAAA,IAAA;AAAA,EAEb;AAEA,SAAO,CAACC,YAAiB;AACvB,QAAIL,YAAYD,MAAMC,aAAa;AAGnC,QAAID,MAAMO,mBAAmBP,MAAMQ,oBAAmBF,mCAASG,aAAY;AACzE,YAAMC,MAAMJ,QAAQG,WAAWT,MAAMO,eAAe;AACpDN,kBAAYT,mBACVkB,KACAV,MAAMQ,iBACNR,MAAMW,sBAAsB,MAC9B;AAAA,IACF;AAEA,WAAO;AAAA,MACLV;AAAAA,MACAC,aAAaF,MAAME,eAAe;AAAA,MAClCC,OAAOH,MAAMY,eAAe;AAAA,MAC5BR,QAAQJ,MAAMa,gBAAgB;AAAA,MAC9BR,SAASL,MAAMc,iBAAiB;AAAA,IAAA;AAAA,EAEpC;AACF;AAYO,SAASC,kBACdT,SACAU,OACAC,YAAY,OACG;AACf,MAAI,CAACD,SAAS,EAACV,mCAASG,YAAY,QAAO;AAC3C,QAAMS,QAAQZ,QAAQG;AAGtB,MAAIQ,aAAaD,MAAMG,UAAU;AAC/B,WAAOH,MAAMG,SAASC,QAAQ,kBAAkB,CAACC,GAAGC,QAAQ;AAC1D,YAAMZ,MAAMQ,MAAMI,GAAG;AACrB,aAAOZ,OAAO,OAAOa,WAAAA,WAAWC,OAAOd,GAAG,CAAC,IAAI;AAAA,IACjD,CAAC;AAAA,EACH;AAGA,QAAMe,QAAkB,CAAA;AAExB,MAAIT,MAAMU,cAAcR,MAAMF,MAAMU,UAAU,KAAK,MAAM;AACvDD,UAAME,KAAK,WAAWJ,WAAAA,WAAWC,OAAON,MAAMF,MAAMU,UAAU,CAAC,CAAC,CAAC,WAAW;AAAA,EAC9E;AAEA,QAAME,SAASZ,MAAMY,UAAUC,OAAOC,KAAKZ,KAAK,EAAEa,MAAM,GAAG,CAAC;AAC5D,aAAWT,OAAOM,QAAQ;AACxB,QAAIN,QAAQN,MAAMU,WAAY;AAC9B,UAAMhB,MAAMQ,MAAMI,GAAG;AACrB,QAAIZ,OAAO,KAAM;AACjB,UAAMsB,YAAY,OAAOtB,QAAQ,WAAWA,IAAIuB,eAAe,OAAO,IAAIT,OAAOd,GAAG;AACpFe,UAAME,KACJ,2CAA2CJ,sBAAWD,GAAG,CAAC,YAAYC,WAAAA,WAAWS,SAAS,CAAC,EAC7F;AAAA,EACF;AAEA,SAAOP,MAAMS,KAAK,OAAO;AAC3B;AAQO,SAASC,cAAc1C,OAA2BwB,YAAY,OAA2B;AAC9F,MAAIxB,SAAS,KAAM,QAAO2C;AAC1B,SAAOnB,YAAYxB,QAAQ8B,WAAAA,WAAW9B,KAAK;AAC7C;AAGO,SAAS4C,kBACdC,GACAC,QACAtB,WACM;AACN,QAAMuB,UAAUL,cAAcI,OAAOC,SAASvB,SAAS;AACvD,MAAIuB,QAASF,GAAEG,YAAYD,OAAO;AAClC,QAAMxB,QAAQmB,cAAcI,OAAOvB,OAAOC,SAAS;AACnD,MAAID,MAAOsB,GAAEI,UAAU1B,KAAK;AAC9B;AAMO,SAAS2B,gBACdC,SACAC,SACAC,SACA9C,OACAgB,OACAC,YAAY,OACP;AACL,QAAM8B,UAAUhD,aAAaC,KAAK;AAElC,QAAMgD,QAAQH,QAAQI,QAAQH,SAAS;AAAA,IACrC9C,OAAO+C;AAAAA,IACPG,cAAcA,CAAC5C,SAAc6C,WAAgB;AAE3C,YAAMC,IAAIL,QAAQzC,OAAO;AACzB,aAAOuC,QAAQQ,aAAaF,QAAQ;AAAA,QAClCG,QAAQ;AAAA,QACRrD,WAAWmD,EAAEnD;AAAAA,QACbC,aAAakD,EAAElD;AAAAA,QACfC,OAAOiD,EAAEjD;AAAAA,QACTC,QAAQgD,EAAEhD;AAAAA,QACVC,SAAS+C,EAAE/C;AAAAA,MAAAA,CACZ;AAAA,IACH;AAAA,IACAkD,eAAeA,CAACjD,SAAckD,iBAAsB;AAClD,YAAMC,OAAO1C,kBAAkBT,SAASU,OAAOC,SAAS;AACxD,UAAIwC,MAAM;AACRD,qBAAad,UAAUe,MAAM;AAAA,UAAEC,UAAU;AAAA,QAAA,CAAK;AAAA,MAChD;AAAA,IACF;AAAA,EAAA,CACD;AAEDV,QAAMW,MAAMf,OAAO;AACnB,SAAOI;AACT;AAUA,SAASY,aAAaC,GAA2C;AAC/D,MAAI,CAACA,EAAG,QAAO;AACf,QAAMC,WAAkB,CAAA;AACxB,aAAWvB,UAAUsB,EAAEE,WAAW,CAAA,GAAI;AACpC,UAAMC,MAAWzB,OAAO0B;AAExB,UAAMC,MAAMC,MAAMC,QAAQJ,GAAG,IAAIA,IAAI,CAAC,IAAIA,2BAAKE;AAC/C,UAAMG,MAAMF,MAAMC,QAAQJ,GAAG,IAAIA,IAAI,CAAC,IAAIA,2BAAKK;AAC/C,QAAI,OAAOH,QAAQ,YAAY,OAAOG,QAAQ,SAAU;AACxDP,aAASnC,KAAK;AAAA,MACZ2C,MAAM;AAAA,MACNC,UAAU;AAAA,QAAED,MAAM;AAAA,QAASE,aAAa,CAACH,KAAKH,GAAG;AAAA,MAAA;AAAA,MACjDzD,YAAY;AAAA,QACV,GAAI8B,OAAOC,UAAU;AAAA,UAAEA,SAASD,OAAOC;AAAAA,QAAAA,IAAY,CAAA;AAAA,QACnD,GAAID,OAAOvB,QAAQ;AAAA,UAAEA,OAAOuB,OAAOvB;AAAAA,QAAAA,IAAU,CAAA;AAAA,MAAC;AAAA,IAChD,CACD;AAAA,EACH;AACA,SAAOyD,KAAKC,UAAU;AAAA,IAAEJ,MAAM;AAAA,IAAqBR;AAAAA,EAAAA,GAAY,MAAM,CAAC;AACxE;AAEO,MAAMa,cAA4CzD,CAAAA,UAAU;AACjE,MAAI0D;AACJ,MAAIC,cAAmB;AACvB,QAAM,CAACC,iBAAiBC,kBAAkB,IAAIC,QAAAA,aAAa,KAAK;AAChE,QAAM,CAACC,OAAOC,QAAQ,IAAIF,QAAAA,aAA4B,IAAI;AAI1D,QAAM,CAACG,cAAcC,eAAe,IAAIJ,QAAAA,aAA4B,IAAI;AACxE,QAAMK,aAAaC,kBAAAA,YAAAA;AACnB,QAAMC,YAAYC,sBAAAA,aAAAA;AAGlB,QAAMvE,YAAYA,MAAMC,MAAMuE,oBAAoB;AAElD,QAAMC,SAASA,MAAAA;;AAAMxE,iBAAMwE,YAAWxE,WAAMyE,cAANzE,mBAAiBwE;AAAAA;AAMvDE,UAAAA,aAAa,MAAM;AACAP,eAAAA;AACjB,QAAI,CAACR,YAAa;AAIlBgB,eAAW,MAAA;;AAAMhB,8DAAaiB,mBAAbjB;AAAAA,OAAiC,GAAG;AAAA,EACvD,CAAC;AAGDe,UAAAA,aAAa,YAAY;;AACvB,QAAIG,aAAU;AAEd,QAAI,CAACzG,GAAG;AACN,UAAI;AACF,cAAM0G,UAAS,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,6BAAS,CAAA,EAAA,KAAA,OAAA,EAAA,UAAA;AACrC1G,YAAI0G,QAAOC,WAAWD;AACtB,cAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,+EAA0B,CAAA;AACvCjB,2BAAmB,IAAI;AAAA,MACzB,SAASmB,GAAG;AACVC,gBAAQC,KAAK,0BAA0BF,CAAC;AACxChB,iBAAS,kCAAkC;AAC3C;AAAA,MACF;AAAA,IACF,OAAO;AACLH,yBAAmB,IAAI;AAAA,IACzB;AAEA,QAAID,gBAAAA,KAAqBF,gBAAgB,CAACC,aAAa;AACrD,YAAMhB,IAAI6B,OAAAA;AACV,YAAMW,UAASxC,uBAAGwC,WAAU,CAAC,QAAQ,KAAK;AAC1C,YAAMC,QAAOzC,uBAAGyC,SAAQ;AAExBzB,oBAAcvF,EAAEiH,IAAI3B,cAAc;AAAA,QAChC4B,cAAa3C,uBAAG2C,iBAAgB;AAAA,QAChCC,kBAAiB5C,uBAAG4C,qBAAoB;AAAA,QACxCC,oBAAoB;AAAA,MAAA,CACrB,EAAEC,QAAQN,QAAQC,IAAI;AAGvB,YAAMM,gBAAe/C,uBAAGgD,cAAa;AACrCvH,QAAEuH,UAAUD,cAAc;AAAA,QACxBE,cACEjD,uBAAGiD,gBACH;AAAA,MAAA,CACH,EAAEnD,MAAMkB,WAAW;AAEpB,WAAIhB,uBAAGiD,iBAAgB,IAAI;AACzBxH,UAAEyH,QAAQD,YAAY;AAAA,UAAEE,QAAQ;AAAA,QAAA,CAAO,EAAErD,MAAMkB,WAAW;AAAA,MAC5D;AAGA,aAAQvF,EAAE2H,KAAKC,QAAQC,UAAkBC;AACzC9H,QAAE2H,KAAKC,QAAQG,aAAa;AAAA,QAC1BC,eAAe;AAAA,QACfC,SAAS;AAAA,QACTC,WAAW;AAAA,MAAA,CACZ;AAAA,IACH;AAGA,QAAI3C,eAAevF,GAAG;AACpB,UAAI;AACF,cAAMuE,IAAI6B,OAAAA;AACV,cAAM+B,kBAAyB,CAAA;AAG/B5C,oBAAY6C,UAAU,CAAC1E,UAAe;AACpC,cACEA,iBAAiB1D,EAAEqI,UACnB3E,iBAAiB1D,EAAEsI,WACnB5E,iBAAiB1D,EAAEuI,gBACnB7E,MAAM8E,UACN9E,MAAM+E,eACN;AACAlD,wBAAYmD,YAAYhF,KAAK;AAAA,UAC/B;AAAA,QACF,CAAC;AAGD,cAAMe,UAAiB,CAAA;AACvB,cAAMkE,iBAAgBpE,uBAAGqE,gBAAcrE,uBAAGE,YAAWF,EAAEE,QAAQlE,SAAS;AAExE,YAAIoI,eAAe;AACjB,cAAI;AACF,kBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,2CAAuB,CAAA,EAAA,KAAA,OAAA,EAAA,wBAAA;AACpC,gBAAI,CAAC1I,kBAAkB;AACrB,oBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,+HAA8C,CAAA;AAC3D,oBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,uIAAsD,CAAA;AACnEA,iCAAmB;AAAA,YACrB;AACA,kBAAM4I,cACJ,OAAOtE,EAAEqE,eAAe,WAAWrE,EAAEqE,aAAa,CAAA;AACpD,kBAAME,eAAgB9I,EAAU+I,mBAAmB;AAAA,cACjDC,kBAAkBH,YAAYG,oBAAoB;AAAA,cAClDC,mBAAmBJ,YAAYI,qBAAqB;AAAA,cACpDC,qBAAqBL,YAAYK,uBAAuB;AAAA,cACxDC,yBAAyBN,YAAYM;AAAAA,cACrCC,SAASP,YAAYQ,wBAAwB;AAAA,YAAA,CAC9C;AACD9E,yCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,oBAAMD,IAAIhD,EAAEiD,OAAOA,OAAO0B,QAAQ;AAClC5B,gCAAkBC,GAAGC,QAAQtB,WAAW;AACxCmH,2BAAaS,SAASvG,CAAC;AACvByB,sBAAQpC,KAAKW,CAAC;AAAA,YAChB;AACAuC,wBAAYgE,SAAST,YAAY;AAAA,UACnC,QAAQ;AACNvE,yCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,oBAAMD,IAAIhD,EAAEiD,OAAOA,OAAO0B,QAAQ,EAAEN,MAAMkB,WAAW;AACrDxC,gCAAkBC,GAAGC,QAAQtB,WAAW;AACxC8C,sBAAQpC,KAAKW,CAAC;AAAA,YAChB;AAAA,UACF;AAAA,QACF,OAAO;AACLuB,uCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,kBAAMD,IAAIhD,EAAEiD,OAAOA,OAAO0B,QAAQ,EAAEN,MAAMkB,WAAW;AACrDxC,8BAAkBC,GAAGC,QAAQtB,WAAW;AACxC8C,oBAAQpC,KAAKW,CAAC;AAAA,UAChB;AAAA,QACF;AAEA,YAAIyB,QAAQlE,SAAS,GAAG;AACtB4H,0BAAgB9F,KAAK,GAAGoC,OAAO;AAAA,QACjC;AAGA,YAAIF,uBAAGf,SAAS;AACd,gBAAMgG,WAAWnG,gBACfkC,aACAvF,GACAuE,EAAEf,SACFe,EAAEkF,cACFlF,EAAE7C,OACFC,UAAAA,CACF;AACAwG,0BAAgB9F,KAAKmH,QAAQ;AAAA,QAC/B;AAGA,aAAIjF,uBAAGmF,WAAUnF,EAAEmF,OAAOnJ,SAAS,GAAG;AACpC,gBAAMoJ,WAAgC,CAAA;AAEtC,qBAAWC,YAAYrF,EAAEmF,QAAQ;AAC/B,kBAAMF,WAAWnG,gBACfkC,aACAvF,GACA4J,SAASpG,SACToG,SAASlJ,UAAS6D,uBAAGkF,eACrBG,SAASlI,UAAS6C,uBAAG7C,QACrBC,WACF;AAEAgI,qBAASC,SAASC,IAAI,IAAIL;AAC1BrB,4BAAgB9F,KAAKmH,QAAQ;AAG7B,gBAAII,SAASE,YAAY,OAAO;AAC9BvE,0BAAYmD,YAAYc,QAAQ;AAAA,YAClC;AAAA,UACF;AAGA,cAAIjH,OAAOC,KAAKmH,QAAQ,EAAEpJ,SAAS,GAAG;AACpCP,cAAEyH,QAAQiC,OAAO,MAAMC,UAAU;AAAA,cAAEI,WAAW;AAAA,YAAA,CAAM,EAAE1F,MAAMkB,WAAW;AAAA,UACzE;AAAA,QACF;AAGAO,wBAAgB,IAAI;AACpB,YAAIvB,uBAAGyF,SAAS;AACd,cAAI;AAEF,kBAAMC,YAAY,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA;AAAA;AAAA,cAA0B;AAAA,YAAmB,CAAA;AACrE,kBAAMC,WAAW3F,EAAEyF;AAEnB,kBAAMG,eACJD,cAASC,eAATD,mBAAqBjD,IAAKmD,CAAAA,UAAU;AAAA,cAClCC,WAAWD,KAAKC;AAAAA,cAChBC,YAAY,IAAKL,UACfG,KAAKE,eAAe,YAChB,sBACAF,KAAKE,eAAe,SAClB,mBACA,kBAAkB,EACxB;AAAA,gBACAC,MAAMH,KAAKvJ,SAAS;AAAA,gBACpB2J,QAAQJ,KAAKvJ,SAAS;AAAA,gBACtB4J,OAAOL,KAAKK,SAAS;AAAA,gBACrB1J,SAASqJ,KAAKrJ,WAAW;AAAA,cAAA,CAC1B;AAAA,YAAA,QACI,CAAA;AAET,kBAAM2J,eACJR,cAASQ,eAATR,mBAAqBjD,IAAKmD,CAAAA,UAAU;AAAA,cAClCC,WAAWD,KAAKC;AAAAA,cAChBC,YAAY,IAAKL,UAAkBU,eAAe;AAAA,gBAChDC,aAAa,CAACR,KAAKS,SAAS;AAAA,gBAC5BC,UAAUV,KAAKU,YAAY;AAAA,cAAA,CAC5B;AAAA,YAAA,QACI,CAAA;AAET,kBAAMC,UAAWd,UAAkBe,aAAa;AAAA,cAC9CC,KAAKf,SAASe;AAAAA,cACdzD,aAAa0C,SAAS1C;AAAAA,cACtB2C;AAAAA,cACAO;AAAAA,cACAQ,SAAShB,SAASgB;AAAAA,cAClBC,SAASjB,SAASiB;AAAAA,YAAAA,CACnB;AAEDJ,oBAAQ1G,MAAMkB,WAAW;AAAA,UAC3B,SAASqB,GAAG;AAKV,kBAAMwE,SAASxE,aAAayE,QAAQzE,EAAE0E,UAAUpJ,OAAO0E,CAAC;AACxD,kBAAM0E,UACJ;AAEFzE,oBAAQC,KAAK,cAAcwE,SAAS1E,CAAC;AACrCd,4BAAgBwF,OAAO;AACvBrF,mDAAWsF,SAAS;AAAA,cAClBvG,MAAM;AAAA,cACNwG,cAAc,GAAGF,OAAO,KAAKF,MAAM;AAAA,cACnCK,MAAI7J,WAAMyE,cAANzE,mBAAiB6J,OAAM;AAAA,cAC3BC,eAAe;AAAA,cACfC,IAAIC,KAAKC,IAAAA;AAAAA,YAAI;AAAA,UAEjB;AAAA,QACF;AAGA,aAAItH,uBAAGuH,cAAa3D,gBAAgB5H,SAAS,GAAG;AAC9C,gBAAMwL,QAAQ/L,EAAEgM,aAAa7D,eAAe;AAC5C,gBAAM8D,SAASF,MAAMG,UAAAA;AACrB,cAAID,OAAOE,WAAW;AACpB5G,wBAAYuG,UAAUG,OAAOG,IAAI,GAAG,CAAC;AAAA,UACvC;AAAA,QACF,WAAW7H,uBAAGwC,QAAQ;AACpBxB,sBAAY8B,QAAQ9C,EAAEwC,QAAQxC,EAAEyC,QAAQzB,YAAY8G,SAAS;AAAA,QAC/D;AAAA,MACF,SAASC,KAAK;AAGZ,cAAMhB,UAAUgB,eAAejB,QAAQiB,IAAIhB,UAAU;AACrD1F,iBAAS0F,OAAO;AAChBrF,+CAAWsF,SAAS;AAAA,UAClBvG,MAAM;AAAA,UACNwG,cAAcF;AAAAA,UACdG,MAAI7J,WAAMyE,cAANzE,mBAAiB6J,OAAM;AAAA,UAC3BC,eAAe;AAAA,UACfC,IAAIC,KAAKC,IAAAA;AAAAA,QAAI;AAAA,MAEjB;AAAA,IACF;AAAA,EACF,CAAC;AAGDU,UAAAA,UAAU,MAAM;AACd,QAAIhH,aAAa;AACfA,kBAAYiH,OAAAA;AACZjH,oBAAc;AAAA,IAChB;AAAA,EACF,CAAC;AAED,SAAAkH,IAAAA,gBACGC,kBAAAA,mBAAiB;AAAA,IAChBC,OAAO;AAAA,IAAK,IACZC,WAAQ;AAAA,aAAEtI,aAAa8B,QAAQ;AAAA,IAAC;AAAA,IAChCyG,WAAS;AAAA,IAAA,IACTC,iBAAc;AAAA,aAAElL,MAAMkL;AAAAA,IAAc;AAAA,IAAA,IAAAC,WAAA;AAAA,UAAAC,OAAAC,IAAAA,eAAAC,OAAA,GAAAC,QAAAH,KAAAI,YAAA,CAAAC,OAAAC,KAAA,IAAAC,IAAAA,cAAAJ,MAAAK,WAAA,GAAAC,QAAAJ,MAAAG,aAAA,CAAAE,OAAAC,KAAA,IAAAJ,IAAAA,cAAAE,MAAAD,WAAA;AAAAI,iBAAAZ,MAAAP,IAAAA,gBAOjCoB,cAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAEnI,MAAAA;AAAAA,QAAO;AAAA,QAAA,IAAAoH,WAAA;AAAA,cAAAgB,QAAAd,IAAAA,eAAAe,MAAA;AAAAJ,cAAAA,OAAAG,OAAAtB,oBAIdwB,iBAAAA,kBAAgBC,IAAAA,WAAA;AAAA,YAAA,IACf5C,UAAO;AAAA,qBAAE,yBAAyB3F,OAAO;AAAA,YAAE;AAAA,YAC3CwI,SAAO;AAAA,UAAA,GAAA,MACHC,oBAAAA,mBAAmBhI,OAAAA,KAAY,CAAA,CAAE,CAAC,CAAA,CAAA;AAAA,iBAAA2H;AAAAA,QAAA;AAAA,MAAA,CAAA,GAAAV,OAAAC,KAAA;AAAAM,iBAAAZ,MAAAP,IAAAA,gBAI3CoB,cAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAE,CAACnI,MAAAA;AAAAA,QAAO;AAAA,QAAA,IAAAoH,WAAA;AAAA,iBAAA,CAAAN,IAAAA,gBAGjBoB,cAAI;AAAA,YAAA,IAACC,OAAI;AAAA,qBAAEjI,aAAAA;AAAAA,YAAc;AAAA,YAAA,IAAAkH,WAAA;AAAA,kBAAAsB,QAAApB,IAAAA,eAAAqB,OAAA,GAAAC,QAAAF,MAAAjB,YAAA,CAAAoB,OAAAC,IAAA,IAAAlB,IAAAA,cAAAgB,MAAAf,WAAA;AAAAgB,oBAAAhB;AAAAI,kBAAAA,OAAAS,OAKrBxI,cAAY2I,OAAAC,IAAA;AAAA,qBAAAJ;AAAAA,YAAA;AAAA,UAAA,CAAA,IAAA,MAAA;AAAA,gBAAAK,QAAAzB,IAAAA,eAAA0B,OAAA;AAAA,gBAAAC,QAIVtJ;AAAY,mBAAAsJ,UAAA,aAAAC,IAAAA,IAAAD,OAAAF,KAAA,IAAZpJ,eAAYoJ;AAAAI,gBAAAA,OAAAC,CAAAA,QAAA;;AAAA,kBAAAC,MAEfjJ,eACI;AAAA,gBAAEkJ,QAAQ;AAAA,gBAAQxE,OAAO;AAAA,gBAAQ,WAAW;AAAA,cAAA,IAC5C;AAAA,gBAAEwE,UAAQ7I,kBAAAA,mBAAU6I,WAAU;AAAA,gBAASxE,OAAO;AAAA,gBAAQ,WAAW;AAAA,cAAA,GAAGyE,OAEnE,gBAAgBnJ,WAAAA,IAAe,mBAAmB,EAAE;AAAEgJ,kBAAAnI,IAAAuI,IAAAA,MAAAT,OAAAM,KAAAD,IAAAnI,CAAA;AAAAsI,uBAAAH,IAAAK,KAAAC,IAAAA,UAAAX,OAAAK,IAAAK,IAAAF,IAAA;AAAA,qBAAAH;AAAAA,YAAA,GAAA;AAAA,cAAAnI,GAAA9D;AAAAA,cAAAsM,GAAAtM;AAAAA,YAAAA,CAAA;AAAA,mBAAA4L;AAAAA,UAAA,IAAA;AAAA,QAAA;AAAA,MAAA,CAAA,GAAAhB,OAAAC,KAAA;AAAAmB,UAAAA,OAAA,MAAA;;AAAAO,mBAAAA,UAAArC,MAjC1D,uHAAqH5G,kBAAAA,mBAAUkJ,cAAa,EAAE,IACnJvJ,WAAAA,IAAe,iCAAiC,EAAE,EAClD;AAAA,OAAA;AAAA,aAAAiH;AAAAA,IAAA;AAAA,EAAA,CAAA;AAqCV;;;;;;"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* v3.1.0: GeoJSON, choropleth, popups, multi-layer, PMTiles
|
|
5
5
|
*/
|
|
6
6
|
import { Component } from 'solid-js';
|
|
7
|
-
import type { UIComponent, MapComponentParams, MapPopupConfig } from '../types';
|
|
7
|
+
import type { UIComponent, MapComponentParams, MapGeoJSONStyle, MapPopupConfig } from '../types';
|
|
8
8
|
export interface MapRendererProps {
|
|
9
9
|
/**
|
|
10
10
|
* UIComponent containing map params
|
|
@@ -61,5 +61,10 @@ export declare function bindMarkerContent(m: any, marker: {
|
|
|
61
61
|
tooltip?: string;
|
|
62
62
|
popup?: string;
|
|
63
63
|
}, allowHtml: boolean): void;
|
|
64
|
+
/**
|
|
65
|
+
* Add a GeoJSON layer to the map with style and popup support.
|
|
66
|
+
* Returns the layer for bounds calculation.
|
|
67
|
+
*/
|
|
68
|
+
export declare function addGeoJSONLayer(mapInst: any, leaflet: any, geojson: unknown, style?: MapGeoJSONStyle, popup?: MapPopupConfig, allowHtml?: boolean): any;
|
|
64
69
|
export declare const MapRenderer: Component<MapRendererProps>;
|
|
65
70
|
//# sourceMappingURL=MapRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapRenderer.d.ts","sourceRoot":"","sources":["../../src/components/MapRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAA+C,MAAM,UAAU,CAAC;AAElF,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,
|
|
1
|
+
{"version":3,"file":"MapRenderer.d.ts","sourceRoot":"","sources":["../../src/components/MapRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAA+C,MAAM,UAAU,CAAC;AAElF,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAElB,eAAe,EACf,cAAc,EAGf,MAAM,UAAU,CAAC;AAYlB,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC;IAExB;;OAEG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAE5B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IAE5C;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAiED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,GAAG,EACZ,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,SAAS,UAAQ,GAChB,MAAM,GAAG,IAAI,CA+Bf;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,UAAQ,GAAG,MAAM,GAAG,SAAS,CAG9F;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,GAAG,EACN,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5C,SAAS,EAAE,OAAO,GACjB,IAAI,CAKN;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,OAAO,EAChB,KAAK,CAAC,EAAE,eAAe,EACvB,KAAK,CAAC,EAAE,cAAc,EACtB,SAAS,UAAQ,GAChB,GAAG,CA2BL;AA+BD,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,gBAAgB,CA+UnD,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { isServer, createComponent, getNextElement,
|
|
1
|
+
import { isServer, createComponent, getNextElement, getNextMarker, insert, mergeProps, use, effect, style, className, template } from "solid-js/web";
|
|
2
2
|
import { createSignal, createEffect, onCleanup, Show } from "solid-js";
|
|
3
3
|
import { useExpanded, ExpandableWrapper } from "./ExpandableWrapper.js";
|
|
4
4
|
import { DegradedFallback } from "./DegradedFallback.js";
|
|
5
5
|
import { mapToDegradedTable } from "../utils/degraded-projections.js";
|
|
6
|
+
import { escapeHtml } from "../utils/escape-html.js";
|
|
6
7
|
import { useTelemetry } from "../context/MCPUITelemetryContext.js";
|
|
7
8
|
var _tmpl$ = /* @__PURE__ */ template(`<div class=p-3>`), _tmpl$2 = /* @__PURE__ */ template(`<div role=alert class="m-2 rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200"><!$><!/> The base map is still shown.`), _tmpl$3 = /* @__PURE__ */ template(`<div>`), _tmpl$4 = /* @__PURE__ */ template(`<div><!$><!/><!$><!/>`);
|
|
8
9
|
let L = null;
|
|
@@ -65,9 +66,6 @@ function buildPopupContent(feature, popup, allowHtml = false) {
|
|
|
65
66
|
}
|
|
66
67
|
return parts.join("<br/>");
|
|
67
68
|
}
|
|
68
|
-
function escapeHtml(str) {
|
|
69
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
70
|
-
}
|
|
71
69
|
function popupSafeText(value, allowHtml = false) {
|
|
72
70
|
if (value == null) return void 0;
|
|
73
71
|
return allowHtml ? value : escapeHtml(value);
|
|
@@ -78,7 +76,7 @@ function bindMarkerContent(m, marker, allowHtml) {
|
|
|
78
76
|
const popup = popupSafeText(marker.popup, allowHtml);
|
|
79
77
|
if (popup) m.bindPopup(popup);
|
|
80
78
|
}
|
|
81
|
-
function addGeoJSONLayer(mapInst, leaflet, geojson, style2, popup) {
|
|
79
|
+
function addGeoJSONLayer(mapInst, leaflet, geojson, style2, popup, allowHtml = false) {
|
|
82
80
|
const styleFn = buildStyleFn(style2);
|
|
83
81
|
const layer = leaflet.geoJSON(geojson, {
|
|
84
82
|
style: styleFn,
|
|
@@ -94,7 +92,7 @@ function addGeoJSONLayer(mapInst, leaflet, geojson, style2, popup) {
|
|
|
94
92
|
});
|
|
95
93
|
},
|
|
96
94
|
onEachFeature: (feature, featureLayer) => {
|
|
97
|
-
const html = buildPopupContent(feature, popup);
|
|
95
|
+
const html = buildPopupContent(feature, popup, allowHtml);
|
|
98
96
|
if (html) {
|
|
99
97
|
featureLayer.bindPopup(html, {
|
|
100
98
|
maxWidth: 300
|
|
@@ -249,13 +247,13 @@ const MapRenderer = (props) => {
|
|
|
249
247
|
allBoundsLayers.push(...markers);
|
|
250
248
|
}
|
|
251
249
|
if (p == null ? void 0 : p.geojson) {
|
|
252
|
-
const geoLayer = addGeoJSONLayer(mapInstance, L, p.geojson, p.geojsonStyle, p.popup);
|
|
250
|
+
const geoLayer = addGeoJSONLayer(mapInstance, L, p.geojson, p.geojsonStyle, p.popup, allowHtml());
|
|
253
251
|
allBoundsLayers.push(geoLayer);
|
|
254
252
|
}
|
|
255
253
|
if ((p == null ? void 0 : p.layers) && p.layers.length > 0) {
|
|
256
254
|
const overlays = {};
|
|
257
255
|
for (const layerDef of p.layers) {
|
|
258
|
-
const geoLayer = addGeoJSONLayer(mapInstance, L, layerDef.geojson, layerDef.style || (p == null ? void 0 : p.geojsonStyle), layerDef.popup || (p == null ? void 0 : p.popup));
|
|
256
|
+
const geoLayer = addGeoJSONLayer(mapInstance, L, layerDef.geojson, layerDef.style || (p == null ? void 0 : p.geojsonStyle), layerDef.popup || (p == null ? void 0 : p.popup), allowHtml());
|
|
259
257
|
overlays[layerDef.name] = geoLayer;
|
|
260
258
|
allBoundsLayers.push(geoLayer);
|
|
261
259
|
if (layerDef.visible === false) {
|
|
@@ -420,6 +418,7 @@ const MapRenderer = (props) => {
|
|
|
420
418
|
};
|
|
421
419
|
export {
|
|
422
420
|
MapRenderer,
|
|
421
|
+
addGeoJSONLayer,
|
|
423
422
|
bindMarkerContent,
|
|
424
423
|
buildPopupContent,
|
|
425
424
|
popupSafeText
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapRenderer.js","sources":["../../src/components/MapRenderer.tsx"],"sourcesContent":["/**\n * MapRenderer - Interactive map Component\n * Sprint 6: Markers + clustering\n * v3.1.0: GeoJSON, choropleth, popups, multi-layer, PMTiles\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js';\nimport { isServer } from 'solid-js/web';\nimport type {\n UIComponent,\n MapComponentParams,\n MapClusterOptions,\n MapGeoJSONStyle,\n MapPopupConfig,\n MapLayer,\n MapPMTilesConfig,\n} from '../types';\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper';\nimport { DegradedFallback } from './DegradedFallback';\nimport { mapToDegradedTable } from '../utils/degraded-projections';\nimport { useTelemetry } from '../context/MCPUITelemetryContext';\n\n// Lazy load leaflet (it doesn't support SSR well)\nlet L: any = null;\n// Track if marker cluster CSS has been loaded\nlet clusterCssLoaded = false;\n\nexport interface MapRendererProps {\n /**\n * UIComponent containing map params\n */\n component?: UIComponent;\n\n /**\n * Direct map params\n */\n params?: MapComponentParams;\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible';\n\n /**\n * Trust marker / popup content as raw HTML (v6.10.0, audit P1.2).\n *\n * Leaflet renders bound tooltip/popup strings as HTML, so `marker.tooltip`,\n * `marker.popup` and a GeoJSON `popup.template` are XSS vectors when the\n * payload is untrusted (the default for an LLM/connector-driven public\n * package). **Default `false`** → those are escaped as plain text, and\n * `popup.template` is ignored in favour of the safe auto-generated popup.\n *\n * This is a **host-level** trust decision, deliberately NOT a payload field\n * (a malicious payload could just set its own flag). The\n * `<UIResourceRenderer>` path never sets it, so payload-driven maps are\n * always text-safe. A host rendering `<MapRenderer>` directly with trusted\n * data may set `allowHtmlPopups` to restore rich HTML popups. The\n * auto-generated popup (`titleField` / `fields`) is safe-by-construction\n * and unaffected either way.\n */\n allowHtmlPopups?: boolean;\n}\n\n// ─── Helpers ────────────────────────────────────────────────\n\n/**\n * Resolve choropleth color for a feature based on property value and scale stops.\n */\nfunction getChoroplethColor(\n value: unknown,\n scale: Array<[number, string]>,\n fallback: string\n): string {\n if (value == null || typeof value !== 'number' || !isFinite(value)) return fallback;\n\n // Scale is sorted ascending: [[0, '#eff3ff'], [100, '#084594']]\n if (scale.length === 0) return fallback;\n if (value <= scale[0][0]) return scale[0][1];\n if (value >= scale[scale.length - 1][0]) return scale[scale.length - 1][1];\n\n // Find surrounding stops and interpolate (use upper bracket color)\n for (let i = 1; i < scale.length; i++) {\n if (value <= scale[i][0]) return scale[i][1];\n }\n return scale[scale.length - 1][1];\n}\n\n/**\n * Build a Leaflet style function from MapGeoJSONStyle config.\n */\nfunction buildStyleFn(\n style: MapGeoJSONStyle | undefined\n): (feature: any) => Record<string, unknown> {\n if (!style) {\n return () => ({\n fillColor: '#3388ff',\n fillOpacity: 0.6,\n color: '#333',\n weight: 1,\n opacity: 1,\n });\n }\n\n return (feature: any) => {\n let fillColor = style.fillColor || '#3388ff';\n\n // Choropleth: override fillColor based on feature property\n if (style.choroplethField && style.choroplethScale && feature?.properties) {\n const val = feature.properties[style.choroplethField];\n fillColor = getChoroplethColor(\n val,\n style.choroplethScale,\n style.choroplethFallback || '#ccc'\n );\n }\n\n return {\n fillColor,\n fillOpacity: style.fillOpacity ?? 0.6,\n color: style.strokeColor || '#333',\n weight: style.strokeWeight ?? 1,\n opacity: style.strokeOpacity ?? 1,\n };\n };\n}\n\n/**\n * Build popup HTML from a feature's properties using popup config.\n *\n * `allowHtml` (audit P1.2) gates the raw-HTML `popup.template`: it is honored\n * only when the host trusts the payload. On the default (untrusted) path the\n * template is ignored and we fall through to the auto-generated popup, whose\n * structure is renderer-authored and whose values are always escaped — safe\n * by construction. Even in the trusted path, substituted `{{prop}}` values\n * are escaped (they are data, not markup).\n */\nexport function buildPopupContent(\n feature: any,\n popup: MapPopupConfig | undefined,\n allowHtml = false\n): string | null {\n if (!popup || !feature?.properties) return null;\n const props = feature.properties;\n\n // Custom template — raw HTML, so trusted-host only.\n if (allowHtml && popup.template) {\n return popup.template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\n const val = props[key];\n return val != null ? escapeHtml(String(val)) : '';\n });\n }\n\n // Auto-generated popup\n const parts: string[] = [];\n\n if (popup.titleField && props[popup.titleField] != null) {\n parts.push(`<strong>${escapeHtml(String(props[popup.titleField]))}</strong>`);\n }\n\n const fields = popup.fields || Object.keys(props).slice(0, 8);\n for (const key of fields) {\n if (key === popup.titleField) continue;\n const val = props[key];\n if (val == null) continue;\n const formatted = typeof val === 'number' ? val.toLocaleString('fr-FR') : String(val);\n parts.push(\n `<span style=\"color:#666;font-size:11px\">${escapeHtml(key)}</span>: ${escapeHtml(formatted)}`\n );\n }\n\n return parts.join('<br/>');\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\n/**\n * Resolve a marker's tooltip/popup string for binding (audit P1.2). Leaflet\n * renders bound strings as HTML; `marker.tooltip` / `marker.popup` come from\n * the (untrusted) payload, so they are escaped to plain text unless the host\n * has opted into raw HTML via `allowHtmlPopups`. Pure + exported for tests.\n */\nexport function popupSafeText(value: string | undefined, allowHtml = false): string | undefined {\n if (value == null) return undefined;\n return allowHtml ? value : escapeHtml(value);\n}\n\n/** Bind a marker's tooltip + popup, escaping by default (see popupSafeText). */\nexport function bindMarkerContent(\n m: any,\n marker: { tooltip?: string; popup?: string },\n allowHtml: boolean\n): void {\n const tooltip = popupSafeText(marker.tooltip, allowHtml);\n if (tooltip) m.bindTooltip(tooltip);\n const popup = popupSafeText(marker.popup, allowHtml);\n if (popup) m.bindPopup(popup);\n}\n\n/**\n * Add a GeoJSON layer to the map with style and popup support.\n * Returns the layer for bounds calculation.\n */\nfunction addGeoJSONLayer(\n mapInst: any,\n leaflet: any,\n geojson: unknown,\n style?: MapGeoJSONStyle,\n popup?: MapPopupConfig\n): any {\n const styleFn = buildStyleFn(style);\n\n const layer = leaflet.geoJSON(geojson, {\n style: styleFn,\n pointToLayer: (feature: any, latlng: any) => {\n // Render points as circle markers for consistency\n const s = styleFn(feature);\n return leaflet.circleMarker(latlng, {\n radius: 6,\n fillColor: s.fillColor,\n fillOpacity: s.fillOpacity,\n color: s.color,\n weight: s.weight,\n opacity: s.opacity,\n });\n },\n onEachFeature: (feature: any, featureLayer: any) => {\n const html = buildPopupContent(feature, popup);\n if (html) {\n featureLayer.bindPopup(html, { maxWidth: 300 });\n }\n },\n });\n\n layer.addTo(mapInst);\n return layer;\n}\n\n// ─── Component ──────────────────────────────────────────────\n\n/**\n * Build a GeoJSON FeatureCollection from the map's `markers` (and any\n * inlined GeoJSON layers, when present). Used by the \"Copy data\" button\n * shipped via `<ExpandableWrapper>` (v6.2.0). Best-effort — clusters,\n * tile layers, and choropleth-only data don't get round-tripped.\n */\nfunction mapToGeoJSON(p: MapComponentParams | undefined): string {\n if (!p) return '{\"type\":\"FeatureCollection\",\"features\":[]}';\n const features: any[] = [];\n for (const marker of p.markers ?? []) {\n const pos: any = marker.position as any;\n // Accept both [lat, lng] tuple and {lat, lng} object shapes (v5.0.2 spec)\n const lat = Array.isArray(pos) ? pos[0] : pos?.lat;\n const lng = Array.isArray(pos) ? pos[1] : pos?.lng;\n if (typeof lat !== 'number' || typeof lng !== 'number') continue;\n features.push({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [lng, lat] },\n properties: {\n ...(marker.tooltip ? { tooltip: marker.tooltip } : {}),\n ...(marker.popup ? { popup: marker.popup } : {}),\n },\n });\n }\n return JSON.stringify({ type: 'FeatureCollection', features }, null, 2);\n}\n\nexport const MapRenderer: Component<MapRendererProps> = (props) => {\n let mapContainer: HTMLDivElement | undefined;\n let mapInstance: any = null;\n const [isLeafletLoaded, setIsLeafletLoaded] = createSignal(false);\n const [error, setError] = createSignal<string | null>(null);\n // PMTiles is an optional overlay on top of the base map. When it fails we\n // keep the base map but surface a visible notice (audit P1.3) instead of a\n // silent console.warn that leaves the user with an unexplained empty layer.\n const [pmtilesError, setPmtilesError] = createSignal<string | null>(null);\n const isExpanded = useExpanded();\n const telemetry = useTelemetry();\n // Host-level trust for raw HTML in marker/popup content (audit P1.2).\n // Default false → tooltip/popup escaped, GeoJSON `popup.template` ignored.\n const allowHtml = () => props.allowHtmlPopups === true;\n\n const params = () => props.params || (props.component?.params as MapComponentParams);\n\n // v6.2.0 — Leaflet has to be told to re-measure when its container\n // resizes (e.g. transitioning to fullscreen via ExpandableWrapper).\n // We give the DOM a tick to settle the new dimensions, then ask\n // Leaflet to reflow tiles.\n createEffect(() => {\n const expanded = isExpanded();\n if (!mapInstance) return;\n // Read the signal so the effect re-runs on toggle ; the value is\n // observed for its side effects on layout.\n void expanded;\n setTimeout(() => mapInstance?.invalidateSize?.(), 100);\n });\n\n // Initialize Map\n createEffect(async () => {\n if (isServer) return; // Don't run on server\n\n if (!L) {\n try {\n const module = await import('leaflet');\n L = module.default || module;\n await import('leaflet/dist/leaflet.css'); // Import CSS\n setIsLeafletLoaded(true);\n } catch (e) {\n console.warn('Failed to load leaflet', e);\n setError('Map library could not be loaded.');\n return;\n }\n } else {\n setIsLeafletLoaded(true);\n }\n\n if (isLeafletLoaded() && mapContainer && !mapInstance) {\n const p = params();\n const center = p?.center || [51.505, -0.09]; // Default to London\n const zoom = p?.zoom || 13;\n\n mapInstance = L.map(mapContainer, {\n zoomControl: p?.zoomControl !== false,\n scrollWheelZoom: p?.scrollWheelZoom !== false,\n attributionControl: false,\n }).setView(center, zoom);\n\n // Add OpenStreetMap tile layer\n const tileLayerUrl = p?.tileLayer || 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';\n L.tileLayer(tileLayerUrl, {\n attribution:\n p?.attribution ||\n '© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors',\n }).addTo(mapInstance);\n\n if (p?.attribution !== '') {\n L.control.attribution({ prefix: false }).addTo(mapInstance);\n }\n\n // Fix marker icons (Leaflet issue with bundlers)\n delete (L.Icon.Default.prototype as any)._getIconUrl;\n L.Icon.Default.mergeOptions({\n iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',\n iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',\n shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',\n });\n }\n\n // Update markers and view\n if (mapInstance && L) {\n try {\n const p = params();\n const allBoundsLayers: any[] = [];\n\n // Clear existing layers (markers, cluster groups, GeoJSON)\n mapInstance.eachLayer((layer: any) => {\n if (\n layer instanceof L.Marker ||\n layer instanceof L.GeoJSON ||\n layer instanceof L.CircleMarker ||\n layer._group ||\n layer._featureGroup\n ) {\n mapInstance.removeLayer(layer);\n }\n });\n\n // ─── Markers (legacy) ────────────────────────\n const markers: any[] = [];\n const shouldCluster = p?.clustering && p?.markers && p.markers.length > 0;\n\n if (shouldCluster) {\n try {\n await import('leaflet.markercluster');\n if (!clusterCssLoaded) {\n await import('leaflet.markercluster/dist/MarkerCluster.css');\n await import('leaflet.markercluster/dist/MarkerCluster.Default.css');\n clusterCssLoaded = true;\n }\n const clusterOpts: MapClusterOptions =\n typeof p.clustering === 'object' ? p.clustering : {};\n const clusterGroup = (L as any).markerClusterGroup({\n maxClusterRadius: clusterOpts.maxClusterRadius ?? 80,\n spiderfyOnMaxZoom: clusterOpts.spiderfyOnMaxZoom ?? true,\n showCoverageOnHover: clusterOpts.showCoverageOnHover ?? true,\n disableClusteringAtZoom: clusterOpts.disableClusteringAtZoom,\n animate: clusterOpts.animateAddingMarkers ?? true,\n });\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position);\n bindMarkerContent(m, marker, allowHtml());\n clusterGroup.addLayer(m);\n markers.push(m);\n });\n mapInstance.addLayer(clusterGroup);\n } catch {\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position).addTo(mapInstance);\n bindMarkerContent(m, marker, allowHtml());\n markers.push(m);\n });\n }\n } else {\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position).addTo(mapInstance);\n bindMarkerContent(m, marker, allowHtml());\n markers.push(m);\n });\n }\n\n if (markers.length > 0) {\n allBoundsLayers.push(...markers);\n }\n\n // ─── GeoJSON (v3.1.0) ───────────────────────\n if (p?.geojson) {\n const geoLayer = addGeoJSONLayer(mapInstance, L, p.geojson, p.geojsonStyle, p.popup);\n allBoundsLayers.push(geoLayer);\n }\n\n // ─── Named layers (v3.1.0) ──────────────────\n if (p?.layers && p.layers.length > 0) {\n const overlays: Record<string, any> = {};\n\n for (const layerDef of p.layers) {\n const geoLayer = addGeoJSONLayer(\n mapInstance,\n L,\n layerDef.geojson,\n layerDef.style || p?.geojsonStyle,\n layerDef.popup || p?.popup\n );\n\n overlays[layerDef.name] = geoLayer;\n allBoundsLayers.push(geoLayer);\n\n // Respect initial visibility\n if (layerDef.visible === false) {\n mapInstance.removeLayer(geoLayer);\n }\n }\n\n // Add layer control if multiple layers\n if (Object.keys(overlays).length > 1) {\n L.control.layers(null, overlays, { collapsed: true }).addTo(mapInstance);\n }\n }\n\n // ─── PMTiles (v3.1.0) ────────────────────────\n setPmtilesError(null);\n if (p?.pmtiles) {\n try {\n // @ts-ignore — optional peer dependency, may not be installed\n const protomaps = await import(/* @vite-ignore */ 'protomaps-leaflet');\n const pmConfig = p.pmtiles;\n\n const paintRules =\n pmConfig.paintRules?.map((rule) => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any)[\n rule.symbolizer === 'polygon'\n ? 'PolygonSymbolizer'\n : rule.symbolizer === 'line'\n ? 'LineSymbolizer'\n : 'CircleSymbolizer'\n ]({\n fill: rule.color || '#3388ff',\n stroke: rule.color || '#333',\n width: rule.width ?? 1,\n opacity: rule.opacity ?? 0.6,\n }),\n })) || [];\n\n const labelRules =\n pmConfig.labelRules?.map((rule) => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any).TextSymbolizer({\n label_props: [rule.textField],\n fontSize: rule.fontSize ?? 12,\n }),\n })) || [];\n\n const pmLayer = (protomaps as any).leafletLayer({\n url: pmConfig.url,\n attribution: pmConfig.attribution,\n paintRules,\n labelRules,\n maxZoom: pmConfig.maxZoom,\n minZoom: pmConfig.minZoom,\n });\n\n pmLayer.addTo(mapInstance);\n } catch (e) {\n // P1.3 — do NOT fail silently. Keep the base map, but surface a\n // visible notice and report a renderer error via telemetry. The\n // most common cause is the optional `protomaps-leaflet` peer not\n // being installed.\n const detail = e instanceof Error ? e.message : String(e);\n const message =\n 'PMTiles layer unavailable — the optional \"protomaps-leaflet\" ' +\n 'peer dependency failed to load or render.';\n console.warn('[MCP-UI] ' + message, e);\n setPmtilesError(message);\n telemetry?.dispatch({\n type: 'render:error',\n errorMessage: `${message} (${detail})`,\n id: props.component?.id ?? '',\n componentType: 'map',\n ts: Date.now(),\n });\n }\n }\n\n // ─── Fit bounds ─────────────────────────────\n if (p?.fitBounds && allBoundsLayers.length > 0) {\n const group = L.featureGroup(allBoundsLayers);\n const bounds = group.getBounds();\n if (bounds.isValid()) {\n mapInstance.fitBounds(bounds.pad(0.1));\n }\n } else if (p?.center) {\n mapInstance.setView(p.center, p.zoom || mapInstance.getZoom());\n }\n } catch (err) {\n // Fallback ladder (P2.5): a Leaflet drawing failure degrades to\n // the coordinate table below instead of a blank/partial map.\n const message = err instanceof Error ? err.message : 'Failed to render map';\n setError(message);\n telemetry?.dispatch({\n type: 'render:error',\n errorMessage: message,\n id: props.component?.id ?? '',\n componentType: 'map',\n ts: Date.now(),\n });\n }\n }\n });\n\n // Cleanup\n onCleanup(() => {\n if (mapInstance) {\n mapInstance.remove();\n mapInstance = null;\n }\n });\n\n return (\n <ExpandableWrapper\n title={'Map'}\n copyData={mapToGeoJSON(params())}\n copyLabel=\"Copy markers as GeoJSON\"\n toolbarVariant={props.toolbarVariant}\n >\n <div\n class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${params()?.className || ''} ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}\n >\n <Show when={error()}>\n {/* Fallback ladder (P2.5): degrade to a coordinate table\n rather than a bare error string. */}\n <div class=\"p-3\">\n <DegradedFallback\n message={`Map rendering failed: ${error()}`}\n caption=\"Showing the map data as a coordinate table — the interactive map is unavailable.\"\n {...mapToDegradedTable(params() ?? {})}\n />\n </div>\n </Show>\n <Show when={!error()}>\n {/* P1.3 — visible notice when the PMTiles overlay fails but the\n base map is still usable. */}\n <Show when={pmtilesError()}>\n <div\n role=\"alert\"\n class=\"m-2 rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200\"\n >\n {pmtilesError()} The base map is still shown.\n </div>\n </Show>\n <div\n ref={mapContainer}\n style={\n isExpanded()\n ? { height: '100%', width: '100%', 'z-index': 0 }\n : { height: params()?.height || '400px', width: '100%', 'z-index': 0 }\n }\n class={`relative z-0 ${isExpanded() ? 'flex-1 min-h-0' : ''}`}\n />\n </Show>\n </div>\n </ExpandableWrapper>\n );\n};\n"],"names":["L","clusterCssLoaded","getChoroplethColor","value","scale","fallback","isFinite","length","i","buildStyleFn","style","fillColor","fillOpacity","color","weight","opacity","feature","choroplethField","choroplethScale","properties","val","choroplethFallback","strokeColor","strokeWeight","strokeOpacity","buildPopupContent","popup","allowHtml","props","template","replace","_","key","escapeHtml","String","parts","titleField","push","fields","Object","keys","slice","formatted","toLocaleString","join","str","popupSafeText","undefined","bindMarkerContent","m","marker","tooltip","bindTooltip","bindPopup","addGeoJSONLayer","mapInst","leaflet","geojson","styleFn","layer","geoJSON","pointToLayer","latlng","s","circleMarker","radius","onEachFeature","featureLayer","html","maxWidth","addTo","mapToGeoJSON","p","features","markers","pos","position","lat","Array","isArray","lng","type","geometry","coordinates","JSON","stringify","MapRenderer","mapContainer","mapInstance","isLeafletLoaded","setIsLeafletLoaded","createSignal","error","setError","pmtilesError","setPmtilesError","isExpanded","useExpanded","telemetry","useTelemetry","allowHtmlPopups","params","component","createEffect","setTimeout","invalidateSize","isServer","module","default","e","console","warn","center","zoom","map","zoomControl","scrollWheelZoom","attributionControl","setView","tileLayerUrl","tileLayer","attribution","control","prefix","Icon","Default","prototype","_getIconUrl","mergeOptions","iconRetinaUrl","iconUrl","shadowUrl","allBoundsLayers","eachLayer","Marker","GeoJSON","CircleMarker","_group","_featureGroup","removeLayer","shouldCluster","clustering","clusterOpts","clusterGroup","markerClusterGroup","maxClusterRadius","spiderfyOnMaxZoom","showCoverageOnHover","disableClusteringAtZoom","animate","animateAddingMarkers","forEach","addLayer","geoLayer","geojsonStyle","layers","overlays","layerDef","name","visible","collapsed","pmtiles","protomaps","pmConfig","paintRules","rule","dataLayer","symbolizer","fill","stroke","width","labelRules","TextSymbolizer","label_props","textField","fontSize","pmLayer","leafletLayer","url","maxZoom","minZoom","detail","Error","message","dispatch","errorMessage","id","componentType","ts","Date","now","fitBounds","group","featureGroup","bounds","getBounds","isValid","pad","getZoom","err","onCleanup","remove","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$2","_$getNextMarker","nextSibling","_el$0","_el$1","_co$3","_$insert","Show","when","_el$2","_tmpl$","DegradedFallback","_$mergeProps","caption","mapToDegradedTable","_el$3","_tmpl$2","_el$5","_el$6","_co$","_el$7","_tmpl$3","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","_$style","t","_$className","className"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MapRenderer.js","sources":["../../src/components/MapRenderer.tsx"],"sourcesContent":["/**\n * MapRenderer - Interactive map Component\n * Sprint 6: Markers + clustering\n * v3.1.0: GeoJSON, choropleth, popups, multi-layer, PMTiles\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js';\nimport { isServer } from 'solid-js/web';\nimport type {\n UIComponent,\n MapComponentParams,\n MapClusterOptions,\n MapGeoJSONStyle,\n MapPopupConfig,\n MapLayer,\n MapPMTilesConfig,\n} from '../types';\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper';\nimport { DegradedFallback } from './DegradedFallback';\nimport { mapToDegradedTable } from '../utils/degraded-projections';\nimport { escapeHtml } from '../utils/escape-html';\nimport { useTelemetry } from '../context/MCPUITelemetryContext';\n\n// Lazy load leaflet (it doesn't support SSR well)\nlet L: any = null;\n// Track if marker cluster CSS has been loaded\nlet clusterCssLoaded = false;\n\nexport interface MapRendererProps {\n /**\n * UIComponent containing map params\n */\n component?: UIComponent;\n\n /**\n * Direct map params\n */\n params?: MapComponentParams;\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible';\n\n /**\n * Trust marker / popup content as raw HTML (v6.10.0, audit P1.2).\n *\n * Leaflet renders bound tooltip/popup strings as HTML, so `marker.tooltip`,\n * `marker.popup` and a GeoJSON `popup.template` are XSS vectors when the\n * payload is untrusted (the default for an LLM/connector-driven public\n * package). **Default `false`** → those are escaped as plain text, and\n * `popup.template` is ignored in favour of the safe auto-generated popup.\n *\n * This is a **host-level** trust decision, deliberately NOT a payload field\n * (a malicious payload could just set its own flag). The\n * `<UIResourceRenderer>` path never sets it, so payload-driven maps are\n * always text-safe. A host rendering `<MapRenderer>` directly with trusted\n * data may set `allowHtmlPopups` to restore rich HTML popups. The\n * auto-generated popup (`titleField` / `fields`) is safe-by-construction\n * and unaffected either way.\n */\n allowHtmlPopups?: boolean;\n}\n\n// ─── Helpers ────────────────────────────────────────────────\n\n/**\n * Resolve choropleth color for a feature based on property value and scale stops.\n */\nfunction getChoroplethColor(\n value: unknown,\n scale: Array<[number, string]>,\n fallback: string\n): string {\n if (value == null || typeof value !== 'number' || !isFinite(value)) return fallback;\n\n // Scale is sorted ascending: [[0, '#eff3ff'], [100, '#084594']]\n if (scale.length === 0) return fallback;\n if (value <= scale[0][0]) return scale[0][1];\n if (value >= scale[scale.length - 1][0]) return scale[scale.length - 1][1];\n\n // Find surrounding stops and interpolate (use upper bracket color)\n for (let i = 1; i < scale.length; i++) {\n if (value <= scale[i][0]) return scale[i][1];\n }\n return scale[scale.length - 1][1];\n}\n\n/**\n * Build a Leaflet style function from MapGeoJSONStyle config.\n */\nfunction buildStyleFn(\n style: MapGeoJSONStyle | undefined\n): (feature: any) => Record<string, unknown> {\n if (!style) {\n return () => ({\n fillColor: '#3388ff',\n fillOpacity: 0.6,\n color: '#333',\n weight: 1,\n opacity: 1,\n });\n }\n\n return (feature: any) => {\n let fillColor = style.fillColor || '#3388ff';\n\n // Choropleth: override fillColor based on feature property\n if (style.choroplethField && style.choroplethScale && feature?.properties) {\n const val = feature.properties[style.choroplethField];\n fillColor = getChoroplethColor(\n val,\n style.choroplethScale,\n style.choroplethFallback || '#ccc'\n );\n }\n\n return {\n fillColor,\n fillOpacity: style.fillOpacity ?? 0.6,\n color: style.strokeColor || '#333',\n weight: style.strokeWeight ?? 1,\n opacity: style.strokeOpacity ?? 1,\n };\n };\n}\n\n/**\n * Build popup HTML from a feature's properties using popup config.\n *\n * `allowHtml` (audit P1.2) gates the raw-HTML `popup.template`: it is honored\n * only when the host trusts the payload. On the default (untrusted) path the\n * template is ignored and we fall through to the auto-generated popup, whose\n * structure is renderer-authored and whose values are always escaped — safe\n * by construction. Even in the trusted path, substituted `{{prop}}` values\n * are escaped (they are data, not markup).\n */\nexport function buildPopupContent(\n feature: any,\n popup: MapPopupConfig | undefined,\n allowHtml = false\n): string | null {\n if (!popup || !feature?.properties) return null;\n const props = feature.properties;\n\n // Custom template — raw HTML, so trusted-host only.\n if (allowHtml && popup.template) {\n return popup.template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\n const val = props[key];\n return val != null ? escapeHtml(String(val)) : '';\n });\n }\n\n // Auto-generated popup\n const parts: string[] = [];\n\n if (popup.titleField && props[popup.titleField] != null) {\n parts.push(`<strong>${escapeHtml(String(props[popup.titleField]))}</strong>`);\n }\n\n const fields = popup.fields || Object.keys(props).slice(0, 8);\n for (const key of fields) {\n if (key === popup.titleField) continue;\n const val = props[key];\n if (val == null) continue;\n const formatted = typeof val === 'number' ? val.toLocaleString('fr-FR') : String(val);\n parts.push(\n `<span style=\"color:#666;font-size:11px\">${escapeHtml(key)}</span>: ${escapeHtml(formatted)}`\n );\n }\n\n return parts.join('<br/>');\n}\n\n/**\n * Resolve a marker's tooltip/popup string for binding (audit P1.2). Leaflet\n * renders bound strings as HTML; `marker.tooltip` / `marker.popup` come from\n * the (untrusted) payload, so they are escaped to plain text unless the host\n * has opted into raw HTML via `allowHtmlPopups`. Pure + exported for tests.\n */\nexport function popupSafeText(value: string | undefined, allowHtml = false): string | undefined {\n if (value == null) return undefined;\n return allowHtml ? value : escapeHtml(value);\n}\n\n/** Bind a marker's tooltip + popup, escaping by default (see popupSafeText). */\nexport function bindMarkerContent(\n m: any,\n marker: { tooltip?: string; popup?: string },\n allowHtml: boolean\n): void {\n const tooltip = popupSafeText(marker.tooltip, allowHtml);\n if (tooltip) m.bindTooltip(tooltip);\n const popup = popupSafeText(marker.popup, allowHtml);\n if (popup) m.bindPopup(popup);\n}\n\n/**\n * Add a GeoJSON layer to the map with style and popup support.\n * Returns the layer for bounds calculation.\n */\nexport function addGeoJSONLayer(\n mapInst: any,\n leaflet: any,\n geojson: unknown,\n style?: MapGeoJSONStyle,\n popup?: MapPopupConfig,\n allowHtml = false\n): any {\n const styleFn = buildStyleFn(style);\n\n const layer = leaflet.geoJSON(geojson, {\n style: styleFn,\n pointToLayer: (feature: any, latlng: any) => {\n // Render points as circle markers for consistency\n const s = styleFn(feature);\n return leaflet.circleMarker(latlng, {\n radius: 6,\n fillColor: s.fillColor,\n fillOpacity: s.fillOpacity,\n color: s.color,\n weight: s.weight,\n opacity: s.opacity,\n });\n },\n onEachFeature: (feature: any, featureLayer: any) => {\n const html = buildPopupContent(feature, popup, allowHtml);\n if (html) {\n featureLayer.bindPopup(html, { maxWidth: 300 });\n }\n },\n });\n\n layer.addTo(mapInst);\n return layer;\n}\n\n// ─── Component ──────────────────────────────────────────────\n\n/**\n * Build a GeoJSON FeatureCollection from the map's `markers` (and any\n * inlined GeoJSON layers, when present). Used by the \"Copy data\" button\n * shipped via `<ExpandableWrapper>` (v6.2.0). Best-effort — clusters,\n * tile layers, and choropleth-only data don't get round-tripped.\n */\nfunction mapToGeoJSON(p: MapComponentParams | undefined): string {\n if (!p) return '{\"type\":\"FeatureCollection\",\"features\":[]}';\n const features: any[] = [];\n for (const marker of p.markers ?? []) {\n const pos: any = marker.position as any;\n // Accept both [lat, lng] tuple and {lat, lng} object shapes (v5.0.2 spec)\n const lat = Array.isArray(pos) ? pos[0] : pos?.lat;\n const lng = Array.isArray(pos) ? pos[1] : pos?.lng;\n if (typeof lat !== 'number' || typeof lng !== 'number') continue;\n features.push({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [lng, lat] },\n properties: {\n ...(marker.tooltip ? { tooltip: marker.tooltip } : {}),\n ...(marker.popup ? { popup: marker.popup } : {}),\n },\n });\n }\n return JSON.stringify({ type: 'FeatureCollection', features }, null, 2);\n}\n\nexport const MapRenderer: Component<MapRendererProps> = (props) => {\n let mapContainer: HTMLDivElement | undefined;\n let mapInstance: any = null;\n const [isLeafletLoaded, setIsLeafletLoaded] = createSignal(false);\n const [error, setError] = createSignal<string | null>(null);\n // PMTiles is an optional overlay on top of the base map. When it fails we\n // keep the base map but surface a visible notice (audit P1.3) instead of a\n // silent console.warn that leaves the user with an unexplained empty layer.\n const [pmtilesError, setPmtilesError] = createSignal<string | null>(null);\n const isExpanded = useExpanded();\n const telemetry = useTelemetry();\n // Host-level trust for raw HTML in marker/popup content (audit P1.2).\n // Default false → tooltip/popup escaped, GeoJSON `popup.template` ignored.\n const allowHtml = () => props.allowHtmlPopups === true;\n\n const params = () => props.params || (props.component?.params as MapComponentParams);\n\n // v6.2.0 — Leaflet has to be told to re-measure when its container\n // resizes (e.g. transitioning to fullscreen via ExpandableWrapper).\n // We give the DOM a tick to settle the new dimensions, then ask\n // Leaflet to reflow tiles.\n createEffect(() => {\n const expanded = isExpanded();\n if (!mapInstance) return;\n // Read the signal so the effect re-runs on toggle ; the value is\n // observed for its side effects on layout.\n void expanded;\n setTimeout(() => mapInstance?.invalidateSize?.(), 100);\n });\n\n // Initialize Map\n createEffect(async () => {\n if (isServer) return; // Don't run on server\n\n if (!L) {\n try {\n const module = await import('leaflet');\n L = module.default || module;\n await import('leaflet/dist/leaflet.css'); // Import CSS\n setIsLeafletLoaded(true);\n } catch (e) {\n console.warn('Failed to load leaflet', e);\n setError('Map library could not be loaded.');\n return;\n }\n } else {\n setIsLeafletLoaded(true);\n }\n\n if (isLeafletLoaded() && mapContainer && !mapInstance) {\n const p = params();\n const center = p?.center || [51.505, -0.09]; // Default to London\n const zoom = p?.zoom || 13;\n\n mapInstance = L.map(mapContainer, {\n zoomControl: p?.zoomControl !== false,\n scrollWheelZoom: p?.scrollWheelZoom !== false,\n attributionControl: false,\n }).setView(center, zoom);\n\n // Add OpenStreetMap tile layer\n const tileLayerUrl = p?.tileLayer || 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';\n L.tileLayer(tileLayerUrl, {\n attribution:\n p?.attribution ||\n '© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors',\n }).addTo(mapInstance);\n\n if (p?.attribution !== '') {\n L.control.attribution({ prefix: false }).addTo(mapInstance);\n }\n\n // Fix marker icons (Leaflet issue with bundlers)\n delete (L.Icon.Default.prototype as any)._getIconUrl;\n L.Icon.Default.mergeOptions({\n iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',\n iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',\n shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',\n });\n }\n\n // Update markers and view\n if (mapInstance && L) {\n try {\n const p = params();\n const allBoundsLayers: any[] = [];\n\n // Clear existing layers (markers, cluster groups, GeoJSON)\n mapInstance.eachLayer((layer: any) => {\n if (\n layer instanceof L.Marker ||\n layer instanceof L.GeoJSON ||\n layer instanceof L.CircleMarker ||\n layer._group ||\n layer._featureGroup\n ) {\n mapInstance.removeLayer(layer);\n }\n });\n\n // ─── Markers (legacy) ────────────────────────\n const markers: any[] = [];\n const shouldCluster = p?.clustering && p?.markers && p.markers.length > 0;\n\n if (shouldCluster) {\n try {\n await import('leaflet.markercluster');\n if (!clusterCssLoaded) {\n await import('leaflet.markercluster/dist/MarkerCluster.css');\n await import('leaflet.markercluster/dist/MarkerCluster.Default.css');\n clusterCssLoaded = true;\n }\n const clusterOpts: MapClusterOptions =\n typeof p.clustering === 'object' ? p.clustering : {};\n const clusterGroup = (L as any).markerClusterGroup({\n maxClusterRadius: clusterOpts.maxClusterRadius ?? 80,\n spiderfyOnMaxZoom: clusterOpts.spiderfyOnMaxZoom ?? true,\n showCoverageOnHover: clusterOpts.showCoverageOnHover ?? true,\n disableClusteringAtZoom: clusterOpts.disableClusteringAtZoom,\n animate: clusterOpts.animateAddingMarkers ?? true,\n });\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position);\n bindMarkerContent(m, marker, allowHtml());\n clusterGroup.addLayer(m);\n markers.push(m);\n });\n mapInstance.addLayer(clusterGroup);\n } catch {\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position).addTo(mapInstance);\n bindMarkerContent(m, marker, allowHtml());\n markers.push(m);\n });\n }\n } else {\n p?.markers?.forEach((marker) => {\n const m = L.marker(marker.position).addTo(mapInstance);\n bindMarkerContent(m, marker, allowHtml());\n markers.push(m);\n });\n }\n\n if (markers.length > 0) {\n allBoundsLayers.push(...markers);\n }\n\n // ─── GeoJSON (v3.1.0) ───────────────────────\n if (p?.geojson) {\n const geoLayer = addGeoJSONLayer(\n mapInstance,\n L,\n p.geojson,\n p.geojsonStyle,\n p.popup,\n allowHtml()\n );\n allBoundsLayers.push(geoLayer);\n }\n\n // ─── Named layers (v3.1.0) ──────────────────\n if (p?.layers && p.layers.length > 0) {\n const overlays: Record<string, any> = {};\n\n for (const layerDef of p.layers) {\n const geoLayer = addGeoJSONLayer(\n mapInstance,\n L,\n layerDef.geojson,\n layerDef.style || p?.geojsonStyle,\n layerDef.popup || p?.popup,\n allowHtml()\n );\n\n overlays[layerDef.name] = geoLayer;\n allBoundsLayers.push(geoLayer);\n\n // Respect initial visibility\n if (layerDef.visible === false) {\n mapInstance.removeLayer(geoLayer);\n }\n }\n\n // Add layer control if multiple layers\n if (Object.keys(overlays).length > 1) {\n L.control.layers(null, overlays, { collapsed: true }).addTo(mapInstance);\n }\n }\n\n // ─── PMTiles (v3.1.0) ────────────────────────\n setPmtilesError(null);\n if (p?.pmtiles) {\n try {\n // @ts-ignore — optional peer dependency, may not be installed\n const protomaps = await import(/* @vite-ignore */ 'protomaps-leaflet');\n const pmConfig = p.pmtiles;\n\n const paintRules =\n pmConfig.paintRules?.map((rule) => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any)[\n rule.symbolizer === 'polygon'\n ? 'PolygonSymbolizer'\n : rule.symbolizer === 'line'\n ? 'LineSymbolizer'\n : 'CircleSymbolizer'\n ]({\n fill: rule.color || '#3388ff',\n stroke: rule.color || '#333',\n width: rule.width ?? 1,\n opacity: rule.opacity ?? 0.6,\n }),\n })) || [];\n\n const labelRules =\n pmConfig.labelRules?.map((rule) => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any).TextSymbolizer({\n label_props: [rule.textField],\n fontSize: rule.fontSize ?? 12,\n }),\n })) || [];\n\n const pmLayer = (protomaps as any).leafletLayer({\n url: pmConfig.url,\n attribution: pmConfig.attribution,\n paintRules,\n labelRules,\n maxZoom: pmConfig.maxZoom,\n minZoom: pmConfig.minZoom,\n });\n\n pmLayer.addTo(mapInstance);\n } catch (e) {\n // P1.3 — do NOT fail silently. Keep the base map, but surface a\n // visible notice and report a renderer error via telemetry. The\n // most common cause is the optional `protomaps-leaflet` peer not\n // being installed.\n const detail = e instanceof Error ? e.message : String(e);\n const message =\n 'PMTiles layer unavailable — the optional \"protomaps-leaflet\" ' +\n 'peer dependency failed to load or render.';\n console.warn('[MCP-UI] ' + message, e);\n setPmtilesError(message);\n telemetry?.dispatch({\n type: 'render:error',\n errorMessage: `${message} (${detail})`,\n id: props.component?.id ?? '',\n componentType: 'map',\n ts: Date.now(),\n });\n }\n }\n\n // ─── Fit bounds ─────────────────────────────\n if (p?.fitBounds && allBoundsLayers.length > 0) {\n const group = L.featureGroup(allBoundsLayers);\n const bounds = group.getBounds();\n if (bounds.isValid()) {\n mapInstance.fitBounds(bounds.pad(0.1));\n }\n } else if (p?.center) {\n mapInstance.setView(p.center, p.zoom || mapInstance.getZoom());\n }\n } catch (err) {\n // Fallback ladder (P2.5): a Leaflet drawing failure degrades to\n // the coordinate table below instead of a blank/partial map.\n const message = err instanceof Error ? err.message : 'Failed to render map';\n setError(message);\n telemetry?.dispatch({\n type: 'render:error',\n errorMessage: message,\n id: props.component?.id ?? '',\n componentType: 'map',\n ts: Date.now(),\n });\n }\n }\n });\n\n // Cleanup\n onCleanup(() => {\n if (mapInstance) {\n mapInstance.remove();\n mapInstance = null;\n }\n });\n\n return (\n <ExpandableWrapper\n title={'Map'}\n copyData={mapToGeoJSON(params())}\n copyLabel=\"Copy markers as GeoJSON\"\n toolbarVariant={props.toolbarVariant}\n >\n <div\n class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${params()?.className || ''} ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}\n >\n <Show when={error()}>\n {/* Fallback ladder (P2.5): degrade to a coordinate table\n rather than a bare error string. */}\n <div class=\"p-3\">\n <DegradedFallback\n message={`Map rendering failed: ${error()}`}\n caption=\"Showing the map data as a coordinate table — the interactive map is unavailable.\"\n {...mapToDegradedTable(params() ?? {})}\n />\n </div>\n </Show>\n <Show when={!error()}>\n {/* P1.3 — visible notice when the PMTiles overlay fails but the\n base map is still usable. */}\n <Show when={pmtilesError()}>\n <div\n role=\"alert\"\n class=\"m-2 rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200\"\n >\n {pmtilesError()} The base map is still shown.\n </div>\n </Show>\n <div\n ref={mapContainer}\n style={\n isExpanded()\n ? { height: '100%', width: '100%', 'z-index': 0 }\n : { height: params()?.height || '400px', width: '100%', 'z-index': 0 }\n }\n class={`relative z-0 ${isExpanded() ? 'flex-1 min-h-0' : ''}`}\n />\n </Show>\n </div>\n </ExpandableWrapper>\n );\n};\n"],"names":["L","clusterCssLoaded","getChoroplethColor","value","scale","fallback","isFinite","length","i","buildStyleFn","style","fillColor","fillOpacity","color","weight","opacity","feature","choroplethField","choroplethScale","properties","val","choroplethFallback","strokeColor","strokeWeight","strokeOpacity","buildPopupContent","popup","allowHtml","props","template","replace","_","key","escapeHtml","String","parts","titleField","push","fields","Object","keys","slice","formatted","toLocaleString","join","popupSafeText","undefined","bindMarkerContent","m","marker","tooltip","bindTooltip","bindPopup","addGeoJSONLayer","mapInst","leaflet","geojson","styleFn","layer","geoJSON","pointToLayer","latlng","s","circleMarker","radius","onEachFeature","featureLayer","html","maxWidth","addTo","mapToGeoJSON","p","features","markers","pos","position","lat","Array","isArray","lng","type","geometry","coordinates","JSON","stringify","MapRenderer","mapContainer","mapInstance","isLeafletLoaded","setIsLeafletLoaded","createSignal","error","setError","pmtilesError","setPmtilesError","isExpanded","useExpanded","telemetry","useTelemetry","allowHtmlPopups","params","component","createEffect","setTimeout","invalidateSize","isServer","module","default","e","console","warn","center","zoom","map","zoomControl","scrollWheelZoom","attributionControl","setView","tileLayerUrl","tileLayer","attribution","control","prefix","Icon","Default","prototype","_getIconUrl","mergeOptions","iconRetinaUrl","iconUrl","shadowUrl","allBoundsLayers","eachLayer","Marker","GeoJSON","CircleMarker","_group","_featureGroup","removeLayer","shouldCluster","clustering","clusterOpts","clusterGroup","markerClusterGroup","maxClusterRadius","spiderfyOnMaxZoom","showCoverageOnHover","disableClusteringAtZoom","animate","animateAddingMarkers","forEach","addLayer","geoLayer","geojsonStyle","layers","overlays","layerDef","name","visible","collapsed","pmtiles","protomaps","pmConfig","paintRules","rule","dataLayer","symbolizer","fill","stroke","width","labelRules","TextSymbolizer","label_props","textField","fontSize","pmLayer","leafletLayer","url","maxZoom","minZoom","detail","Error","message","dispatch","errorMessage","id","componentType","ts","Date","now","fitBounds","group","featureGroup","bounds","getBounds","isValid","pad","getZoom","err","onCleanup","remove","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$2","_$getNextMarker","nextSibling","_el$0","_el$1","_co$3","_$insert","Show","when","_el$2","_tmpl$","DegradedFallback","_$mergeProps","caption","mapToDegradedTable","_el$3","_tmpl$2","_el$5","_el$6","_co$","_el$7","_tmpl$3","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","_$style","t","_$className","className"],"mappings":";;;;;;;;AAwBA,IAAIA,IAAS;AAEb,IAAIC,mBAAmB;AA4CvB,SAASC,mBACPC,OACAC,OACAC,UACQ;AACR,MAAIF,SAAS,QAAQ,OAAOA,UAAU,YAAY,CAACG,SAASH,KAAK,EAAG,QAAOE;AAG3E,MAAID,MAAMG,WAAW,EAAG,QAAOF;AAC/B,MAAIF,SAASC,MAAM,CAAC,EAAE,CAAC,EAAG,QAAOA,MAAM,CAAC,EAAE,CAAC;AAC3C,MAAID,SAASC,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC,EAAG,QAAOH,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC;AAGzE,WAASC,IAAI,GAAGA,IAAIJ,MAAMG,QAAQC,KAAK;AACrC,QAAIL,SAASC,MAAMI,CAAC,EAAE,CAAC,EAAG,QAAOJ,MAAMI,CAAC,EAAE,CAAC;AAAA,EAC7C;AACA,SAAOJ,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC;AAClC;AAKA,SAASE,aACPC,QAC2C;AAC3C,MAAI,CAACA,QAAO;AACV,WAAO,OAAO;AAAA,MACZC,WAAW;AAAA,MACXC,aAAa;AAAA,MACbC,OAAO;AAAA,MACPC,QAAQ;AAAA,MACRC,SAAS;AAAA,IAAA;AAAA,EAEb;AAEA,SAAO,CAACC,YAAiB;AACvB,QAAIL,YAAYD,OAAMC,aAAa;AAGnC,QAAID,OAAMO,mBAAmBP,OAAMQ,oBAAmBF,mCAASG,aAAY;AACzE,YAAMC,MAAMJ,QAAQG,WAAWT,OAAMO,eAAe;AACpDN,kBAAYT,mBACVkB,KACAV,OAAMQ,iBACNR,OAAMW,sBAAsB,MAC9B;AAAA,IACF;AAEA,WAAO;AAAA,MACLV;AAAAA,MACAC,aAAaF,OAAME,eAAe;AAAA,MAClCC,OAAOH,OAAMY,eAAe;AAAA,MAC5BR,QAAQJ,OAAMa,gBAAgB;AAAA,MAC9BR,SAASL,OAAMc,iBAAiB;AAAA,IAAA;AAAA,EAEpC;AACF;AAYO,SAASC,kBACdT,SACAU,OACAC,YAAY,OACG;AACf,MAAI,CAACD,SAAS,EAACV,mCAASG,YAAY,QAAO;AAC3C,QAAMS,QAAQZ,QAAQG;AAGtB,MAAIQ,aAAaD,MAAMG,UAAU;AAC/B,WAAOH,MAAMG,SAASC,QAAQ,kBAAkB,CAACC,GAAGC,QAAQ;AAC1D,YAAMZ,MAAMQ,MAAMI,GAAG;AACrB,aAAOZ,OAAO,OAAOa,WAAWC,OAAOd,GAAG,CAAC,IAAI;AAAA,IACjD,CAAC;AAAA,EACH;AAGA,QAAMe,QAAkB,CAAA;AAExB,MAAIT,MAAMU,cAAcR,MAAMF,MAAMU,UAAU,KAAK,MAAM;AACvDD,UAAME,KAAK,WAAWJ,WAAWC,OAAON,MAAMF,MAAMU,UAAU,CAAC,CAAC,CAAC,WAAW;AAAA,EAC9E;AAEA,QAAME,SAASZ,MAAMY,UAAUC,OAAOC,KAAKZ,KAAK,EAAEa,MAAM,GAAG,CAAC;AAC5D,aAAWT,OAAOM,QAAQ;AACxB,QAAIN,QAAQN,MAAMU,WAAY;AAC9B,UAAMhB,MAAMQ,MAAMI,GAAG;AACrB,QAAIZ,OAAO,KAAM;AACjB,UAAMsB,YAAY,OAAOtB,QAAQ,WAAWA,IAAIuB,eAAe,OAAO,IAAIT,OAAOd,GAAG;AACpFe,UAAME,KACJ,2CAA2CJ,WAAWD,GAAG,CAAC,YAAYC,WAAWS,SAAS,CAAC,EAC7F;AAAA,EACF;AAEA,SAAOP,MAAMS,KAAK,OAAO;AAC3B;AAQO,SAASC,cAAc1C,OAA2BwB,YAAY,OAA2B;AAC9F,MAAIxB,SAAS,KAAM,QAAO2C;AAC1B,SAAOnB,YAAYxB,QAAQ8B,WAAW9B,KAAK;AAC7C;AAGO,SAAS4C,kBACdC,GACAC,QACAtB,WACM;AACN,QAAMuB,UAAUL,cAAcI,OAAOC,SAASvB,SAAS;AACvD,MAAIuB,QAASF,GAAEG,YAAYD,OAAO;AAClC,QAAMxB,QAAQmB,cAAcI,OAAOvB,OAAOC,SAAS;AACnD,MAAID,MAAOsB,GAAEI,UAAU1B,KAAK;AAC9B;AAMO,SAAS2B,gBACdC,SACAC,SACAC,SACA9C,QACAgB,OACAC,YAAY,OACP;AACL,QAAM8B,UAAUhD,aAAaC,MAAK;AAElC,QAAMgD,QAAQH,QAAQI,QAAQH,SAAS;AAAA,IACrC9C,OAAO+C;AAAAA,IACPG,cAAcA,CAAC5C,SAAc6C,WAAgB;AAE3C,YAAMC,IAAIL,QAAQzC,OAAO;AACzB,aAAOuC,QAAQQ,aAAaF,QAAQ;AAAA,QAClCG,QAAQ;AAAA,QACRrD,WAAWmD,EAAEnD;AAAAA,QACbC,aAAakD,EAAElD;AAAAA,QACfC,OAAOiD,EAAEjD;AAAAA,QACTC,QAAQgD,EAAEhD;AAAAA,QACVC,SAAS+C,EAAE/C;AAAAA,MAAAA,CACZ;AAAA,IACH;AAAA,IACAkD,eAAeA,CAACjD,SAAckD,iBAAsB;AAClD,YAAMC,OAAO1C,kBAAkBT,SAASU,OAAOC,SAAS;AACxD,UAAIwC,MAAM;AACRD,qBAAad,UAAUe,MAAM;AAAA,UAAEC,UAAU;AAAA,QAAA,CAAK;AAAA,MAChD;AAAA,IACF;AAAA,EAAA,CACD;AAEDV,QAAMW,MAAMf,OAAO;AACnB,SAAOI;AACT;AAUA,SAASY,aAAaC,GAA2C;AAC/D,MAAI,CAACA,EAAG,QAAO;AACf,QAAMC,WAAkB,CAAA;AACxB,aAAWvB,UAAUsB,EAAEE,WAAW,CAAA,GAAI;AACpC,UAAMC,MAAWzB,OAAO0B;AAExB,UAAMC,MAAMC,MAAMC,QAAQJ,GAAG,IAAIA,IAAI,CAAC,IAAIA,2BAAKE;AAC/C,UAAMG,MAAMF,MAAMC,QAAQJ,GAAG,IAAIA,IAAI,CAAC,IAAIA,2BAAKK;AAC/C,QAAI,OAAOH,QAAQ,YAAY,OAAOG,QAAQ,SAAU;AACxDP,aAASnC,KAAK;AAAA,MACZ2C,MAAM;AAAA,MACNC,UAAU;AAAA,QAAED,MAAM;AAAA,QAASE,aAAa,CAACH,KAAKH,GAAG;AAAA,MAAA;AAAA,MACjDzD,YAAY;AAAA,QACV,GAAI8B,OAAOC,UAAU;AAAA,UAAEA,SAASD,OAAOC;AAAAA,QAAAA,IAAY,CAAA;AAAA,QACnD,GAAID,OAAOvB,QAAQ;AAAA,UAAEA,OAAOuB,OAAOvB;AAAAA,QAAAA,IAAU,CAAA;AAAA,MAAC;AAAA,IAChD,CACD;AAAA,EACH;AACA,SAAOyD,KAAKC,UAAU;AAAA,IAAEJ,MAAM;AAAA,IAAqBR;AAAAA,EAAAA,GAAY,MAAM,CAAC;AACxE;AAEO,MAAMa,cAA4CzD,CAAAA,UAAU;AACjE,MAAI0D;AACJ,MAAIC,cAAmB;AACvB,QAAM,CAACC,iBAAiBC,kBAAkB,IAAIC,aAAa,KAAK;AAChE,QAAM,CAACC,OAAOC,QAAQ,IAAIF,aAA4B,IAAI;AAI1D,QAAM,CAACG,cAAcC,eAAe,IAAIJ,aAA4B,IAAI;AACxE,QAAMK,aAAaC,YAAAA;AACnB,QAAMC,YAAYC,aAAAA;AAGlB,QAAMvE,YAAYA,MAAMC,MAAMuE,oBAAoB;AAElD,QAAMC,SAASA,MAAAA;;AAAMxE,iBAAMwE,YAAWxE,WAAMyE,cAANzE,mBAAiBwE;AAAAA;AAMvDE,eAAa,MAAM;AACAP,eAAAA;AACjB,QAAI,CAACR,YAAa;AAIlBgB,eAAW,MAAA;;AAAMhB,8DAAaiB,mBAAbjB;AAAAA,OAAiC,GAAG;AAAA,EACvD,CAAC;AAGDe,eAAa,YAAY;;AACvB,QAAIG,SAAU;AAEd,QAAI,CAACzG,GAAG;AACN,UAAI;AACF,cAAM0G,SAAS,MAAM,OAAO,4BAAS,EAAA,KAAA,OAAA,EAAA,CAAA;AACrC1G,YAAI0G,OAAOC,WAAWD;AACtB,cAAM,OAAO,8EAA0B;AACvCjB,2BAAmB,IAAI;AAAA,MACzB,SAASmB,GAAG;AACVC,gBAAQC,KAAK,0BAA0BF,CAAC;AACxChB,iBAAS,kCAAkC;AAC3C;AAAA,MACF;AAAA,IACF,OAAO;AACLH,yBAAmB,IAAI;AAAA,IACzB;AAEA,QAAID,gBAAAA,KAAqBF,gBAAgB,CAACC,aAAa;AACrD,YAAMhB,IAAI6B,OAAAA;AACV,YAAMW,UAASxC,uBAAGwC,WAAU,CAAC,QAAQ,KAAK;AAC1C,YAAMC,QAAOzC,uBAAGyC,SAAQ;AAExBzB,oBAAcvF,EAAEiH,IAAI3B,cAAc;AAAA,QAChC4B,cAAa3C,uBAAG2C,iBAAgB;AAAA,QAChCC,kBAAiB5C,uBAAG4C,qBAAoB;AAAA,QACxCC,oBAAoB;AAAA,MAAA,CACrB,EAAEC,QAAQN,QAAQC,IAAI;AAGvB,YAAMM,gBAAe/C,uBAAGgD,cAAa;AACrCvH,QAAEuH,UAAUD,cAAc;AAAA,QACxBE,cACEjD,uBAAGiD,gBACH;AAAA,MAAA,CACH,EAAEnD,MAAMkB,WAAW;AAEpB,WAAIhB,uBAAGiD,iBAAgB,IAAI;AACzBxH,UAAEyH,QAAQD,YAAY;AAAA,UAAEE,QAAQ;AAAA,QAAA,CAAO,EAAErD,MAAMkB,WAAW;AAAA,MAC5D;AAGA,aAAQvF,EAAE2H,KAAKC,QAAQC,UAAkBC;AACzC9H,QAAE2H,KAAKC,QAAQG,aAAa;AAAA,QAC1BC,eAAe;AAAA,QACfC,SAAS;AAAA,QACTC,WAAW;AAAA,MAAA,CACZ;AAAA,IACH;AAGA,QAAI3C,eAAevF,GAAG;AACpB,UAAI;AACF,cAAMuE,IAAI6B,OAAAA;AACV,cAAM+B,kBAAyB,CAAA;AAG/B5C,oBAAY6C,UAAU,CAAC1E,UAAe;AACpC,cACEA,iBAAiB1D,EAAEqI,UACnB3E,iBAAiB1D,EAAEsI,WACnB5E,iBAAiB1D,EAAEuI,gBACnB7E,MAAM8E,UACN9E,MAAM+E,eACN;AACAlD,wBAAYmD,YAAYhF,KAAK;AAAA,UAC/B;AAAA,QACF,CAAC;AAGD,cAAMe,UAAiB,CAAA;AACvB,cAAMkE,iBAAgBpE,uBAAGqE,gBAAcrE,uBAAGE,YAAWF,EAAEE,QAAQlE,SAAS;AAExE,YAAIoI,eAAe;AACjB,cAAI;AACF,kBAAM,OAAO,0CAAuB,EAAA,KAAA,OAAA,EAAA,CAAA;AACpC,gBAAI,CAAC1I,kBAAkB;AACrB,oBAAM,OAAO,8HAA8C;AAC3D,oBAAM,OAAO,sIAAsD;AACnEA,iCAAmB;AAAA,YACrB;AACA,kBAAM4I,cACJ,OAAOtE,EAAEqE,eAAe,WAAWrE,EAAEqE,aAAa,CAAA;AACpD,kBAAME,eAAgB9I,EAAU+I,mBAAmB;AAAA,cACjDC,kBAAkBH,YAAYG,oBAAoB;AAAA,cAClDC,mBAAmBJ,YAAYI,qBAAqB;AAAA,cACpDC,qBAAqBL,YAAYK,uBAAuB;AAAA,cACxDC,yBAAyBN,YAAYM;AAAAA,cACrCC,SAASP,YAAYQ,wBAAwB;AAAA,YAAA,CAC9C;AACD9E,yCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,oBAAMD,IAAIhD,EAAEiD,OAAOA,OAAO0B,QAAQ;AAClC5B,gCAAkBC,GAAGC,QAAQtB,WAAW;AACxCmH,2BAAaS,SAASvG,CAAC;AACvByB,sBAAQpC,KAAKW,CAAC;AAAA,YAChB;AACAuC,wBAAYgE,SAAST,YAAY;AAAA,UACnC,QAAQ;AACNvE,yCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,oBAAMD,IAAIhD,EAAEiD,OAAOA,OAAO0B,QAAQ,EAAEN,MAAMkB,WAAW;AACrDxC,gCAAkBC,GAAGC,QAAQtB,WAAW;AACxC8C,sBAAQpC,KAAKW,CAAC;AAAA,YAChB;AAAA,UACF;AAAA,QACF,OAAO;AACLuB,uCAAGE,YAAHF,mBAAY+E,QAASrG,CAAAA,WAAW;AAC9B,kBAAMD,IAAIhD,EAAEiD,OAAOA,OAAO0B,QAAQ,EAAEN,MAAMkB,WAAW;AACrDxC,8BAAkBC,GAAGC,QAAQtB,WAAW;AACxC8C,oBAAQpC,KAAKW,CAAC;AAAA,UAChB;AAAA,QACF;AAEA,YAAIyB,QAAQlE,SAAS,GAAG;AACtB4H,0BAAgB9F,KAAK,GAAGoC,OAAO;AAAA,QACjC;AAGA,YAAIF,uBAAGf,SAAS;AACd,gBAAMgG,WAAWnG,gBACfkC,aACAvF,GACAuE,EAAEf,SACFe,EAAEkF,cACFlF,EAAE7C,OACFC,UAAAA,CACF;AACAwG,0BAAgB9F,KAAKmH,QAAQ;AAAA,QAC/B;AAGA,aAAIjF,uBAAGmF,WAAUnF,EAAEmF,OAAOnJ,SAAS,GAAG;AACpC,gBAAMoJ,WAAgC,CAAA;AAEtC,qBAAWC,YAAYrF,EAAEmF,QAAQ;AAC/B,kBAAMF,WAAWnG,gBACfkC,aACAvF,GACA4J,SAASpG,SACToG,SAASlJ,UAAS6D,uBAAGkF,eACrBG,SAASlI,UAAS6C,uBAAG7C,QACrBC,WACF;AAEAgI,qBAASC,SAASC,IAAI,IAAIL;AAC1BrB,4BAAgB9F,KAAKmH,QAAQ;AAG7B,gBAAII,SAASE,YAAY,OAAO;AAC9BvE,0BAAYmD,YAAYc,QAAQ;AAAA,YAClC;AAAA,UACF;AAGA,cAAIjH,OAAOC,KAAKmH,QAAQ,EAAEpJ,SAAS,GAAG;AACpCP,cAAEyH,QAAQiC,OAAO,MAAMC,UAAU;AAAA,cAAEI,WAAW;AAAA,YAAA,CAAM,EAAE1F,MAAMkB,WAAW;AAAA,UACzE;AAAA,QACF;AAGAO,wBAAgB,IAAI;AACpB,YAAIvB,uBAAGyF,SAAS;AACd,cAAI;AAEF,kBAAMC,YAAY,MAAM;AAAA;AAAA,cAA0B;AAAA,YAAA;AAClD,kBAAMC,WAAW3F,EAAEyF;AAEnB,kBAAMG,eACJD,cAASC,eAATD,mBAAqBjD,IAAKmD,CAAAA,UAAU;AAAA,cAClCC,WAAWD,KAAKC;AAAAA,cAChBC,YAAY,IAAKL,UACfG,KAAKE,eAAe,YAChB,sBACAF,KAAKE,eAAe,SAClB,mBACA,kBAAkB,EACxB;AAAA,gBACAC,MAAMH,KAAKvJ,SAAS;AAAA,gBACpB2J,QAAQJ,KAAKvJ,SAAS;AAAA,gBACtB4J,OAAOL,KAAKK,SAAS;AAAA,gBACrB1J,SAASqJ,KAAKrJ,WAAW;AAAA,cAAA,CAC1B;AAAA,YAAA,QACI,CAAA;AAET,kBAAM2J,eACJR,cAASQ,eAATR,mBAAqBjD,IAAKmD,CAAAA,UAAU;AAAA,cAClCC,WAAWD,KAAKC;AAAAA,cAChBC,YAAY,IAAKL,UAAkBU,eAAe;AAAA,gBAChDC,aAAa,CAACR,KAAKS,SAAS;AAAA,gBAC5BC,UAAUV,KAAKU,YAAY;AAAA,cAAA,CAC5B;AAAA,YAAA,QACI,CAAA;AAET,kBAAMC,UAAWd,UAAkBe,aAAa;AAAA,cAC9CC,KAAKf,SAASe;AAAAA,cACdzD,aAAa0C,SAAS1C;AAAAA,cACtB2C;AAAAA,cACAO;AAAAA,cACAQ,SAAShB,SAASgB;AAAAA,cAClBC,SAASjB,SAASiB;AAAAA,YAAAA,CACnB;AAEDJ,oBAAQ1G,MAAMkB,WAAW;AAAA,UAC3B,SAASqB,GAAG;AAKV,kBAAMwE,SAASxE,aAAayE,QAAQzE,EAAE0E,UAAUpJ,OAAO0E,CAAC;AACxD,kBAAM0E,UACJ;AAEFzE,oBAAQC,KAAK,cAAcwE,SAAS1E,CAAC;AACrCd,4BAAgBwF,OAAO;AACvBrF,mDAAWsF,SAAS;AAAA,cAClBvG,MAAM;AAAA,cACNwG,cAAc,GAAGF,OAAO,KAAKF,MAAM;AAAA,cACnCK,MAAI7J,WAAMyE,cAANzE,mBAAiB6J,OAAM;AAAA,cAC3BC,eAAe;AAAA,cACfC,IAAIC,KAAKC,IAAAA;AAAAA,YAAI;AAAA,UAEjB;AAAA,QACF;AAGA,aAAItH,uBAAGuH,cAAa3D,gBAAgB5H,SAAS,GAAG;AAC9C,gBAAMwL,QAAQ/L,EAAEgM,aAAa7D,eAAe;AAC5C,gBAAM8D,SAASF,MAAMG,UAAAA;AACrB,cAAID,OAAOE,WAAW;AACpB5G,wBAAYuG,UAAUG,OAAOG,IAAI,GAAG,CAAC;AAAA,UACvC;AAAA,QACF,WAAW7H,uBAAGwC,QAAQ;AACpBxB,sBAAY8B,QAAQ9C,EAAEwC,QAAQxC,EAAEyC,QAAQzB,YAAY8G,SAAS;AAAA,QAC/D;AAAA,MACF,SAASC,KAAK;AAGZ,cAAMhB,UAAUgB,eAAejB,QAAQiB,IAAIhB,UAAU;AACrD1F,iBAAS0F,OAAO;AAChBrF,+CAAWsF,SAAS;AAAA,UAClBvG,MAAM;AAAA,UACNwG,cAAcF;AAAAA,UACdG,MAAI7J,WAAMyE,cAANzE,mBAAiB6J,OAAM;AAAA,UAC3BC,eAAe;AAAA,UACfC,IAAIC,KAAKC,IAAAA;AAAAA,QAAI;AAAA,MAEjB;AAAA,IACF;AAAA,EACF,CAAC;AAGDU,YAAU,MAAM;AACd,QAAIhH,aAAa;AACfA,kBAAYiH,OAAAA;AACZjH,oBAAc;AAAA,IAChB;AAAA,EACF,CAAC;AAED,SAAAkH,gBACGC,mBAAiB;AAAA,IAChBC,OAAO;AAAA,IAAK,IACZC,WAAQ;AAAA,aAAEtI,aAAa8B,QAAQ;AAAA,IAAC;AAAA,IAChCyG,WAAS;AAAA,IAAA,IACTC,iBAAc;AAAA,aAAElL,MAAMkL;AAAAA,IAAc;AAAA,IAAA,IAAAC,WAAA;AAAA,UAAAC,OAAAC,eAAAC,OAAA,GAAAC,QAAAH,KAAAI,YAAA,CAAAC,OAAAC,KAAA,IAAAC,cAAAJ,MAAAK,WAAA,GAAAC,QAAAJ,MAAAG,aAAA,CAAAE,OAAAC,KAAA,IAAAJ,cAAAE,MAAAD,WAAA;AAAAI,aAAAZ,MAAAP,gBAOjCoB,MAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAEnI,MAAAA;AAAAA,QAAO;AAAA,QAAA,IAAAoH,WAAA;AAAA,cAAAgB,QAAAd,eAAAe,MAAA;AAAAJ,iBAAAG,OAAAtB,gBAIdwB,kBAAgBC,WAAA;AAAA,YAAA,IACf5C,UAAO;AAAA,qBAAE,yBAAyB3F,OAAO;AAAA,YAAE;AAAA,YAC3CwI,SAAO;AAAA,UAAA,GAAA,MACHC,mBAAmBhI,OAAAA,KAAY,CAAA,CAAE,CAAC,CAAA,CAAA;AAAA,iBAAA2H;AAAAA,QAAA;AAAA,MAAA,CAAA,GAAAV,OAAAC,KAAA;AAAAM,aAAAZ,MAAAP,gBAI3CoB,MAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAE,CAACnI,MAAAA;AAAAA,QAAO;AAAA,QAAA,IAAAoH,WAAA;AAAA,iBAAA,CAAAN,gBAGjBoB,MAAI;AAAA,YAAA,IAACC,OAAI;AAAA,qBAAEjI,aAAAA;AAAAA,YAAc;AAAA,YAAA,IAAAkH,WAAA;AAAA,kBAAAsB,QAAApB,eAAAqB,OAAA,GAAAC,QAAAF,MAAAjB,YAAA,CAAAoB,OAAAC,IAAA,IAAAlB,cAAAgB,MAAAf,WAAA;AAAAgB,oBAAAhB;AAAAI,qBAAAS,OAKrBxI,cAAY2I,OAAAC,IAAA;AAAA,qBAAAJ;AAAAA,YAAA;AAAA,UAAA,CAAA,IAAA,MAAA;AAAA,gBAAAK,QAAAzB,eAAA0B,OAAA;AAAA,gBAAAC,QAIVtJ;AAAY,mBAAAsJ,UAAA,aAAAC,IAAAD,OAAAF,KAAA,IAAZpJ,eAAYoJ;AAAAI,mBAAAC,CAAAA,QAAA;;AAAA,kBAAAC,MAEfjJ,eACI;AAAA,gBAAEkJ,QAAQ;AAAA,gBAAQxE,OAAO;AAAA,gBAAQ,WAAW;AAAA,cAAA,IAC5C;AAAA,gBAAEwE,UAAQ7I,kBAAAA,mBAAU6I,WAAU;AAAA,gBAASxE,OAAO;AAAA,gBAAQ,WAAW;AAAA,cAAA,GAAGyE,OAEnE,gBAAgBnJ,WAAAA,IAAe,mBAAmB,EAAE;AAAEgJ,kBAAAnI,IAAAuI,MAAAT,OAAAM,KAAAD,IAAAnI,CAAA;AAAAsI,uBAAAH,IAAAK,KAAAC,UAAAX,OAAAK,IAAAK,IAAAF,IAAA;AAAA,qBAAAH;AAAAA,YAAA,GAAA;AAAA,cAAAnI,GAAA9D;AAAAA,cAAAsM,GAAAtM;AAAAA,YAAAA,CAAA;AAAA,mBAAA4L;AAAAA,UAAA,IAAA;AAAA,QAAA;AAAA,MAAA,CAAA,GAAAhB,OAAAC,KAAA;AAAAmB,aAAA,MAAA;;AAAAO,yBAAArC,MAjC1D,uHAAqH5G,kBAAAA,mBAAUkJ,cAAa,EAAE,IACnJvJ,WAAAA,IAAe,iCAAiC,EAAE,EAClD;AAAA,OAAA;AAAA,aAAAiH;AAAAA,IAAA;AAAA,EAAA,CAAA;AAqCV;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { delegateEvents, createComponent, Portal, getNextElement,
|
|
1
|
+
import { delegateEvents, createComponent, Portal, getNextElement, getNextMarker, insert, runHydrationEvents, effect, setAttribute, className, style, template } from "solid-js/web";
|
|
2
2
|
import { createSignal, createEffect, onCleanup, Show } from "solid-js";
|
|
3
3
|
var _tmpl$ = /* @__PURE__ */ template(`<h2 id=modal-title class="text-lg font-semibold text-gray-900 dark:text-white">`), _tmpl$2 = /* @__PURE__ */ template(`<div>`), _tmpl$3 = /* @__PURE__ */ template(`<button class="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"aria-label="Close modal"><svg class="w-5 h-5"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M6 18L18 6M6 6l12 12">`), _tmpl$4 = /* @__PURE__ */ template(`<div class="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700"><!$><!/><!$><!/><!$><!/>`), _tmpl$5 = /* @__PURE__ */ template(`<div class="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm"role=dialog aria-modal=true tabindex=-1 style="animation:modal-fade-in 0.15s ease-out"><div style="animation:modal-scale-in 0.15s ease-out"><!$><!/><div class=p-4>`), _tmpl$6 = /* @__PURE__ */ template(`<style>
|
|
4
4
|
@keyframes modal-fade-in {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createComponent, Portal, getNextElement,
|
|
1
|
+
import { createComponent, Portal, getNextElement, insert, effect, setStyleProperty, className, template, use } from "solid-js/web";
|
|
2
2
|
import { createSignal, createEffect, onCleanup, Show } from "solid-js";
|
|
3
3
|
var _tmpl$ = /* @__PURE__ */ template(`<div role=menu style=position:fixed;z-index:9999>`);
|
|
4
4
|
const PortalDropdownMenu = (props) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { delegateEvents, getNextElement,
|
|
1
|
+
import { delegateEvents, getNextElement, getNextMarker, insert, createComponent, runHydrationEvents, setAttribute, effect, className, setProperty, template } from "solid-js/web";
|
|
2
2
|
import { createSignal, Show, For } from "solid-js";
|
|
3
3
|
var _tmpl$ = /* @__PURE__ */ template(`<div class="flex items-center gap-2"><span class=text-deposium-slate-500></span><button type=button class="px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-green-500 hover:text-green-600 transition-colors"data-presentation-feedback-verdict=readable></button><button type=button class="px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-amber-500 hover:text-amber-600 transition-colors"data-presentation-feedback-verdict=not_readable>`), _tmpl$2 = /* @__PURE__ */ template(`<div class="flex flex-wrap items-center gap-1"><span class=text-deposium-slate-500></span><!$><!/>`), _tmpl$3 = /* @__PURE__ */ template(`<div class="flex flex-col gap-2 p-2 rounded-lg border border-gray-200 dark:border-gray-700"><span class="font-medium text-deposium-slate-600 dark:text-gray-300"></span><div class="flex flex-wrap gap-1"></div><!$><!/><textarea rows=2 class="w-full rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 p-1.5 text-xs resize-y"data-presentation-feedback-comment></textarea><button type=button class="self-end px-3 py-1 rounded bg-amber-500 text-white font-medium hover:bg-amber-600 transition-colors"data-presentation-feedback-submit>`), _tmpl$4 = /* @__PURE__ */ template(`<span class=text-deposium-slate-500 data-presentation-feedback-ack>`), _tmpl$5 = /* @__PURE__ */ template(`<div><!$><!/><!$><!/><!$><!/>`), _tmpl$6 = /* @__PURE__ */ template(`<button type=button>`);
|
|
4
4
|
const PROBLEM_ORDER = ["too_raw", "wrong_columns", "wrong_chart", "missing_context", "wrong_unit", "bad_grouping", "missing_dataset_context"];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getNextElement,
|
|
1
|
+
import { getNextElement, getNextMarker, insert, template, createComponent } from "solid-js/web";
|
|
2
2
|
import { createContext, useContext } from "solid-js";
|
|
3
3
|
var _tmpl$ = /* @__PURE__ */ template(`<div class="p-4 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg"><p class="text-sm text-yellow-800 dark:text-yellow-200">Component "<!$><!/>" cannot be rendered outside of UIResourceRenderer`);
|
|
4
4
|
const defaultContextValue = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const web = require("solid-js/web");
|
|
4
4
|
const solidJs = require("solid-js");
|
|
5
5
|
var _tmpl$ = /* @__PURE__ */ web.template(`<div role=separator><div class=mcp-resize-indicator>`);
|
|
@@ -173,5 +173,4 @@ const ResizeHandle = (props) => {
|
|
|
173
173
|
};
|
|
174
174
|
web.delegateEvents(["pointerdown", "keydown"]);
|
|
175
175
|
exports.ResizeHandle = ResizeHandle;
|
|
176
|
-
exports.default = ResizeHandle;
|
|
177
176
|
//# sourceMappingURL=ResizeHandle.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResizeHandle.cjs","sources":["../../src/components/ResizeHandle.tsx"],"sourcesContent":["/**\n * ResizeHandle Component\n * Visual handle for resizing grid components\n *\n * Sprint Drag-Drop Feature\n */\n\nimport { Component, JSX, createMemo, mergeProps } from 'solid-js'\n\n/**\n * Resize edge types\n */\nexport type ResizeEdge = 'left' | 'right' | 'top' | 'bottom'\n\n/**\n * Props for ResizeHandle\n */\nexport interface ResizeHandleProps {\n /**\n * Which edge this handle is on\n */\n edge: ResizeEdge\n\n /**\n * Callback when resize starts\n */\n onResizeStart?: (edge: ResizeEdge, event: PointerEvent) => void\n\n /**\n * Whether the handle is disabled\n */\n disabled?: boolean\n\n /**\n * Whether resize is active\n */\n isActive?: boolean\n\n /**\n * Custom class\n */\n class?: string\n\n /**\n * Handle size in pixels\n */\n size?: number\n\n /**\n * Hit area size in pixels (larger than visible size for easier grabbing)\n */\n hitAreaSize?: number\n}\n\n/**\n * Get cursor style for edge\n */\nfunction getCursor(edge: ResizeEdge): string {\n switch (edge) {\n case 'left':\n case 'right':\n return 'ew-resize'\n case 'top':\n case 'bottom':\n return 'ns-resize'\n default:\n return 'default'\n }\n}\n\n/**\n * Get position styles for edge\n */\nfunction getPositionStyle(\n edge: ResizeEdge,\n hitAreaSize: number\n): JSX.CSSProperties {\n const halfSize = hitAreaSize / 2\n\n switch (edge) {\n case 'left':\n return {\n left: `-${halfSize}px`,\n top: '0',\n width: `${hitAreaSize}px`,\n height: '100%'\n }\n case 'right':\n return {\n right: `-${halfSize}px`,\n top: '0',\n width: `${hitAreaSize}px`,\n height: '100%'\n }\n case 'top':\n return {\n top: `-${halfSize}px`,\n left: '0',\n width: '100%',\n height: `${hitAreaSize}px`\n }\n case 'bottom':\n return {\n bottom: `-${halfSize}px`,\n left: '0',\n width: '100%',\n height: `${hitAreaSize}px`\n }\n default:\n return {}\n }\n}\n\n/**\n * Get visual indicator styles for edge\n */\nfunction getIndicatorStyle(\n edge: ResizeEdge,\n size: number,\n isActive: boolean\n): JSX.CSSProperties {\n const baseColor = isActive ? '#3b82f6' : '#9ca3af'\n\n const common: JSX.CSSProperties = {\n position: 'absolute',\n 'background-color': baseColor,\n 'border-radius': `${size / 2}px`,\n transition: 'background-color 150ms ease, opacity 150ms ease',\n opacity: isActive ? '1' : '0'\n }\n\n switch (edge) {\n case 'left':\n return {\n ...common,\n left: '50%',\n top: '50%',\n transform: 'translate(-50%, -50%)',\n width: `${size}px`,\n height: '40px',\n 'max-height': '60%'\n }\n case 'right':\n return {\n ...common,\n right: '50%',\n top: '50%',\n transform: 'translate(50%, -50%)',\n width: `${size}px`,\n height: '40px',\n 'max-height': '60%'\n }\n case 'top':\n return {\n ...common,\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n width: '40px',\n 'max-width': '60%',\n height: `${size}px`\n }\n case 'bottom':\n return {\n ...common,\n bottom: '50%',\n left: '50%',\n transform: 'translate(-50%, 50%)',\n width: '40px',\n 'max-width': '60%',\n height: `${size}px`\n }\n default:\n return common\n }\n}\n\n/**\n * ResizeHandle Component\n */\nexport const ResizeHandle: Component<ResizeHandleProps> = (props) => {\n const merged = mergeProps(\n {\n disabled: false,\n isActive: false,\n size: 4,\n hitAreaSize: 12\n },\n props\n )\n\n const handlePointerDown = (e: PointerEvent) => {\n if (merged.disabled) return\n\n e.preventDefault()\n e.stopPropagation()\n\n props.onResizeStart?.(props.edge, e)\n }\n\n // Container styles\n const containerStyle = createMemo((): JSX.CSSProperties => ({\n position: 'absolute',\n 'z-index': '10',\n cursor: merged.disabled ? 'default' : getCursor(props.edge),\n 'user-select': 'none',\n 'touch-action': 'none',\n ...getPositionStyle(props.edge, merged.hitAreaSize)\n }))\n\n // Indicator styles\n const indicatorStyle = createMemo(() =>\n getIndicatorStyle(props.edge, merged.size, merged.isActive)\n )\n\n // Class names\n const classNames = createMemo(() => {\n const classes = [\n 'mcp-resize-handle',\n `mcp-resize-handle-${props.edge}`\n ]\n\n if (merged.disabled) classes.push('mcp-resize-handle-disabled')\n if (merged.isActive) classes.push('mcp-resize-handle-active')\n if (props.class) classes.push(props.class)\n\n return classes.join(' ')\n })\n\n return (\n <div\n class={classNames()}\n style={containerStyle()}\n onPointerDown={handlePointerDown}\n data-resize-edge={props.edge}\n role=\"separator\"\n aria-orientation={\n props.edge === 'left' || props.edge === 'right'\n ? 'vertical'\n : 'horizontal'\n }\n aria-valuenow={undefined}\n tabIndex={merged.disabled ? -1 : 0}\n onKeyDown={(e) => {\n // Allow keyboard resizing\n if (merged.disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n // Create synthetic pointer event for keyboard activation\n const syntheticEvent = new PointerEvent('pointerdown', {\n clientX: window.innerWidth / 2,\n clientY: window.innerHeight / 2\n })\n props.onResizeStart?.(props.edge, syntheticEvent)\n }\n }}\n >\n {/* Visual indicator */}\n <div\n class=\"mcp-resize-indicator\"\n style={indicatorStyle()}\n />\n </div>\n )\n}\n\nexport default ResizeHandle\n"],"names":["getCursor","edge","getPositionStyle","hitAreaSize","halfSize","left","top","width","height","right","bottom","getIndicatorStyle","size","isActive","baseColor","common","position","transition","opacity","transform","ResizeHandle","props","merged","mergeProps","disabled","handlePointerDown","e","preventDefault","stopPropagation","onResizeStart","containerStyle","createMemo","cursor","indicatorStyle","classNames","classes","push","class","join","_el$","_$getNextElement","_tmpl$","_el$2","firstChild","$$keydown","key","syntheticEvent","PointerEvent","clientX","window","innerWidth","clientY","innerHeight","$$pointerdown","_$setAttribute","undefined","_$effect","_p$","_v$","_v$2","_v$3","_v$4","_v$5","_v$6","_$className","t","_$style","a","o","i","n","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ResizeHandle.cjs","sources":["../../src/components/ResizeHandle.tsx"],"sourcesContent":["/**\n * ResizeHandle Component\n * Visual handle for resizing grid components\n *\n * Sprint Drag-Drop Feature\n */\n\nimport { Component, JSX, createMemo, mergeProps } from 'solid-js'\n\n/**\n * Resize edge types\n */\nexport type ResizeEdge = 'left' | 'right' | 'top' | 'bottom'\n\n/**\n * Props for ResizeHandle\n */\nexport interface ResizeHandleProps {\n /**\n * Which edge this handle is on\n */\n edge: ResizeEdge\n\n /**\n * Callback when resize starts\n */\n onResizeStart?: (edge: ResizeEdge, event: PointerEvent) => void\n\n /**\n * Whether the handle is disabled\n */\n disabled?: boolean\n\n /**\n * Whether resize is active\n */\n isActive?: boolean\n\n /**\n * Custom class\n */\n class?: string\n\n /**\n * Handle size in pixels\n */\n size?: number\n\n /**\n * Hit area size in pixels (larger than visible size for easier grabbing)\n */\n hitAreaSize?: number\n}\n\n/**\n * Get cursor style for edge\n */\nfunction getCursor(edge: ResizeEdge): string {\n switch (edge) {\n case 'left':\n case 'right':\n return 'ew-resize'\n case 'top':\n case 'bottom':\n return 'ns-resize'\n default:\n return 'default'\n }\n}\n\n/**\n * Get position styles for edge\n */\nfunction getPositionStyle(\n edge: ResizeEdge,\n hitAreaSize: number\n): JSX.CSSProperties {\n const halfSize = hitAreaSize / 2\n\n switch (edge) {\n case 'left':\n return {\n left: `-${halfSize}px`,\n top: '0',\n width: `${hitAreaSize}px`,\n height: '100%'\n }\n case 'right':\n return {\n right: `-${halfSize}px`,\n top: '0',\n width: `${hitAreaSize}px`,\n height: '100%'\n }\n case 'top':\n return {\n top: `-${halfSize}px`,\n left: '0',\n width: '100%',\n height: `${hitAreaSize}px`\n }\n case 'bottom':\n return {\n bottom: `-${halfSize}px`,\n left: '0',\n width: '100%',\n height: `${hitAreaSize}px`\n }\n default:\n return {}\n }\n}\n\n/**\n * Get visual indicator styles for edge\n */\nfunction getIndicatorStyle(\n edge: ResizeEdge,\n size: number,\n isActive: boolean\n): JSX.CSSProperties {\n const baseColor = isActive ? '#3b82f6' : '#9ca3af'\n\n const common: JSX.CSSProperties = {\n position: 'absolute',\n 'background-color': baseColor,\n 'border-radius': `${size / 2}px`,\n transition: 'background-color 150ms ease, opacity 150ms ease',\n opacity: isActive ? '1' : '0'\n }\n\n switch (edge) {\n case 'left':\n return {\n ...common,\n left: '50%',\n top: '50%',\n transform: 'translate(-50%, -50%)',\n width: `${size}px`,\n height: '40px',\n 'max-height': '60%'\n }\n case 'right':\n return {\n ...common,\n right: '50%',\n top: '50%',\n transform: 'translate(50%, -50%)',\n width: `${size}px`,\n height: '40px',\n 'max-height': '60%'\n }\n case 'top':\n return {\n ...common,\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n width: '40px',\n 'max-width': '60%',\n height: `${size}px`\n }\n case 'bottom':\n return {\n ...common,\n bottom: '50%',\n left: '50%',\n transform: 'translate(-50%, 50%)',\n width: '40px',\n 'max-width': '60%',\n height: `${size}px`\n }\n default:\n return common\n }\n}\n\n/**\n * ResizeHandle Component\n */\nexport const ResizeHandle: Component<ResizeHandleProps> = (props) => {\n const merged = mergeProps(\n {\n disabled: false,\n isActive: false,\n size: 4,\n hitAreaSize: 12\n },\n props\n )\n\n const handlePointerDown = (e: PointerEvent) => {\n if (merged.disabled) return\n\n e.preventDefault()\n e.stopPropagation()\n\n props.onResizeStart?.(props.edge, e)\n }\n\n // Container styles\n const containerStyle = createMemo((): JSX.CSSProperties => ({\n position: 'absolute',\n 'z-index': '10',\n cursor: merged.disabled ? 'default' : getCursor(props.edge),\n 'user-select': 'none',\n 'touch-action': 'none',\n ...getPositionStyle(props.edge, merged.hitAreaSize)\n }))\n\n // Indicator styles\n const indicatorStyle = createMemo(() =>\n getIndicatorStyle(props.edge, merged.size, merged.isActive)\n )\n\n // Class names\n const classNames = createMemo(() => {\n const classes = [\n 'mcp-resize-handle',\n `mcp-resize-handle-${props.edge}`\n ]\n\n if (merged.disabled) classes.push('mcp-resize-handle-disabled')\n if (merged.isActive) classes.push('mcp-resize-handle-active')\n if (props.class) classes.push(props.class)\n\n return classes.join(' ')\n })\n\n return (\n <div\n class={classNames()}\n style={containerStyle()}\n onPointerDown={handlePointerDown}\n data-resize-edge={props.edge}\n role=\"separator\"\n aria-orientation={\n props.edge === 'left' || props.edge === 'right'\n ? 'vertical'\n : 'horizontal'\n }\n aria-valuenow={undefined}\n tabIndex={merged.disabled ? -1 : 0}\n onKeyDown={(e) => {\n // Allow keyboard resizing\n if (merged.disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n // Create synthetic pointer event for keyboard activation\n const syntheticEvent = new PointerEvent('pointerdown', {\n clientX: window.innerWidth / 2,\n clientY: window.innerHeight / 2\n })\n props.onResizeStart?.(props.edge, syntheticEvent)\n }\n }}\n >\n {/* Visual indicator */}\n <div\n class=\"mcp-resize-indicator\"\n style={indicatorStyle()}\n />\n </div>\n )\n}\n\nexport default ResizeHandle\n"],"names":["getCursor","edge","getPositionStyle","hitAreaSize","halfSize","left","top","width","height","right","bottom","getIndicatorStyle","size","isActive","baseColor","common","position","transition","opacity","transform","ResizeHandle","props","merged","mergeProps","disabled","handlePointerDown","e","preventDefault","stopPropagation","onResizeStart","containerStyle","createMemo","cursor","indicatorStyle","classNames","classes","push","class","join","_el$","_$getNextElement","_tmpl$","_el$2","firstChild","$$keydown","key","syntheticEvent","PointerEvent","clientX","window","innerWidth","clientY","innerHeight","$$pointerdown","_$setAttribute","undefined","_$effect","_p$","_v$","_v$2","_v$3","_v$4","_v$5","_v$6","_$className","t","_$style","a","o","i","n","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
|