@seed-ship/mcp-ui-solid 6.3.0 → 6.4.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 +87 -0
- package/dist/components/CarouselRenderer.cjs +3 -0
- package/dist/components/CarouselRenderer.cjs.map +1 -1
- package/dist/components/CarouselRenderer.d.ts +5 -0
- package/dist/components/CarouselRenderer.d.ts.map +1 -1
- package/dist/components/CarouselRenderer.js +3 -0
- package/dist/components/CarouselRenderer.js.map +1 -1
- package/dist/components/ChartJSRenderer.cjs +3 -0
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts +5 -0
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +3 -0
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/CodeBlockRenderer.cjs +3 -0
- package/dist/components/CodeBlockRenderer.cjs.map +1 -1
- package/dist/components/CodeBlockRenderer.d.ts +5 -0
- package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
- package/dist/components/CodeBlockRenderer.js +3 -0
- package/dist/components/CodeBlockRenderer.js.map +1 -1
- package/dist/components/GraphRenderer.cjs +33 -24
- package/dist/components/GraphRenderer.cjs.map +1 -1
- package/dist/components/GraphRenderer.d.ts +8 -2
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +33 -24
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/components/ImageGalleryRenderer.cjs +3 -0
- package/dist/components/ImageGalleryRenderer.cjs.map +1 -1
- package/dist/components/ImageGalleryRenderer.d.ts +5 -0
- package/dist/components/ImageGalleryRenderer.d.ts.map +1 -1
- package/dist/components/ImageGalleryRenderer.js +3 -0
- package/dist/components/ImageGalleryRenderer.js.map +1 -1
- package/dist/components/MapRenderer.cjs +3 -0
- package/dist/components/MapRenderer.cjs.map +1 -1
- package/dist/components/MapRenderer.d.ts +5 -0
- package/dist/components/MapRenderer.d.ts.map +1 -1
- package/dist/components/MapRenderer.js +3 -0
- package/dist/components/MapRenderer.js.map +1 -1
- package/dist/components/PortalDropdownMenu.cjs +82 -0
- package/dist/components/PortalDropdownMenu.cjs.map +1 -0
- package/dist/components/PortalDropdownMenu.d.ts +56 -0
- package/dist/components/PortalDropdownMenu.d.ts.map +1 -0
- package/dist/components/PortalDropdownMenu.js +82 -0
- package/dist/components/PortalDropdownMenu.js.map +1 -0
- package/dist/components/UIResourceRenderer.cjs +296 -256
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts +12 -0
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +296 -256
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/VideoRenderer.cjs +3 -0
- package/dist/components/VideoRenderer.cjs.map +1 -1
- package/dist/components/VideoRenderer.d.ts +5 -0
- package/dist/components/VideoRenderer.d.ts.map +1 -1
- package/dist/components/VideoRenderer.js +3 -0
- package/dist/components/VideoRenderer.js.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components.cjs +2 -0
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.cts +2 -0
- package/dist/components.d.ts +2 -0
- package/dist/components.js +2 -0
- package/dist/components.js.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CarouselRenderer.tsx +6 -0
- package/src/components/ChartJSRenderer.tsx +7 -0
- package/src/components/CodeBlockRenderer.tsx +7 -1
- package/src/components/GraphRenderer.tsx +40 -21
- package/src/components/ImageGalleryRenderer.tsx +7 -0
- package/src/components/MapRenderer.tsx +7 -0
- package/src/components/PortalDropdownMenu.test.tsx +113 -0
- package/src/components/PortalDropdownMenu.tsx +130 -0
- package/src/components/UIResourceRenderer.fluidity.test.tsx +51 -0
- package/src/components/UIResourceRenderer.tsx +50 -24
- package/src/components/VideoRenderer.tsx +7 -0
- package/src/components/index.ts +4 -0
- package/src/index.ts +2 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphRenderer.js","sources":["../../src/components/GraphRenderer.tsx"],"sourcesContent":["/**\n * GraphRenderer (v6.0.0) — generic node-link visualization powered by\n * `@antv/g6 ^5` (peer-optional). Same lazy-load pattern as\n * `ChartJSRenderer` and `MapRenderer` : the heavy lib is dynamically\n * imported only on first mount, and apps that don't install the peer\n * see an informative fallback instead of a crash.\n *\n * Spec : `@seed-ship/mcp-ui-spec@5.0.4` exports `GraphComponentParamsSchema`,\n * `GraphNode`, `GraphEdge`, `GraphLayoutName`, `GraphLayout`,\n * `GraphComponentParams` — the shape consumed here. Domain semantics\n * (`weight` etc.) are opaque to this renderer ; consumers decide what\n * the values mean.\n *\n * Copy + export : the renderer ships with `<ExpandableWrapper>` (default\n * copy = JSON of `{nodes, edges}`) plus a 3-format export menu — **PNG**\n * (visual snapshot via the underlying canvas/SVG), **Mermaid** (markdown\n * / GitHub-renderable `flowchart` syntax), **JSON** (raw reimportable\n * data). All three are computed lazily on click.\n */\n\nimport { Component, createSignal, onCleanup, onMount, Show, For } from 'solid-js'\nimport type { UIComponent } from '../types'\nimport type { GraphComponentParams, GraphLayout, GraphNode, GraphEdge } from '@seed-ship/mcp-ui-spec'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\n\n// Module-scoped lazy import promise — first call triggers the dynamic\n// import, subsequent calls reuse the resolved module.\nlet g6ModulePromise: Promise<typeof import('@antv/g6')> | undefined\n\n/**\n * Whether the `@antv/g6` peer dependency is installed and importable.\n * Resolves to `true` when the lib is available, `false` otherwise.\n *\n * Mirrors `isChartJSAvailable()` from `ChartJSRenderer`.\n */\nexport async function isG6Available(): Promise<boolean> {\n try {\n if (!g6ModulePromise) {\n g6ModulePromise = import('@antv/g6')\n }\n await g6ModulePromise\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Resolve the spec layout shorthand or object form into the config object\n * G6 v5 expects. When `layout` is omitted, picks `'force'` if edges are\n * present (universal default) or `'circular'` otherwise.\n */\nfunction resolveLayout(params: GraphComponentParams): { type: string; [key: string]: unknown } {\n const layout: GraphLayout | undefined = params.layout\n if (layout === undefined) {\n const hasEdges = (params.edges?.length ?? 0) > 0\n return { type: hasEdges ? 'force' : 'circular' }\n }\n if (typeof layout === 'string') {\n return { type: layout }\n }\n // Object form: spread the passthrough options alongside `type`.\n return { type: layout.type, ...(layout.options ?? {}) }\n}\n\n/**\n * Build the G6 v5 `behaviors` array from the params interactivity flags.\n * Defaults : drag-canvas + zoom-canvas + drag-element + click-select.\n * Any flag set to `false` opts out.\n */\nfunction resolveBehaviors(params: GraphComponentParams): string[] {\n const behaviors: string[] = []\n if (params.enableDrag !== false) behaviors.push('drag-element')\n if (params.enableZoom !== false) {\n behaviors.push('zoom-canvas', 'drag-canvas')\n }\n if (params.enableSelect !== false) behaviors.push('click-select')\n return behaviors\n}\n\n/**\n * Pick a sensible Mermaid `flowchart` direction from the resolved layout.\n * `dagre` / `tree` / `mindmap` are top-down hierarchies → TD ; everything\n * else (force, concentric, circular, grid) → LR (default mermaid).\n */\nfunction mermaidDirection(layoutType: string): 'TD' | 'LR' {\n return layoutType === 'dagre' || layoutType === 'tree' || layoutType === 'mindmap' ? 'TD' : 'LR'\n}\n\n/**\n * Sanitize a string for use inside a Mermaid node label. Mermaid breaks\n * on raw quotes / brackets / pipes ; we strip the worst offenders.\n */\nfunction mermaidLabel(s: string): string {\n return s.replace(/[\"[\\]|]/g, '').replace(/\\s+/g, ' ').trim()\n}\n\n/**\n * Convert the graph data to Mermaid `flowchart` syntax. The edge label\n * carries the optional `weight` prefix when present (e.g. `|3| label`).\n */\nfunction toMermaid(params: GraphComponentParams): string {\n const layoutType = resolveLayout(params).type\n const dir = mermaidDirection(layoutType)\n const lines: string[] = [`flowchart ${dir}`]\n for (const n of params.nodes) {\n const label = mermaidLabel(n.label ?? n.id)\n lines.push(` ${n.id}[\"${label}\"]`)\n }\n for (const e of params.edges ?? []) {\n const labelParts: string[] = []\n if (e.weight !== undefined) labelParts.push(String(e.weight))\n if (e.label) labelParts.push(mermaidLabel(e.label))\n const labelText = labelParts.join(' · ')\n if (labelText) {\n lines.push(` ${e.source} -->|${labelText}| ${e.target}`)\n } else {\n lines.push(` ${e.source} --> ${e.target}`)\n }\n }\n return lines.join('\\n')\n}\n\nfunction toJSON(params: GraphComponentParams): string {\n return JSON.stringify({ nodes: params.nodes, edges: params.edges ?? [] }, null, 2)\n}\n\nfunction downloadBlob(content: string | Blob, filename: string, mimeType?: string): void {\n const blob = typeof content === 'string' ? new Blob([content], { type: mimeType ?? 'text/plain' }) : content\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = filename\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n URL.revokeObjectURL(url)\n}\n\nexport const GraphRenderer: Component<{ component: UIComponent }> = (props) => {\n const params = () => props.component.params as GraphComponentParams\n const isExpanded = useExpanded()\n const [available, setAvailable] = createSignal<boolean | null>(null)\n const [error, setError] = createSignal<string | undefined>()\n const [exportMenuOpen, setExportMenuOpen] = createSignal(false)\n let containerRef: HTMLDivElement | undefined\n // Loosely typed because G6 is a peer-optional — we don't pull its\n // types into the bundle just to type a transient local handle.\n let graphInstance: any | undefined\n\n onMount(async () => {\n const g6Available = await isG6Available()\n setAvailable(g6Available)\n if (!g6Available || !containerRef) return\n\n try {\n const { Graph } = await g6ModulePromise!\n const p = params()\n const config: Record<string, unknown> = {\n container: containerRef,\n data: { nodes: p.nodes, edges: p.edges ?? [] },\n layout: resolveLayout(p),\n behaviors: resolveBehaviors(p),\n renderer: p.rendererPref === 'svg' ? 'svg' : 'canvas',\n }\n if (p.fitView !== false) {\n config.autoFit = 'view'\n }\n if (p.tooltip !== false) {\n // Built-in tooltip plugin — shows label + a compact dump of\n // node.data on hover. Consumers can opt out with `tooltip: false`.\n config.plugins = [\n {\n type: 'tooltip',\n getContent: (_evt: unknown, items: any[]) => {\n const item = items?.[0]\n if (!item) return ''\n const label = item.label ?? item.id ?? ''\n const data = item.data ? JSON.stringify(item.data) : ''\n return `<div style=\"padding:4px 8px\"><strong>${escapeHtml(String(label))}</strong>${\n data ? `<br><span style=\"font-size:11px;opacity:0.7\">${escapeHtml(data)}</span>` : ''\n }</div>`\n },\n },\n ]\n }\n graphInstance = new (Graph as any)(config)\n await graphInstance.render()\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to render graph')\n }\n })\n\n onCleanup(() => {\n try {\n graphInstance?.destroy()\n } catch {\n // G6 destroy can throw on already-destroyed instances or partial\n // init failures — silent because the component is unmounting anyway.\n }\n graphInstance = undefined\n })\n\n // ─── Export handlers ────────────────────────────────────────────────\n const handleExportJSON = () => {\n downloadBlob(toJSON(params()), `${graphFilenameStem(params())}.json`, 'application/json')\n setExportMenuOpen(false)\n }\n\n const handleExportMermaid = () => {\n downloadBlob(toMermaid(params()), `${graphFilenameStem(params())}.mmd`, 'text/plain')\n setExportMenuOpen(false)\n }\n\n const handleExportPNG = async () => {\n if (!graphInstance) return\n try {\n // G6 v5 exposes `toDataURL()` on the graph instance.\n const dataUrl: string = await graphInstance.toDataURL?.('image/png')\n if (!dataUrl) {\n // Fallback: try to grab the underlying canvas directly.\n const canvas = containerRef?.querySelector('canvas')\n if (canvas) {\n const url = (canvas as HTMLCanvasElement).toDataURL('image/png')\n await downloadDataUrl(url, `${graphFilenameStem(params())}.png`)\n } else {\n setError('PNG export not supported in current renderer mode')\n }\n } else {\n await downloadDataUrl(dataUrl, `${graphFilenameStem(params())}.png`)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'PNG export failed')\n }\n setExportMenuOpen(false)\n }\n\n return (\n <Show\n when={available() === true}\n fallback={\n <Show\n when={available() === false}\n fallback={\n // Loading skeleton while we determine peer availability\n <div class=\"w-full p-4 bg-gray-50 dark:bg-gray-800/40 border border-gray-200 dark:border-gray-700 rounded-lg animate-pulse\">\n <div class=\"h-4 w-32 bg-gray-200 dark:bg-gray-700 rounded mb-2\" />\n <div class=\"h-3 w-48 bg-gray-200 dark:bg-gray-700 rounded\" />\n </div>\n }\n >\n <div class=\"w-full p-4 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg\">\n <p class=\"text-sm font-medium text-yellow-900 dark:text-yellow-100\">\n Graph rendering unavailable\n </p>\n <p class=\"text-xs text-yellow-700 dark:text-yellow-300 mt-1\">\n Install <code>@antv/g6</code> peer dependency to render <code>type: \"graph\"</code> components.\n </p>\n </div>\n </Show>\n }\n >\n <ExpandableWrapper\n title={params().title ?? 'Graph'}\n copyData={toJSON(params())}\n copyLabel=\"Copy graph (JSON)\"\n >\n <div class={`relative w-full ${params().className ?? ''} ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Export menu — top-right, mirrors TableRenderer's pattern */}\n <div class=\"absolute right-2 top-2 z-10\">\n <button\n type=\"button\"\n onClick={() => setExportMenuOpen((v) => !v)}\n class=\"px-2 py-1 text-xs bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300\"\n title=\"Export graph\"\n aria-label=\"Export graph\"\n aria-expanded={exportMenuOpen()}\n >\n Export ▾\n </button>\n <Show when={exportMenuOpen()}>\n <div class=\"absolute right-0 mt-1 w-44 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded shadow-lg text-xs\">\n <For each={[\n { label: 'Download PNG', onClick: handleExportPNG, hint: 'visual snapshot' },\n { label: 'Download Mermaid', onClick: handleExportMermaid, hint: 'markdown / GitHub' },\n { label: 'Download JSON', onClick: handleExportJSON, hint: 'raw data' },\n ]}>\n {(item) => (\n <button\n type=\"button\"\n onClick={item.onClick}\n class=\"w-full text-left px-3 py-2 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-gray-700 last:border-b-0\"\n >\n <div class=\"font-medium\">{item.label}</div>\n <div class=\"text-[10px] text-gray-500 dark:text-gray-400\">{item.hint}</div>\n </button>\n )}\n </For>\n </div>\n </Show>\n </div>\n\n <div\n ref={containerRef}\n class={`bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0' : ''\n }`}\n style={\n isExpanded()\n ? `height: 100%; width: ${params().width ?? '100%'};`\n : `height: ${params().height ?? '400px'}; width: ${params().width ?? '100%'};`\n }\n />\n <Show when={error()}>\n <p class=\"text-xs text-red-600 dark:text-red-400 mt-1\">Render error: {error()}</p>\n </Show>\n </div>\n </ExpandableWrapper>\n </Show>\n )\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────\n\nfunction graphFilenameStem(params: GraphComponentParams): string {\n const base = (params.title ?? 'graph').replace(/[^a-z0-9-_]+/gi, '-').replace(/^-+|-+$/g, '')\n return base || 'graph'\n}\n\nasync function downloadDataUrl(dataUrl: string, filename: string): Promise<void> {\n const res = await fetch(dataUrl)\n const blob = await res.blob()\n downloadBlob(blob, filename)\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[&<>\"']/g, (c) => {\n switch (c) {\n case '&': return '&'\n case '<': return '<'\n case '>': return '>'\n case '\"': return '"'\n case \"'\": return '''\n default: return c\n }\n })\n}\n\n// Re-export for tests + consumers that want to compose their own export menu\nexport { toMermaid as graphToMermaid, toJSON as graphToJSON }\n"],"names":["g6ModulePromise","isG6Available","resolveLayout","params","layout","undefined","hasEdges","edges","length","type","options","resolveBehaviors","behaviors","enableDrag","push","enableZoom","enableSelect","mermaidDirection","layoutType","mermaidLabel","s","replace","trim","toMermaid","dir","lines","n","nodes","label","id","e","labelParts","weight","String","labelText","join","source","target","toJSON","JSON","stringify","downloadBlob","content","filename","mimeType","blob","Blob","url","URL","createObjectURL","a","document","createElement","href","download","body","appendChild","click","removeChild","revokeObjectURL","GraphRenderer","props","component","isExpanded","useExpanded","available","setAvailable","createSignal","error","setError","exportMenuOpen","setExportMenuOpen","containerRef","graphInstance","onMount","g6Available","Graph","p","config","container","data","renderer","rendererPref","fitView","autoFit","tooltip","plugins","getContent","_evt","items","item","escapeHtml","render","err","Error","message","onCleanup","destroy","handleExportJSON","graphFilenameStem","handleExportMermaid","handleExportPNG","dataUrl","toDataURL","canvas","querySelector","downloadDataUrl","_$createComponent","Show","when","fallback","_$getNextElement","_tmpl$5","children","_tmpl$4","ExpandableWrapper","title","copyData","copyLabel","_el$","_tmpl$3","_el$2","firstChild","_el$3","_el$5","nextSibling","_el$6","_co$","_$getNextMarker","_el$7","_el$10","_el$11","_co$3","$$click","v","_$insert","_el$4","_tmpl$","For","each","onClick","hint","_el$14","_tmpl$6","_el$15","_el$16","_$addEventListener","_$runHydrationEvents","_ref$","_$use","_el$8","_tmpl$2","_el$9","_el$0","_el$1","_co$2","_$effect","_p$","_v$","className","_v$2","_v$3","_v$4","width","height","_$className","t","_$setAttribute","o","_$style","base","res","fetch","c","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GraphRenderer.js","sources":["../../src/components/GraphRenderer.tsx"],"sourcesContent":["/**\n * GraphRenderer (v6.0.0) — generic node-link visualization powered by\n * `@antv/g6 ^5` (peer-optional). Same lazy-load pattern as\n * `ChartJSRenderer` and `MapRenderer` : the heavy lib is dynamically\n * imported only on first mount, and apps that don't install the peer\n * see an informative fallback instead of a crash.\n *\n * Spec : `@seed-ship/mcp-ui-spec@5.0.4` exports `GraphComponentParamsSchema`,\n * `GraphNode`, `GraphEdge`, `GraphLayoutName`, `GraphLayout`,\n * `GraphComponentParams` — the shape consumed here. Domain semantics\n * (`weight` etc.) are opaque to this renderer ; consumers decide what\n * the values mean.\n *\n * Copy + export : the renderer ships with `<ExpandableWrapper>` (default\n * copy = JSON of `{nodes, edges}`) plus a 3-format export menu — **PNG**\n * (visual snapshot via the underlying canvas/SVG), **Mermaid** (markdown\n * / GitHub-renderable `flowchart` syntax), **JSON** (raw reimportable\n * data). All three are computed lazily on click.\n */\n\nimport { Component, createSignal, onCleanup, onMount, Show, For } from 'solid-js'\nimport type { UIComponent } from '../types'\nimport type { GraphComponentParams, GraphLayout, GraphNode, GraphEdge } from '@seed-ship/mcp-ui-spec'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\nimport { PortalDropdownMenu } from './PortalDropdownMenu'\n\n// Module-scoped lazy import promise — first call triggers the dynamic\n// import, subsequent calls reuse the resolved module.\nlet g6ModulePromise: Promise<typeof import('@antv/g6')> | undefined\n\n/**\n * Whether the `@antv/g6` peer dependency is installed and importable.\n * Resolves to `true` when the lib is available, `false` otherwise.\n *\n * Mirrors `isChartJSAvailable()` from `ChartJSRenderer`.\n */\nexport async function isG6Available(): Promise<boolean> {\n try {\n if (!g6ModulePromise) {\n g6ModulePromise = import('@antv/g6')\n }\n await g6ModulePromise\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Resolve the spec layout shorthand or object form into the config object\n * G6 v5 expects. When `layout` is omitted, picks `'force'` if edges are\n * present (universal default) or `'circular'` otherwise.\n */\nfunction resolveLayout(params: GraphComponentParams): { type: string; [key: string]: unknown } {\n const layout: GraphLayout | undefined = params.layout\n if (layout === undefined) {\n const hasEdges = (params.edges?.length ?? 0) > 0\n return { type: hasEdges ? 'force' : 'circular' }\n }\n if (typeof layout === 'string') {\n return { type: layout }\n }\n // Object form: spread the passthrough options alongside `type`.\n return { type: layout.type, ...(layout.options ?? {}) }\n}\n\n/**\n * Build the G6 v5 `behaviors` array from the params interactivity flags.\n * Defaults : drag-canvas + zoom-canvas + drag-element + click-select.\n * Any flag set to `false` opts out.\n */\nfunction resolveBehaviors(params: GraphComponentParams): string[] {\n const behaviors: string[] = []\n if (params.enableDrag !== false) behaviors.push('drag-element')\n if (params.enableZoom !== false) {\n behaviors.push('zoom-canvas', 'drag-canvas')\n }\n if (params.enableSelect !== false) behaviors.push('click-select')\n return behaviors\n}\n\n/**\n * Pick a sensible Mermaid `flowchart` direction from the resolved layout.\n * `dagre` / `tree` / `mindmap` are top-down hierarchies → TD ; everything\n * else (force, concentric, circular, grid) → LR (default mermaid).\n */\nfunction mermaidDirection(layoutType: string): 'TD' | 'LR' {\n return layoutType === 'dagre' || layoutType === 'tree' || layoutType === 'mindmap' ? 'TD' : 'LR'\n}\n\n/**\n * Sanitize a string for use inside a Mermaid node label. Mermaid breaks\n * on raw quotes / brackets / pipes ; we strip the worst offenders.\n */\nfunction mermaidLabel(s: string): string {\n return s.replace(/[\"[\\]|]/g, '').replace(/\\s+/g, ' ').trim()\n}\n\n/**\n * Convert the graph data to Mermaid `flowchart` syntax. The edge label\n * carries the optional `weight` prefix when present (e.g. `|3| label`).\n */\nfunction toMermaid(params: GraphComponentParams): string {\n const layoutType = resolveLayout(params).type\n const dir = mermaidDirection(layoutType)\n const lines: string[] = [`flowchart ${dir}`]\n for (const n of params.nodes) {\n const label = mermaidLabel(n.label ?? n.id)\n lines.push(` ${n.id}[\"${label}\"]`)\n }\n for (const e of params.edges ?? []) {\n const labelParts: string[] = []\n if (e.weight !== undefined) labelParts.push(String(e.weight))\n if (e.label) labelParts.push(mermaidLabel(e.label))\n const labelText = labelParts.join(' · ')\n if (labelText) {\n lines.push(` ${e.source} -->|${labelText}| ${e.target}`)\n } else {\n lines.push(` ${e.source} --> ${e.target}`)\n }\n }\n return lines.join('\\n')\n}\n\nfunction toJSON(params: GraphComponentParams): string {\n return JSON.stringify({ nodes: params.nodes, edges: params.edges ?? [] }, null, 2)\n}\n\nfunction downloadBlob(content: string | Blob, filename: string, mimeType?: string): void {\n const blob = typeof content === 'string' ? new Blob([content], { type: mimeType ?? 'text/plain' }) : content\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = filename\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n URL.revokeObjectURL(url)\n}\n\nexport interface GraphRendererProps {\n component: UIComponent\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible'\n}\n\nexport const GraphRenderer: Component<GraphRendererProps> = (props) => {\n const params = () => props.component.params as GraphComponentParams\n const isExpanded = useExpanded()\n const [available, setAvailable] = createSignal<boolean | null>(null)\n const [error, setError] = createSignal<string | undefined>()\n const [exportMenuOpen, setExportMenuOpen] = createSignal(false)\n let containerRef: HTMLDivElement | undefined\n // v6.4.0 — trigger ref consumed by <PortalDropdownMenu> for positioning\n let exportTriggerRef: HTMLButtonElement | undefined\n // Loosely typed because G6 is a peer-optional — we don't pull its\n // types into the bundle just to type a transient local handle.\n let graphInstance: any | undefined\n\n onMount(async () => {\n const g6Available = await isG6Available()\n setAvailable(g6Available)\n if (!g6Available || !containerRef) return\n\n try {\n const { Graph } = await g6ModulePromise!\n const p = params()\n const config: Record<string, unknown> = {\n container: containerRef,\n data: { nodes: p.nodes, edges: p.edges ?? [] },\n layout: resolveLayout(p),\n behaviors: resolveBehaviors(p),\n renderer: p.rendererPref === 'svg' ? 'svg' : 'canvas',\n }\n if (p.fitView !== false) {\n config.autoFit = 'view'\n }\n if (p.tooltip !== false) {\n // Built-in tooltip plugin — shows label + a compact dump of\n // node.data on hover. Consumers can opt out with `tooltip: false`.\n config.plugins = [\n {\n type: 'tooltip',\n getContent: (_evt: unknown, items: any[]) => {\n const item = items?.[0]\n if (!item) return ''\n const label = item.label ?? item.id ?? ''\n const data = item.data ? JSON.stringify(item.data) : ''\n return `<div style=\"padding:4px 8px\"><strong>${escapeHtml(String(label))}</strong>${\n data ? `<br><span style=\"font-size:11px;opacity:0.7\">${escapeHtml(data)}</span>` : ''\n }</div>`\n },\n },\n ]\n }\n graphInstance = new (Graph as any)(config)\n await graphInstance.render()\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to render graph')\n }\n })\n\n onCleanup(() => {\n try {\n graphInstance?.destroy()\n } catch {\n // G6 destroy can throw on already-destroyed instances or partial\n // init failures — silent because the component is unmounting anyway.\n }\n graphInstance = undefined\n })\n\n // ─── Export handlers ────────────────────────────────────────────────\n const handleExportJSON = () => {\n downloadBlob(toJSON(params()), `${graphFilenameStem(params())}.json`, 'application/json')\n setExportMenuOpen(false)\n }\n\n const handleExportMermaid = () => {\n downloadBlob(toMermaid(params()), `${graphFilenameStem(params())}.mmd`, 'text/plain')\n setExportMenuOpen(false)\n }\n\n const handleExportPNG = async () => {\n if (!graphInstance) return\n try {\n // G6 v5 exposes `toDataURL()` on the graph instance.\n const dataUrl: string = await graphInstance.toDataURL?.('image/png')\n if (!dataUrl) {\n // Fallback: try to grab the underlying canvas directly.\n const canvas = containerRef?.querySelector('canvas')\n if (canvas) {\n const url = (canvas as HTMLCanvasElement).toDataURL('image/png')\n await downloadDataUrl(url, `${graphFilenameStem(params())}.png`)\n } else {\n setError('PNG export not supported in current renderer mode')\n }\n } else {\n await downloadDataUrl(dataUrl, `${graphFilenameStem(params())}.png`)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'PNG export failed')\n }\n setExportMenuOpen(false)\n }\n\n return (\n <Show\n when={available() === true}\n fallback={\n <Show\n when={available() === false}\n fallback={\n // Loading skeleton while we determine peer availability\n <div class=\"w-full p-4 bg-gray-50 dark:bg-gray-800/40 border border-gray-200 dark:border-gray-700 rounded-lg animate-pulse\">\n <div class=\"h-4 w-32 bg-gray-200 dark:bg-gray-700 rounded mb-2\" />\n <div class=\"h-3 w-48 bg-gray-200 dark:bg-gray-700 rounded\" />\n </div>\n }\n >\n <div class=\"w-full p-4 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg\">\n <p class=\"text-sm font-medium text-yellow-900 dark:text-yellow-100\">\n Graph rendering unavailable\n </p>\n <p class=\"text-xs text-yellow-700 dark:text-yellow-300 mt-1\">\n Install <code>@antv/g6</code> peer dependency to render <code>type: \"graph\"</code> components.\n </p>\n </div>\n </Show>\n }\n >\n <ExpandableWrapper\n title={params().title ?? 'Graph'}\n copyData={toJSON(params())}\n copyLabel=\"Copy graph (JSON)\"\n toolbarVariant={props.toolbarVariant}\n >\n <div class={`relative w-full ${params().className ?? ''} ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Export menu — top-right, mirrors TableRenderer's pattern */}\n <div class=\"absolute right-2 top-2 z-10\">\n <button\n ref={exportTriggerRef}\n type=\"button\"\n onClick={() => setExportMenuOpen((v) => !v)}\n class=\"px-2 py-1 text-xs bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300\"\n title=\"Export graph\"\n aria-label=\"Export graph\"\n aria-haspopup=\"menu\"\n aria-expanded={exportMenuOpen()}\n >\n Export ▾\n </button>\n <PortalDropdownMenu\n open={exportMenuOpen()}\n onClose={() => setExportMenuOpen(false)}\n trigger={exportTriggerRef}\n width={176}\n class=\"text-xs\"\n >\n <For each={[\n { label: 'Download PNG', onClick: handleExportPNG, hint: 'visual snapshot' },\n { label: 'Download Mermaid', onClick: handleExportMermaid, hint: 'markdown / GitHub' },\n { label: 'Download JSON', onClick: handleExportJSON, hint: 'raw data' },\n ]}>\n {(item) => (\n <button\n type=\"button\"\n onClick={item.onClick}\n class=\"w-full text-left px-3 py-2 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-gray-700 last:border-b-0\"\n >\n <div class=\"font-medium\">{item.label}</div>\n <div class=\"text-[10px] text-gray-500 dark:text-gray-400\">{item.hint}</div>\n </button>\n )}\n </For>\n </PortalDropdownMenu>\n </div>\n\n <div\n ref={containerRef}\n class={`bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0' : ''\n }`}\n style={\n isExpanded()\n ? `height: 100%; width: ${params().width ?? '100%'};`\n : `height: ${params().height ?? '400px'}; width: ${params().width ?? '100%'};`\n }\n />\n <Show when={error()}>\n <p class=\"text-xs text-red-600 dark:text-red-400 mt-1\">Render error: {error()}</p>\n </Show>\n </div>\n </ExpandableWrapper>\n </Show>\n )\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────\n\nfunction graphFilenameStem(params: GraphComponentParams): string {\n const base = (params.title ?? 'graph').replace(/[^a-z0-9-_]+/gi, '-').replace(/^-+|-+$/g, '')\n return base || 'graph'\n}\n\nasync function downloadDataUrl(dataUrl: string, filename: string): Promise<void> {\n const res = await fetch(dataUrl)\n const blob = await res.blob()\n downloadBlob(blob, filename)\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[&<>\"']/g, (c) => {\n switch (c) {\n case '&': return '&'\n case '<': return '<'\n case '>': return '>'\n case '\"': return '"'\n case \"'\": return '''\n default: return c\n }\n })\n}\n\n// Re-export for tests + consumers that want to compose their own export menu\nexport { toMermaid as graphToMermaid, toJSON as graphToJSON }\n"],"names":["g6ModulePromise","isG6Available","resolveLayout","params","layout","undefined","hasEdges","edges","length","type","options","resolveBehaviors","behaviors","enableDrag","push","enableZoom","enableSelect","mermaidDirection","layoutType","mermaidLabel","s","replace","trim","toMermaid","dir","lines","n","nodes","label","id","e","labelParts","weight","String","labelText","join","source","target","toJSON","JSON","stringify","downloadBlob","content","filename","mimeType","blob","Blob","url","URL","createObjectURL","a","document","createElement","href","download","body","appendChild","click","removeChild","revokeObjectURL","GraphRenderer","props","component","isExpanded","useExpanded","available","setAvailable","createSignal","error","setError","exportMenuOpen","setExportMenuOpen","containerRef","exportTriggerRef","graphInstance","onMount","g6Available","Graph","p","config","container","data","renderer","rendererPref","fitView","autoFit","tooltip","plugins","getContent","_evt","items","item","escapeHtml","render","err","Error","message","onCleanup","destroy","handleExportJSON","graphFilenameStem","handleExportMermaid","handleExportPNG","dataUrl","toDataURL","canvas","querySelector","downloadDataUrl","_$createComponent","Show","when","fallback","_$getNextElement","_tmpl$4","children","_tmpl$3","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_co$","_$getNextMarker","_el$6","_el$1","_el$10","_co$3","$$click","v","_ref$","_$use","_$insert","PortalDropdownMenu","open","onClose","trigger","width","For","each","onClick","hint","_el$13","_tmpl$5","_el$14","_el$15","_$addEventListener","_$runHydrationEvents","_ref$2","_el$7","_tmpl$","_el$8","_el$9","_el$0","_co$2","_$effect","_p$","_v$","className","_v$2","_v$3","_v$4","height","_$className","t","_$setAttribute","o","_$style","base","res","fetch","c","_$delegateEvents"],"mappings":"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"}
|
|
@@ -72,6 +72,9 @@ const ImageGalleryRenderer = (props) => {
|
|
|
72
72
|
return imagesToTextList(params());
|
|
73
73
|
},
|
|
74
74
|
copyLabel: "Copy image URLs",
|
|
75
|
+
get toolbarVariant() {
|
|
76
|
+
return props.toolbarVariant;
|
|
77
|
+
},
|
|
75
78
|
get children() {
|
|
76
79
|
var _el$ = web.getNextElement(_tmpl$2), _el$5 = _el$.firstChild, [_el$6, _co$] = web.getNextMarker(_el$5.nextSibling), _el$4 = _el$6.nextSibling, _el$7 = _el$4.nextSibling, [_el$8, _co$2] = web.getNextMarker(_el$7.nextSibling);
|
|
77
80
|
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageGalleryRenderer.cjs","sources":["../../src/components/ImageGalleryRenderer.tsx"],"sourcesContent":["/**\n * ImageGalleryRenderer - Gallery view for multiple images\n * Sprint 5: Media Components\n */\n\nimport { Component, createSignal, For, Show } from 'solid-js'\nimport type { UIComponent, ImageGalleryParams } from '../types'\nimport { LightboxOverlay } from './LightboxOverlay'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\n\nexport interface ImageGalleryRendererProps {\n /**\n * UIComponent containing gallery params\n */\n component?: UIComponent\n\n /**\n * Direct gallery params (alternative to component)\n */\n params?: ImageGalleryParams\n}\n\n/** Build a newline-separated list of image URLs (with captions when present)\n * for the ExpandableWrapper copy button. v6.2.0. */\nfunction imagesToTextList(p: ImageGalleryParams | undefined): string {\n if (!p) return ''\n return (p.images ?? [])\n .map((img) => (img.caption ? `${img.url}\\t${img.caption}` : img.url))\n .join('\\n')\n}\n\nexport const ImageGalleryRenderer: Component<ImageGalleryRendererProps> = (props) => {\n const [selectedIndex, setSelectedIndex] = createSignal<number | null>(null)\n const isExpanded = useExpanded()\n\n const params = () => props.params || (props.component?.params as ImageGalleryParams)\n\n const columnsClass = () => {\n switch (params()?.columns) {\n case 2:\n return 'grid-cols-2'\n case 3:\n return 'grid-cols-3'\n case 4:\n return 'grid-cols-4'\n case 5:\n return 'grid-cols-5'\n default:\n return 'grid-cols-3'\n }\n }\n\n const gapClass = () => {\n switch (params()?.gap) {\n case 'none':\n return 'gap-0'\n case 'sm':\n return 'gap-1'\n case 'lg':\n return 'gap-4'\n default:\n return 'gap-2'\n }\n }\n\n const aspectClass = () => {\n switch (params()?.aspectRatio) {\n case '1:1':\n return 'aspect-square'\n case '16:9':\n return 'aspect-video'\n case '4:3':\n return 'aspect-[4/3]'\n default:\n return ''\n }\n }\n\n const handleImageClick = (index: number) => {\n if (params()?.lightbox !== false) {\n setSelectedIndex(index)\n }\n }\n\n return (\n <ExpandableWrapper\n title={params()?.title || 'Gallery'}\n copyData={imagesToTextList(params())}\n copyLabel=\"Copy image URLs\"\n >\n <div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Title */}\n <Show when={params()?.title}>\n <div class=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params()!.title}</h3>\n </div>\n </Show>\n\n {/* Gallery Grid */}\n <div class={`grid ${columnsClass()} ${gapClass()} p-4 ${isExpanded() ? 'flex-1 min-h-0 overflow-auto' : ''}`}>\n <For each={params()?.images}>\n {(image, index) => (\n <button\n class={`relative overflow-hidden rounded-md focus:ring-2 focus:ring-blue-500 focus:outline-none group ${aspectClass()}`}\n onClick={() => handleImageClick(index())}\n type=\"button\"\n aria-label={image.alt || `View image ${index() + 1}`}\n >\n <img\n src={image.thumbnail || image.url}\n alt={image.alt || `Image ${index() + 1}`}\n srcset={image.srcset}\n sizes={image.sizes}\n class=\"w-full h-full object-cover group-hover:scale-105 transition-transform duration-200\"\n loading=\"lazy\"\n />\n\n {/* Hover overlay */}\n <div class=\"absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors duration-200\" />\n\n {/* Caption overlay */}\n <Show when={image.caption && params()?.showCaptions}>\n <div class=\"absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent text-white text-xs p-2 pt-4\">\n <span class=\"truncate block\">{image.caption}</span>\n </div>\n </Show>\n\n {/* Zoom icon on hover */}\n <Show when={params()?.lightbox !== false}>\n <div class=\"absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-200\">\n <div class=\"bg-white/90 dark:bg-gray-800/90 rounded-full p-2\">\n <svg\n class=\"w-5 h-5 text-gray-700 dark:text-gray-200\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7\"\n />\n </svg>\n </div>\n </div>\n </Show>\n </button>\n )}\n </For>\n </div>\n\n {/* Lightbox */}\n <LightboxOverlay\n images={params()?.images || []}\n selectedIndex={selectedIndex()}\n onClose={() => setSelectedIndex(null)}\n onNavigate={setSelectedIndex}\n />\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["imagesToTextList","p","images","map","img","caption","url","join","ImageGalleryRenderer","props","selectedIndex","setSelectedIndex","createSignal","isExpanded","useExpanded","params","component","columnsClass","columns","gapClass","gap","aspectClass","aspectRatio","handleImageClick","index","lightbox","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","children","_el$","_$getNextElement","_tmpl$2","_el$5","firstChild","_el$6","_co$","_$getNextMarker","nextSibling","_el$4","_el$7","_el$8","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","For","each","image","_el$9","_tmpl$5","_el$0","_el$1","_el$13","_el$14","_co$3","_el$15","_el$16","_co$4","$$click","_$memo","showCaptions","_el$10","_tmpl$3","_el$11","_tmpl$4","_$effect","_p$","_v$3","_v$4","alt","_v$5","thumbnail","_v$6","_v$7","srcset","_v$8","sizes","e","_$className","t","_$setAttribute","a","o","i","n","undefined","_$runHydrationEvents","LightboxOverlay","onClose","onNavigate","_v$","_v$2","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ImageGalleryRenderer.cjs","sources":["../../src/components/ImageGalleryRenderer.tsx"],"sourcesContent":["/**\n * ImageGalleryRenderer - Gallery view for multiple images\n * Sprint 5: Media Components\n */\n\nimport { Component, createSignal, For, Show } from 'solid-js'\nimport type { UIComponent, ImageGalleryParams } from '../types'\nimport { LightboxOverlay } from './LightboxOverlay'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\n\nexport interface ImageGalleryRendererProps {\n /**\n * UIComponent containing gallery params\n */\n component?: UIComponent\n\n /**\n * Direct gallery params (alternative to component)\n */\n params?: ImageGalleryParams\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible'\n}\n\n/** Build a newline-separated list of image URLs (with captions when present)\n * for the ExpandableWrapper copy button. v6.2.0. */\nfunction imagesToTextList(p: ImageGalleryParams | undefined): string {\n if (!p) return ''\n return (p.images ?? [])\n .map((img) => (img.caption ? `${img.url}\\t${img.caption}` : img.url))\n .join('\\n')\n}\n\nexport const ImageGalleryRenderer: Component<ImageGalleryRendererProps> = (props) => {\n const [selectedIndex, setSelectedIndex] = createSignal<number | null>(null)\n const isExpanded = useExpanded()\n\n const params = () => props.params || (props.component?.params as ImageGalleryParams)\n\n const columnsClass = () => {\n switch (params()?.columns) {\n case 2:\n return 'grid-cols-2'\n case 3:\n return 'grid-cols-3'\n case 4:\n return 'grid-cols-4'\n case 5:\n return 'grid-cols-5'\n default:\n return 'grid-cols-3'\n }\n }\n\n const gapClass = () => {\n switch (params()?.gap) {\n case 'none':\n return 'gap-0'\n case 'sm':\n return 'gap-1'\n case 'lg':\n return 'gap-4'\n default:\n return 'gap-2'\n }\n }\n\n const aspectClass = () => {\n switch (params()?.aspectRatio) {\n case '1:1':\n return 'aspect-square'\n case '16:9':\n return 'aspect-video'\n case '4:3':\n return 'aspect-[4/3]'\n default:\n return ''\n }\n }\n\n const handleImageClick = (index: number) => {\n if (params()?.lightbox !== false) {\n setSelectedIndex(index)\n }\n }\n\n return (\n <ExpandableWrapper\n title={params()?.title || 'Gallery'}\n copyData={imagesToTextList(params())}\n copyLabel=\"Copy image URLs\"\n toolbarVariant={props.toolbarVariant}\n >\n <div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Title */}\n <Show when={params()?.title}>\n <div class=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params()!.title}</h3>\n </div>\n </Show>\n\n {/* Gallery Grid */}\n <div class={`grid ${columnsClass()} ${gapClass()} p-4 ${isExpanded() ? 'flex-1 min-h-0 overflow-auto' : ''}`}>\n <For each={params()?.images}>\n {(image, index) => (\n <button\n class={`relative overflow-hidden rounded-md focus:ring-2 focus:ring-blue-500 focus:outline-none group ${aspectClass()}`}\n onClick={() => handleImageClick(index())}\n type=\"button\"\n aria-label={image.alt || `View image ${index() + 1}`}\n >\n <img\n src={image.thumbnail || image.url}\n alt={image.alt || `Image ${index() + 1}`}\n srcset={image.srcset}\n sizes={image.sizes}\n class=\"w-full h-full object-cover group-hover:scale-105 transition-transform duration-200\"\n loading=\"lazy\"\n />\n\n {/* Hover overlay */}\n <div class=\"absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors duration-200\" />\n\n {/* Caption overlay */}\n <Show when={image.caption && params()?.showCaptions}>\n <div class=\"absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent text-white text-xs p-2 pt-4\">\n <span class=\"truncate block\">{image.caption}</span>\n </div>\n </Show>\n\n {/* Zoom icon on hover */}\n <Show when={params()?.lightbox !== false}>\n <div class=\"absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-200\">\n <div class=\"bg-white/90 dark:bg-gray-800/90 rounded-full p-2\">\n <svg\n class=\"w-5 h-5 text-gray-700 dark:text-gray-200\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7\"\n />\n </svg>\n </div>\n </div>\n </Show>\n </button>\n )}\n </For>\n </div>\n\n {/* Lightbox */}\n <LightboxOverlay\n images={params()?.images || []}\n selectedIndex={selectedIndex()}\n onClose={() => setSelectedIndex(null)}\n onNavigate={setSelectedIndex}\n />\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["imagesToTextList","p","images","map","img","caption","url","join","ImageGalleryRenderer","props","selectedIndex","setSelectedIndex","createSignal","isExpanded","useExpanded","params","component","columnsClass","columns","gapClass","gap","aspectClass","aspectRatio","handleImageClick","index","lightbox","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$2","_el$5","firstChild","_el$6","_co$","_$getNextMarker","nextSibling","_el$4","_el$7","_el$8","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","For","each","image","_el$9","_tmpl$5","_el$0","_el$1","_el$13","_el$14","_co$3","_el$15","_el$16","_co$4","$$click","_$memo","showCaptions","_el$10","_tmpl$3","_el$11","_tmpl$4","_$effect","_p$","_v$3","_v$4","alt","_v$5","thumbnail","_v$6","_v$7","srcset","_v$8","sizes","e","_$className","t","_$setAttribute","a","o","i","n","undefined","_$runHydrationEvents","LightboxOverlay","onClose","onNavigate","_v$","_v$2","_$delegateEvents"],"mappings":"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"}
|
|
@@ -13,6 +13,11 @@ export interface ImageGalleryRendererProps {
|
|
|
13
13
|
* Direct gallery params (alternative to component)
|
|
14
14
|
*/
|
|
15
15
|
params?: ImageGalleryParams;
|
|
16
|
+
/**
|
|
17
|
+
* Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).
|
|
18
|
+
* @see ExpandableWrapperProps.toolbarVariant
|
|
19
|
+
*/
|
|
20
|
+
toolbarVariant?: 'hover' | 'always-visible';
|
|
16
21
|
}
|
|
17
22
|
export declare const ImageGalleryRenderer: Component<ImageGalleryRendererProps>;
|
|
18
23
|
//# sourceMappingURL=ImageGalleryRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageGalleryRenderer.d.ts","sourceRoot":"","sources":["../../src/components/ImageGalleryRenderer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAA2B,MAAM,UAAU,CAAA;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAI/D,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"ImageGalleryRenderer.d.ts","sourceRoot":"","sources":["../../src/components/ImageGalleryRenderer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAA2B,MAAM,UAAU,CAAA;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAI/D,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAE3B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAA;CAC5C;AAWD,eAAO,MAAM,oBAAoB,EAAE,SAAS,CAAC,yBAAyB,CAsIrE,CAAA"}
|
|
@@ -70,6 +70,9 @@ const ImageGalleryRenderer = (props) => {
|
|
|
70
70
|
return imagesToTextList(params());
|
|
71
71
|
},
|
|
72
72
|
copyLabel: "Copy image URLs",
|
|
73
|
+
get toolbarVariant() {
|
|
74
|
+
return props.toolbarVariant;
|
|
75
|
+
},
|
|
73
76
|
get children() {
|
|
74
77
|
var _el$ = getNextElement(_tmpl$2), _el$5 = _el$.firstChild, [_el$6, _co$] = getNextMarker(_el$5.nextSibling), _el$4 = _el$6.nextSibling, _el$7 = _el$4.nextSibling, [_el$8, _co$2] = getNextMarker(_el$7.nextSibling);
|
|
75
78
|
insert(_el$, createComponent(Show, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageGalleryRenderer.js","sources":["../../src/components/ImageGalleryRenderer.tsx"],"sourcesContent":["/**\n * ImageGalleryRenderer - Gallery view for multiple images\n * Sprint 5: Media Components\n */\n\nimport { Component, createSignal, For, Show } from 'solid-js'\nimport type { UIComponent, ImageGalleryParams } from '../types'\nimport { LightboxOverlay } from './LightboxOverlay'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\n\nexport interface ImageGalleryRendererProps {\n /**\n * UIComponent containing gallery params\n */\n component?: UIComponent\n\n /**\n * Direct gallery params (alternative to component)\n */\n params?: ImageGalleryParams\n}\n\n/** Build a newline-separated list of image URLs (with captions when present)\n * for the ExpandableWrapper copy button. v6.2.0. */\nfunction imagesToTextList(p: ImageGalleryParams | undefined): string {\n if (!p) return ''\n return (p.images ?? [])\n .map((img) => (img.caption ? `${img.url}\\t${img.caption}` : img.url))\n .join('\\n')\n}\n\nexport const ImageGalleryRenderer: Component<ImageGalleryRendererProps> = (props) => {\n const [selectedIndex, setSelectedIndex] = createSignal<number | null>(null)\n const isExpanded = useExpanded()\n\n const params = () => props.params || (props.component?.params as ImageGalleryParams)\n\n const columnsClass = () => {\n switch (params()?.columns) {\n case 2:\n return 'grid-cols-2'\n case 3:\n return 'grid-cols-3'\n case 4:\n return 'grid-cols-4'\n case 5:\n return 'grid-cols-5'\n default:\n return 'grid-cols-3'\n }\n }\n\n const gapClass = () => {\n switch (params()?.gap) {\n case 'none':\n return 'gap-0'\n case 'sm':\n return 'gap-1'\n case 'lg':\n return 'gap-4'\n default:\n return 'gap-2'\n }\n }\n\n const aspectClass = () => {\n switch (params()?.aspectRatio) {\n case '1:1':\n return 'aspect-square'\n case '16:9':\n return 'aspect-video'\n case '4:3':\n return 'aspect-[4/3]'\n default:\n return ''\n }\n }\n\n const handleImageClick = (index: number) => {\n if (params()?.lightbox !== false) {\n setSelectedIndex(index)\n }\n }\n\n return (\n <ExpandableWrapper\n title={params()?.title || 'Gallery'}\n copyData={imagesToTextList(params())}\n copyLabel=\"Copy image URLs\"\n >\n <div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Title */}\n <Show when={params()?.title}>\n <div class=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params()!.title}</h3>\n </div>\n </Show>\n\n {/* Gallery Grid */}\n <div class={`grid ${columnsClass()} ${gapClass()} p-4 ${isExpanded() ? 'flex-1 min-h-0 overflow-auto' : ''}`}>\n <For each={params()?.images}>\n {(image, index) => (\n <button\n class={`relative overflow-hidden rounded-md focus:ring-2 focus:ring-blue-500 focus:outline-none group ${aspectClass()}`}\n onClick={() => handleImageClick(index())}\n type=\"button\"\n aria-label={image.alt || `View image ${index() + 1}`}\n >\n <img\n src={image.thumbnail || image.url}\n alt={image.alt || `Image ${index() + 1}`}\n srcset={image.srcset}\n sizes={image.sizes}\n class=\"w-full h-full object-cover group-hover:scale-105 transition-transform duration-200\"\n loading=\"lazy\"\n />\n\n {/* Hover overlay */}\n <div class=\"absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors duration-200\" />\n\n {/* Caption overlay */}\n <Show when={image.caption && params()?.showCaptions}>\n <div class=\"absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent text-white text-xs p-2 pt-4\">\n <span class=\"truncate block\">{image.caption}</span>\n </div>\n </Show>\n\n {/* Zoom icon on hover */}\n <Show when={params()?.lightbox !== false}>\n <div class=\"absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-200\">\n <div class=\"bg-white/90 dark:bg-gray-800/90 rounded-full p-2\">\n <svg\n class=\"w-5 h-5 text-gray-700 dark:text-gray-200\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7\"\n />\n </svg>\n </div>\n </div>\n </Show>\n </button>\n )}\n </For>\n </div>\n\n {/* Lightbox */}\n <LightboxOverlay\n images={params()?.images || []}\n selectedIndex={selectedIndex()}\n onClose={() => setSelectedIndex(null)}\n onNavigate={setSelectedIndex}\n />\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["imagesToTextList","p","images","map","img","caption","url","join","ImageGalleryRenderer","props","selectedIndex","setSelectedIndex","createSignal","isExpanded","useExpanded","params","component","columnsClass","columns","gapClass","gap","aspectClass","aspectRatio","handleImageClick","index","lightbox","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","children","_el$","_$getNextElement","_tmpl$2","_el$5","firstChild","_el$6","_co$","_$getNextMarker","nextSibling","_el$4","_el$7","_el$8","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","For","each","image","_el$9","_tmpl$5","_el$0","_el$1","_el$13","_el$14","_co$3","_el$15","_el$16","_co$4","$$click","_$memo","showCaptions","_el$10","_tmpl$3","_el$11","_tmpl$4","_$effect","_p$","_v$3","_v$4","alt","_v$5","thumbnail","_v$6","_v$7","srcset","_v$8","sizes","e","_$className","t","_$setAttribute","a","o","i","n","undefined","_$runHydrationEvents","LightboxOverlay","onClose","onNavigate","_v$","_v$2","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ImageGalleryRenderer.js","sources":["../../src/components/ImageGalleryRenderer.tsx"],"sourcesContent":["/**\n * ImageGalleryRenderer - Gallery view for multiple images\n * Sprint 5: Media Components\n */\n\nimport { Component, createSignal, For, Show } from 'solid-js'\nimport type { UIComponent, ImageGalleryParams } from '../types'\nimport { LightboxOverlay } from './LightboxOverlay'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\n\nexport interface ImageGalleryRendererProps {\n /**\n * UIComponent containing gallery params\n */\n component?: UIComponent\n\n /**\n * Direct gallery params (alternative to component)\n */\n params?: ImageGalleryParams\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible'\n}\n\n/** Build a newline-separated list of image URLs (with captions when present)\n * for the ExpandableWrapper copy button. v6.2.0. */\nfunction imagesToTextList(p: ImageGalleryParams | undefined): string {\n if (!p) return ''\n return (p.images ?? [])\n .map((img) => (img.caption ? `${img.url}\\t${img.caption}` : img.url))\n .join('\\n')\n}\n\nexport const ImageGalleryRenderer: Component<ImageGalleryRendererProps> = (props) => {\n const [selectedIndex, setSelectedIndex] = createSignal<number | null>(null)\n const isExpanded = useExpanded()\n\n const params = () => props.params || (props.component?.params as ImageGalleryParams)\n\n const columnsClass = () => {\n switch (params()?.columns) {\n case 2:\n return 'grid-cols-2'\n case 3:\n return 'grid-cols-3'\n case 4:\n return 'grid-cols-4'\n case 5:\n return 'grid-cols-5'\n default:\n return 'grid-cols-3'\n }\n }\n\n const gapClass = () => {\n switch (params()?.gap) {\n case 'none':\n return 'gap-0'\n case 'sm':\n return 'gap-1'\n case 'lg':\n return 'gap-4'\n default:\n return 'gap-2'\n }\n }\n\n const aspectClass = () => {\n switch (params()?.aspectRatio) {\n case '1:1':\n return 'aspect-square'\n case '16:9':\n return 'aspect-video'\n case '4:3':\n return 'aspect-[4/3]'\n default:\n return ''\n }\n }\n\n const handleImageClick = (index: number) => {\n if (params()?.lightbox !== false) {\n setSelectedIndex(index)\n }\n }\n\n return (\n <ExpandableWrapper\n title={params()?.title || 'Gallery'}\n copyData={imagesToTextList(params())}\n copyLabel=\"Copy image URLs\"\n toolbarVariant={props.toolbarVariant}\n >\n <div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Title */}\n <Show when={params()?.title}>\n <div class=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params()!.title}</h3>\n </div>\n </Show>\n\n {/* Gallery Grid */}\n <div class={`grid ${columnsClass()} ${gapClass()} p-4 ${isExpanded() ? 'flex-1 min-h-0 overflow-auto' : ''}`}>\n <For each={params()?.images}>\n {(image, index) => (\n <button\n class={`relative overflow-hidden rounded-md focus:ring-2 focus:ring-blue-500 focus:outline-none group ${aspectClass()}`}\n onClick={() => handleImageClick(index())}\n type=\"button\"\n aria-label={image.alt || `View image ${index() + 1}`}\n >\n <img\n src={image.thumbnail || image.url}\n alt={image.alt || `Image ${index() + 1}`}\n srcset={image.srcset}\n sizes={image.sizes}\n class=\"w-full h-full object-cover group-hover:scale-105 transition-transform duration-200\"\n loading=\"lazy\"\n />\n\n {/* Hover overlay */}\n <div class=\"absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors duration-200\" />\n\n {/* Caption overlay */}\n <Show when={image.caption && params()?.showCaptions}>\n <div class=\"absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent text-white text-xs p-2 pt-4\">\n <span class=\"truncate block\">{image.caption}</span>\n </div>\n </Show>\n\n {/* Zoom icon on hover */}\n <Show when={params()?.lightbox !== false}>\n <div class=\"absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-200\">\n <div class=\"bg-white/90 dark:bg-gray-800/90 rounded-full p-2\">\n <svg\n class=\"w-5 h-5 text-gray-700 dark:text-gray-200\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7\"\n />\n </svg>\n </div>\n </div>\n </Show>\n </button>\n )}\n </For>\n </div>\n\n {/* Lightbox */}\n <LightboxOverlay\n images={params()?.images || []}\n selectedIndex={selectedIndex()}\n onClose={() => setSelectedIndex(null)}\n onNavigate={setSelectedIndex}\n />\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["imagesToTextList","p","images","map","img","caption","url","join","ImageGalleryRenderer","props","selectedIndex","setSelectedIndex","createSignal","isExpanded","useExpanded","params","component","columnsClass","columns","gapClass","gap","aspectClass","aspectRatio","handleImageClick","index","lightbox","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$2","_el$5","firstChild","_el$6","_co$","_$getNextMarker","nextSibling","_el$4","_el$7","_el$8","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","For","each","image","_el$9","_tmpl$5","_el$0","_el$1","_el$13","_el$14","_co$3","_el$15","_el$16","_co$4","$$click","_$memo","showCaptions","_el$10","_tmpl$3","_el$11","_tmpl$4","_$effect","_p$","_v$3","_v$4","alt","_v$5","thumbnail","_v$6","_v$7","srcset","_v$8","sizes","e","_$className","t","_$setAttribute","a","o","i","n","undefined","_$runHydrationEvents","LightboxOverlay","onClose","onNavigate","_v$","_v$2","_$delegateEvents"],"mappings":"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"}
|
|
@@ -315,6 +315,9 @@ const MapRenderer = (props) => {
|
|
|
315
315
|
return mapToGeoJSON(params());
|
|
316
316
|
},
|
|
317
317
|
copyLabel: "Copy markers as GeoJSON",
|
|
318
|
+
get toolbarVariant() {
|
|
319
|
+
return props.toolbarVariant;
|
|
320
|
+
},
|
|
318
321
|
get children() {
|
|
319
322
|
var _el$ = web.getNextElement(_tmpl$3), _el$4 = _el$.firstChild, [_el$5, _co$] = web.getNextMarker(_el$4.nextSibling), _el$6 = _el$5.nextSibling, [_el$7, _co$2] = web.getNextMarker(_el$6.nextSibling);
|
|
320
323
|
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
@@ -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 { UIComponent, MapComponentParams, MapClusterOptions, MapGeoJSONStyle, MapPopupConfig, MapLayer, MapPMTilesConfig } from '../types'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\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// ─── 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(style: MapGeoJSONStyle | undefined): (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(val, style.choroplethScale, style.choroplethFallback || '#ccc')\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 */\nfunction buildPopupContent(feature: any, popup: MapPopupConfig | undefined): string | null {\n if (!popup || !feature?.properties) return null\n const props = feature.properties\n\n // Custom template\n if (popup.template) {\n return popup.template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\n const val = props[key]\n return val != null ? 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(`<span style=\"color:#666;font-size:11px\">${escapeHtml(key)}</span>: ${escapeHtml(formatted)}`)\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 * 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 const isExpanded = useExpanded()\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: p?.attribution || '© <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 const p = params()\n const allBoundsLayers: any[] = []\n\n // Clear existing layers (markers, cluster groups, GeoJSON)\n mapInstance.eachLayer((layer: any) => {\n if (layer instanceof L.Marker || layer instanceof L.GeoJSON\n || layer instanceof L.CircleMarker\n || layer._group || layer._featureGroup) {\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 = 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 if (marker.tooltip) m.bindTooltip(marker.tooltip)\n if (marker.popup) m.bindPopup(marker.popup)\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 if (marker.tooltip) m.bindTooltip(marker.tooltip)\n if (marker.popup) m.bindPopup(marker.popup)\n markers.push(m)\n })\n }\n } else {\n p?.markers?.forEach(marker => {\n const m = L.marker(marker.position).addTo(mapInstance)\n if (marker.tooltip) m.bindTooltip(marker.tooltip)\n if (marker.popup) m.bindPopup(marker.popup)\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, 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 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 = pmConfig.paintRules?.map(rule => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any)[\n rule.symbolizer === 'polygon' ? 'PolygonSymbolizer' :\n rule.symbolizer === 'line' ? '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 = 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 console.warn('[MCP-UI] Failed to load protomaps-leaflet for PMTiles:', e)\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 }\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 >\n <div 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 <Show when={error()}>\n <div class=\"p-4 text-red-500 bg-red-50 dark:bg-red-900/20 text-center\">\n {error()}\n </div>\n </Show>\n <Show when={!error()}>\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","props","template","replace","_","key","String","parts","titleField","push","escapeHtml","fields","Object","keys","slice","formatted","toLocaleString","join","str","addGeoJSONLayer","mapInst","leaflet","geojson","styleFn","layer","geoJSON","pointToLayer","latlng","s","circleMarker","radius","onEachFeature","featureLayer","html","bindPopup","maxWidth","addTo","mapToGeoJSON","p","features","marker","markers","pos","position","lat","Array","isArray","lng","type","geometry","coordinates","tooltip","JSON","stringify","MapRenderer","mapContainer","mapInstance","isLeafletLoaded","setIsLeafletLoaded","createSignal","error","setError","isExpanded","useExpanded","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","m","bindTooltip","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","fitBounds","group","featureGroup","bounds","getBounds","isValid","pad","getZoom","onCleanup","remove","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","children","_el$","_$getNextElement","_tmpl$3","_el$4","firstChild","_el$5","_co$","_$getNextMarker","nextSibling","_el$6","_el$7","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","_tmpl$2","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","_$style","t","_$className","undefined","className"],"mappings":"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"}
|
|
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 { UIComponent, MapComponentParams, MapClusterOptions, MapGeoJSONStyle, MapPopupConfig, MapLayer, MapPMTilesConfig } from '../types'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\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// ─── 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(style: MapGeoJSONStyle | undefined): (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(val, style.choroplethScale, style.choroplethFallback || '#ccc')\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 */\nfunction buildPopupContent(feature: any, popup: MapPopupConfig | undefined): string | null {\n if (!popup || !feature?.properties) return null\n const props = feature.properties\n\n // Custom template\n if (popup.template) {\n return popup.template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\n const val = props[key]\n return val != null ? 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(`<span style=\"color:#666;font-size:11px\">${escapeHtml(key)}</span>: ${escapeHtml(formatted)}`)\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 * 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 const isExpanded = useExpanded()\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: p?.attribution || '© <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 const p = params()\n const allBoundsLayers: any[] = []\n\n // Clear existing layers (markers, cluster groups, GeoJSON)\n mapInstance.eachLayer((layer: any) => {\n if (layer instanceof L.Marker || layer instanceof L.GeoJSON\n || layer instanceof L.CircleMarker\n || layer._group || layer._featureGroup) {\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 = 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 if (marker.tooltip) m.bindTooltip(marker.tooltip)\n if (marker.popup) m.bindPopup(marker.popup)\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 if (marker.tooltip) m.bindTooltip(marker.tooltip)\n if (marker.popup) m.bindPopup(marker.popup)\n markers.push(m)\n })\n }\n } else {\n p?.markers?.forEach(marker => {\n const m = L.marker(marker.position).addTo(mapInstance)\n if (marker.tooltip) m.bindTooltip(marker.tooltip)\n if (marker.popup) m.bindPopup(marker.popup)\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, 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 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 = pmConfig.paintRules?.map(rule => ({\n dataLayer: rule.dataLayer,\n symbolizer: new (protomaps as any)[\n rule.symbolizer === 'polygon' ? 'PolygonSymbolizer' :\n rule.symbolizer === 'line' ? '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 = 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 console.warn('[MCP-UI] Failed to load protomaps-leaflet for PMTiles:', e)\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 }\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 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 <Show when={error()}>\n <div class=\"p-4 text-red-500 bg-red-50 dark:bg-red-900/20 text-center\">\n {error()}\n </div>\n </Show>\n <Show when={!error()}>\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","props","template","replace","_","key","String","parts","titleField","push","escapeHtml","fields","Object","keys","slice","formatted","toLocaleString","join","str","addGeoJSONLayer","mapInst","leaflet","geojson","styleFn","layer","geoJSON","pointToLayer","latlng","s","circleMarker","radius","onEachFeature","featureLayer","html","bindPopup","maxWidth","addTo","mapToGeoJSON","p","features","marker","markers","pos","position","lat","Array","isArray","lng","type","geometry","coordinates","tooltip","JSON","stringify","MapRenderer","mapContainer","mapInstance","isLeafletLoaded","setIsLeafletLoaded","createSignal","error","setError","isExpanded","useExpanded","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","m","bindTooltip","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","fitBounds","group","featureGroup","bounds","getBounds","isValid","pad","getZoom","onCleanup","remove","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$3","_el$4","firstChild","_el$5","_co$","_$getNextMarker","nextSibling","_el$6","_el$7","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","_tmpl$2","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","_$style","t","_$className","undefined","className"],"mappings":";;;;;;AAYA,IAAIA,IAAS;AAEb,IAAIC,mBAAmB;AAyBvB,SAASC,mBACLC,OACAC,OACAC,UACM;AACN,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;AACnC,QAAIL,SAASC,MAAMI,CAAC,EAAE,CAAC,EAAG,QAAOJ,MAAMI,CAAC,EAAE,CAAC;AAAA,EAC/C;AACA,SAAOJ,MAAMA,MAAMG,SAAS,CAAC,EAAE,CAAC;AACpC;AAKA,SAASE,aAAaC,OAA+E;AACjG,MAAI,CAACA,OAAO;AACR,WAAO,OAAO;AAAA,MACVC,WAAW;AAAA,MACXC,aAAa;AAAA,MACbC,OAAO;AAAA,MACPC,QAAQ;AAAA,MACRC,SAAS;AAAA,IAAA;AAAA,EAEjB;AAEA,SAAO,CAACC,YAAiB;AACrB,QAAIL,YAAYD,MAAMC,aAAa;AAGnC,QAAID,MAAMO,mBAAmBP,MAAMQ,oBAAmBF,mCAASG,aAAY;AACvE,YAAMC,MAAMJ,QAAQG,WAAWT,MAAMO,eAAe;AACpDN,kBAAYT,mBAAmBkB,KAAKV,MAAMQ,iBAAiBR,MAAMW,sBAAsB,MAAM;AAAA,IACjG;AAEA,WAAO;AAAA,MACHV;AAAAA,MACAC,aAAaF,MAAME,eAAe;AAAA,MAClCC,OAAOH,MAAMY,eAAe;AAAA,MAC5BR,QAAQJ,MAAMa,gBAAgB;AAAA,MAC9BR,SAASL,MAAMc,iBAAiB;AAAA,IAAA;AAAA,EAExC;AACJ;AAKA,SAASC,kBAAkBT,SAAcU,OAAkD;AACvF,MAAI,CAACA,SAAS,EAACV,mCAASG,YAAY,QAAO;AAC3C,QAAMQ,QAAQX,QAAQG;AAGtB,MAAIO,MAAME,UAAU;AAChB,WAAOF,MAAME,SAASC,QAAQ,kBAAkB,CAACC,GAAGC,QAAQ;AACxD,YAAMX,MAAMO,MAAMI,GAAG;AACrB,aAAOX,OAAO,OAAOY,OAAOZ,GAAG,IAAI;AAAA,IACvC,CAAC;AAAA,EACL;AAGA,QAAMa,QAAkB,CAAA;AAExB,MAAIP,MAAMQ,cAAcP,MAAMD,MAAMQ,UAAU,KAAK,MAAM;AACrDD,UAAME,KAAK,WAAWC,WAAWJ,OAAOL,MAAMD,MAAMQ,UAAU,CAAC,CAAC,CAAC,WAAW;AAAA,EAChF;AAEA,QAAMG,SAASX,MAAMW,UAAUC,OAAOC,KAAKZ,KAAK,EAAEa,MAAM,GAAG,CAAC;AAC5D,aAAWT,OAAOM,QAAQ;AACtB,QAAIN,QAAQL,MAAMQ,WAAY;AAC9B,UAAMd,MAAMO,MAAMI,GAAG;AACrB,QAAIX,OAAO,KAAM;AACjB,UAAMqB,YAAY,OAAOrB,QAAQ,WAAWA,IAAIsB,eAAe,OAAO,IAAIV,OAAOZ,GAAG;AACpFa,UAAME,KAAK,2CAA2CC,WAAWL,GAAG,CAAC,YAAYK,WAAWK,SAAS,CAAC,EAAE;AAAA,EAC5G;AAEA,SAAOR,MAAMU,KAAK,OAAO;AAC7B;AAEA,SAASP,WAAWQ,KAAqB;AACrC,SAAOA,IACFf,QAAQ,MAAM,OAAO,EACrBA,QAAQ,MAAM,MAAM,EACpBA,QAAQ,MAAM,MAAM,EACpBA,QAAQ,MAAM,QAAQ;AAC/B;AAMA,SAASgB,gBACLC,SACAC,SACAC,SACAtC,OACAgB,OACG;AACH,QAAMuB,UAAUxC,aAAaC,KAAK;AAElC,QAAMwC,QAAQH,QAAQI,QAAQH,SAAS;AAAA,IACnCtC,OAAOuC;AAAAA,IACPG,cAAcA,CAACpC,SAAcqC,WAAgB;AAEzC,YAAMC,IAAIL,QAAQjC,OAAO;AACzB,aAAO+B,QAAQQ,aAAaF,QAAQ;AAAA,QAChCG,QAAQ;AAAA,QACR7C,WAAW2C,EAAE3C;AAAAA,QACbC,aAAa0C,EAAE1C;AAAAA,QACfC,OAAOyC,EAAEzC;AAAAA,QACTC,QAAQwC,EAAExC;AAAAA,QACVC,SAASuC,EAAEvC;AAAAA,MAAAA,CACd;AAAA,IACL;AAAA,IACA0C,eAAeA,CAACzC,SAAc0C,iBAAsB;AAChD,YAAMC,OAAOlC,kBAAkBT,SAASU,KAAK;AAC7C,UAAIiC,MAAM;AACND,qBAAaE,UAAUD,MAAM;AAAA,UAAEE,UAAU;AAAA,QAAA,CAAK;AAAA,MAClD;AAAA,IACJ;AAAA,EAAA,CACH;AAEDX,QAAMY,MAAMhB,OAAO;AACnB,SAAOI;AACX;AAUA,SAASa,aAAaC,GAA2C;AAC7D,MAAI,CAACA,EAAG,QAAO;AACf,QAAMC,WAAkB,CAAA;AACxB,aAAWC,UAAUF,EAAEG,WAAW,CAAA,GAAI;AAClC,UAAMC,MAAWF,OAAOG;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;AACxDR,aAAS9B,KAAK;AAAA,MACVuC,MAAM;AAAA,MACNC,UAAU;AAAA,QAAED,MAAM;AAAA,QAASE,aAAa,CAACH,KAAKH,GAAG;AAAA,MAAA;AAAA,MACjDnD,YAAY;AAAA,QACR,GAAI+C,OAAOW,UAAU;AAAA,UAAEA,SAASX,OAAOW;AAAAA,QAAAA,IAAY,CAAA;AAAA,QACnD,GAAIX,OAAOxC,QAAQ;AAAA,UAAEA,OAAOwC,OAAOxC;AAAAA,QAAAA,IAAU,CAAA;AAAA,MAAC;AAAA,IAClD,CACH;AAAA,EACL;AACA,SAAOoD,KAAKC,UAAU;AAAA,IAAEL,MAAM;AAAA,IAAqBT;AAAAA,EAAAA,GAAY,MAAM,CAAC;AAC1E;AAEO,MAAMe,cAA4CrD,CAAAA,UAAU;AAC/D,MAAIsD;AACJ,MAAIC,cAAmB;AACvB,QAAM,CAACC,iBAAiBC,kBAAkB,IAAIC,QAAAA,aAAa,KAAK;AAChE,QAAM,CAACC,OAAOC,QAAQ,IAAIF,QAAAA,aAA4B,IAAI;AAC1D,QAAMG,aAAaC,kBAAAA,YAAAA;AAEnB,QAAMC,SAASA,MAAAA;;AAAM/D,iBAAM+D,YAAW/D,WAAMgE,cAANhE,mBAAiB+D;AAAAA;AAMvDE,UAAAA,aAAa,MAAM;AACEJ,eAAAA;AACjB,QAAI,CAACN,YAAa;AAIlBW,eAAW,MAAA;;AAAMX,8DAAaY,mBAAbZ;AAAAA,OAAiC,GAAG;AAAA,EACzD,CAAC;AAGDU,UAAAA,aAAa,YAAY;;AACrB,QAAIG,aAAU;AAEd,QAAI,CAAC/F,GAAG;AACJ,UAAI;AACA,cAAMgG,UAAS,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,6BAAS,CAAA,EAAA,KAAA,OAAA,EAAA,UAAA;AACrChG,YAAIgG,QAAOC,WAAWD;AACtB,cAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,+EAA0B,CAAA;AACvCZ,2BAAmB,IAAI;AAAA,MAC3B,SAASc,GAAG;AACRC,gBAAQC,KAAK,0BAA0BF,CAAC;AACxCX,iBAAS,kCAAkC;AAC3C;AAAA,MACJ;AAAA,IACJ,OAAO;AACHH,yBAAmB,IAAI;AAAA,IAC3B;AAEA,QAAID,gBAAAA,KAAqBF,gBAAgB,CAACC,aAAa;AACnD,YAAMlB,IAAI0B,OAAAA;AACV,YAAMW,UAASrC,uBAAGqC,WAAU,CAAC,QAAQ,KAAK;AAC1C,YAAMC,QAAOtC,uBAAGsC,SAAQ;AAExBpB,oBAAclF,EAAEuG,IAAItB,cAAc;AAAA,QAC9BuB,cAAaxC,uBAAGwC,iBAAgB;AAAA,QAChCC,kBAAiBzC,uBAAGyC,qBAAoB;AAAA,QACxCC,oBAAoB;AAAA,MAAA,CACvB,EAAEC,QAAQN,QAAQC,IAAI;AAGvB,YAAMM,gBAAe5C,uBAAG6C,cAAa;AACrC7G,QAAE6G,UAAUD,cAAc;AAAA,QACtBE,cAAa9C,uBAAG8C,gBAAe;AAAA,MAAA,CAClC,EAAEhD,MAAMoB,WAAW;AAEpB,WAAIlB,uBAAG8C,iBAAgB,IAAI;AACvB9G,UAAE+G,QAAQD,YAAY;AAAA,UAAEE,QAAQ;AAAA,QAAA,CAAO,EAAElD,MAAMoB,WAAW;AAAA,MAC9D;AAGA,aAAQlF,EAAEiH,KAAKC,QAAQC,UAAkBC;AACzCpH,QAAEiH,KAAKC,QAAQG,aAAa;AAAA,QACxBC,eAAe;AAAA,QACfC,SAAS;AAAA,QACTC,WAAW;AAAA,MAAA,CACd;AAAA,IACL;AAGA,QAAItC,eAAelF,GAAG;AAClB,YAAMgE,IAAI0B,OAAAA;AACV,YAAM+B,kBAAyB,CAAA;AAG/BvC,kBAAYwC,UAAU,CAACxE,UAAe;AAClC,YAAIA,iBAAiBlD,EAAE2H,UAAUzE,iBAAiBlD,EAAE4H,WAC7C1E,iBAAiBlD,EAAE6H,gBACnB3E,MAAM4E,UAAU5E,MAAM6E,eAAe;AACxC7C,sBAAY8C,YAAY9E,KAAK;AAAA,QACjC;AAAA,MACJ,CAAC;AAGD,YAAMiB,UAAiB,CAAA;AACvB,YAAM8D,iBAAgBjE,uBAAGkE,gBAAclE,uBAAGG,YAAWH,EAAEG,QAAQ5D,SAAS;AAExE,UAAI0H,eAAe;AACf,YAAI;AACA,gBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,2CAAuB,CAAA,EAAA,KAAA,OAAA,EAAA,wBAAA;AACpC,cAAI,CAAChI,kBAAkB;AACnB,kBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,+HAA8C,CAAA;AAC3D,kBAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,uIAAsD,CAAA;AACnEA,+BAAmB;AAAA,UACvB;AACA,gBAAMkI,cAAiC,OAAOnE,EAAEkE,eAAe,WAAWlE,EAAEkE,aAAa,CAAA;AACzF,gBAAME,eAAgBpI,EAAUqI,mBAAmB;AAAA,YAC/CC,kBAAkBH,YAAYG,oBAAoB;AAAA,YAClDC,mBAAmBJ,YAAYI,qBAAqB;AAAA,YACpDC,qBAAqBL,YAAYK,uBAAuB;AAAA,YACxDC,yBAAyBN,YAAYM;AAAAA,YACrCC,SAASP,YAAYQ,wBAAwB;AAAA,UAAA,CAChD;AACD3E,uCAAGG,YAAHH,mBAAY4E,QAAQ1E,CAAAA,WAAU;AAC1B,kBAAM2E,IAAI7I,EAAEkE,OAAOA,OAAOG,QAAQ;AAClC,gBAAIH,OAAOW,QAASgE,GAAEC,YAAY5E,OAAOW,OAAO;AAChD,gBAAIX,OAAOxC,MAAOmH,GAAEjF,UAAUM,OAAOxC,KAAK;AAC1C0G,yBAAaW,SAASF,CAAC;AACvB1E,oBAAQhC,KAAK0G,CAAC;AAAA,UAClB;AACA3D,sBAAY6D,SAASX,YAAY;AAAA,QACrC,QAAQ;AACJpE,uCAAGG,YAAHH,mBAAY4E,QAAQ1E,CAAAA,WAAU;AAC1B,kBAAM2E,IAAI7I,EAAEkE,OAAOA,OAAOG,QAAQ,EAAEP,MAAMoB,WAAW;AACrD,gBAAIhB,OAAOW,QAASgE,GAAEC,YAAY5E,OAAOW,OAAO;AAChD,gBAAIX,OAAOxC,MAAOmH,GAAEjF,UAAUM,OAAOxC,KAAK;AAC1CyC,oBAAQhC,KAAK0G,CAAC;AAAA,UAClB;AAAA,QACJ;AAAA,MACJ,OAAO;AACH7E,qCAAGG,YAAHH,mBAAY4E,QAAQ1E,CAAAA,WAAU;AAC1B,gBAAM2E,IAAI7I,EAAEkE,OAAOA,OAAOG,QAAQ,EAAEP,MAAMoB,WAAW;AACrD,cAAIhB,OAAOW,QAASgE,GAAEC,YAAY5E,OAAOW,OAAO;AAChD,cAAIX,OAAOxC,MAAOmH,GAAEjF,UAAUM,OAAOxC,KAAK;AAC1CyC,kBAAQhC,KAAK0G,CAAC;AAAA,QAClB;AAAA,MACJ;AAEA,UAAI1E,QAAQ5D,SAAS,GAAG;AACpBkH,wBAAgBtF,KAAK,GAAGgC,OAAO;AAAA,MACnC;AAGA,UAAIH,uBAAGhB,SAAS;AACZ,cAAMgG,WAAWnG,gBAAgBqC,aAAalF,GAAGgE,EAAEhB,SAASgB,EAAEiF,cAAcjF,EAAEtC,KAAK;AACnF+F,wBAAgBtF,KAAK6G,QAAQ;AAAA,MACjC;AAGA,WAAIhF,uBAAGkF,WAAUlF,EAAEkF,OAAO3I,SAAS,GAAG;AAClC,cAAM4I,WAAgC,CAAA;AAEtC,mBAAWC,YAAYpF,EAAEkF,QAAQ;AAC7B,gBAAMF,WAAWnG,gBACbqC,aAAalF,GACboJ,SAASpG,SACToG,SAAS1I,UAASsD,uBAAGiF,eACrBG,SAAS1H,UAASsC,uBAAGtC,MACzB;AAEAyH,mBAASC,SAASC,IAAI,IAAIL;AAC1BvB,0BAAgBtF,KAAK6G,QAAQ;AAG7B,cAAII,SAASE,YAAY,OAAO;AAC5BpE,wBAAY8C,YAAYgB,QAAQ;AAAA,UACpC;AAAA,QACJ;AAGA,YAAI1G,OAAOC,KAAK4G,QAAQ,EAAE5I,SAAS,GAAG;AAClCP,YAAE+G,QAAQmC,OAAO,MAAMC,UAAU;AAAA,YAAEI,WAAW;AAAA,UAAA,CAAM,EAAEzF,MAAMoB,WAAW;AAAA,QAC3E;AAAA,MACJ;AAGA,UAAIlB,uBAAGwF,SAAS;AACZ,YAAI;AAEA,gBAAMC,YAAY,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA;AAAA;AAAA,YAA0B;AAAA,UAAmB,CAAA;AACrE,gBAAMC,WAAW1F,EAAEwF;AAEnB,gBAAMG,eAAaD,cAASC,eAATD,mBAAqBnD,IAAIqD,CAAAA,UAAS;AAAA,YACjDC,WAAWD,KAAKC;AAAAA,YAChBC,YAAY,IAAKL,UACbG,KAAKE,eAAe,YAAY,sBAChCF,KAAKE,eAAe,SAAS,mBAC7B,kBAAkB,EACpB;AAAA,cACEC,MAAMH,KAAK/I,SAAS;AAAA,cACpBmJ,QAAQJ,KAAK/I,SAAS;AAAA,cACtBoJ,OAAOL,KAAKK,SAAS;AAAA,cACrBlJ,SAAS6I,KAAK7I,WAAW;AAAA,YAAA,CAC5B;AAAA,UAAA,QACE,CAAA;AAEP,gBAAMmJ,eAAaR,cAASQ,eAATR,mBAAqBnD,IAAIqD,CAAAA,UAAS;AAAA,YACjDC,WAAWD,KAAKC;AAAAA,YAChBC,YAAY,IAAKL,UAAkBU,eAAe;AAAA,cAC9CC,aAAa,CAACR,KAAKS,SAAS;AAAA,cAC5BC,UAAUV,KAAKU,YAAY;AAAA,YAAA,CAC9B;AAAA,UAAA,QACE,CAAA;AAEP,gBAAMC,UAAWd,UAAkBe,aAAa;AAAA,YAC5CC,KAAKf,SAASe;AAAAA,YACd3D,aAAa4C,SAAS5C;AAAAA,YACtB6C;AAAAA,YACAO;AAAAA,YACAQ,SAAShB,SAASgB;AAAAA,YAClBC,SAASjB,SAASiB;AAAAA,UAAAA,CACrB;AAEDJ,kBAAQzG,MAAMoB,WAAW;AAAA,QAC7B,SAASgB,GAAG;AACRC,kBAAQC,KAAK,0DAA0DF,CAAC;AAAA,QAC5E;AAAA,MACJ;AAGA,WAAIlC,uBAAG4G,cAAanD,gBAAgBlH,SAAS,GAAG;AAC5C,cAAMsK,QAAQ7K,EAAE8K,aAAarD,eAAe;AAC5C,cAAMsD,SAASF,MAAMG,UAAAA;AACrB,YAAID,OAAOE,WAAW;AAClB/F,sBAAY0F,UAAUG,OAAOG,IAAI,GAAG,CAAC;AAAA,QACzC;AAAA,MACJ,WAAWlH,uBAAGqC,QAAQ;AAClBnB,oBAAYyB,QAAQ3C,EAAEqC,QAAQrC,EAAEsC,QAAQpB,YAAYiG,SAAS;AAAA,MACjE;AAAA,IACJ;AAAA,EACJ,CAAC;AAGDC,UAAAA,UAAU,MAAM;AACZ,QAAIlG,aAAa;AACbA,kBAAYmG,OAAAA;AACZnG,oBAAc;AAAA,IAClB;AAAA,EACJ,CAAC;AAED,SAAAoG,IAAAA,gBACKC,kBAAAA,mBAAiB;AAAA,IACdC,OAAO;AAAA,IAAK,IACZC,WAAQ;AAAA,aAAE1H,aAAa2B,QAAQ;AAAA,IAAC;AAAA,IAChCgG,WAAS;AAAA,IAAA,IACTC,iBAAc;AAAA,aAAEhK,MAAMgK;AAAAA,IAAc;AAAA,IAAA,IAAAC,WAAA;AAAA,UAAAC,OAAAC,IAAAA,eAAAC,OAAA,GAAAC,QAAAH,KAAAI,YAAA,CAAAC,OAAAC,IAAA,IAAAC,IAAAA,cAAAJ,MAAAK,WAAA,GAAAC,QAAAJ,MAAAG,aAAA,CAAAE,OAAAC,KAAA,IAAAJ,IAAAA,cAAAE,MAAAD,WAAA;AAAAI,iBAAAZ,MAAAP,IAAAA,gBAK/BoB,cAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAErH,MAAAA;AAAAA,QAAO;AAAA,QAAA,IAAAsG,WAAA;AAAA,cAAAgB,QAAAd,IAAAA,eAAAe,MAAA;AAAAJ,cAAAA,OAAAG,OAEVtH,KAAK;AAAA,iBAAAsH;AAAAA,QAAA;AAAA,MAAA,CAAA,GAAAV,OAAAC,IAAA;AAAAM,iBAAAZ,MAAAP,IAAAA,gBAGboB,cAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAE,CAACrH,MAAAA;AAAAA,QAAO;AAAA,QAAA,IAAAsG,WAAA;AAAA,cAAAkB,QAAAhB,IAAAA,eAAAiB,OAAA;AAAA,cAAAC,QAEP/H;AAAY,iBAAA+H,UAAA,aAAAC,IAAAA,IAAAD,OAAAF,KAAA,IAAZ7H,eAAY6H;AAAAI,cAAAA,OAAAC,CAAAA,QAAA;;AAAA,gBAAAC,MAEb5H,eACM;AAAA,cAAE6H,QAAQ;AAAA,cAAQpD,OAAO;AAAA,cAAQ,WAAW;AAAA,YAAA,IAC5C;AAAA,cAAEoD,UAAQ3H,kBAAAA,mBAAU2H,WAAU;AAAA,cAASpD,OAAO;AAAA,cAAQ,WAAW;AAAA,YAAA,GAAGqD,OAEvE,gBAAgB9H,WAAAA,IAAe,mBAAmB,EAAE;AAAE2H,gBAAAjH,IAAAqH,IAAAA,MAAAT,OAAAM,KAAAD,IAAAjH,CAAA;AAAAoH,qBAAAH,IAAAK,KAAAC,IAAAA,UAAAX,OAAAK,IAAAK,IAAAF,IAAA;AAAA,mBAAAH;AAAAA,UAAA,GAAA;AAAA,YAAAjH,GAAAwH;AAAAA,YAAAF,GAAAE;AAAAA,UAAAA,CAAA;AAAA,iBAAAZ;AAAAA,QAAA;AAAA,MAAA,CAAA,GAAAP,OAAAC,KAAA;AAAAU,UAAAA,OAAA,MAAA;;AAAAO,mBAAAA,UAAA5B,MAhB7D,uHAAqHnG,kBAAAA,mBAAUiI,cAAa,EAAE,IACtJnI,WAAAA,IAAe,iCAAiC,EAAE,EACpD;AAAA,OAAA;AAAA,aAAAqG;AAAAA,IAAA;AAAA,EAAA,CAAA;AAoBd;;"}
|
|
@@ -14,6 +14,11 @@ export interface MapRendererProps {
|
|
|
14
14
|
* Direct map params
|
|
15
15
|
*/
|
|
16
16
|
params?: MapComponentParams;
|
|
17
|
+
/**
|
|
18
|
+
* Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).
|
|
19
|
+
* @see ExpandableWrapperProps.toolbarVariant
|
|
20
|
+
*/
|
|
21
|
+
toolbarVariant?: 'hover' | 'always-visible';
|
|
17
22
|
}
|
|
18
23
|
export declare const MapRenderer: Component<MapRendererProps>;
|
|
19
24
|
//# 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,CAAA;AAEjF,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAkF,MAAM,UAAU,CAAA;AAQ/I,MAAM,WAAW,gBAAgB;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAA;
|
|
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,CAAA;AAEjF,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAkF,MAAM,UAAU,CAAA;AAQ/I,MAAM,WAAW,gBAAgB;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAE3B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAA;CAC9C;AAyKD,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,gBAAgB,CAqQnD,CAAA"}
|
|
@@ -313,6 +313,9 @@ const MapRenderer = (props) => {
|
|
|
313
313
|
return mapToGeoJSON(params());
|
|
314
314
|
},
|
|
315
315
|
copyLabel: "Copy markers as GeoJSON",
|
|
316
|
+
get toolbarVariant() {
|
|
317
|
+
return props.toolbarVariant;
|
|
318
|
+
},
|
|
316
319
|
get children() {
|
|
317
320
|
var _el$ = getNextElement(_tmpl$3), _el$4 = _el$.firstChild, [_el$5, _co$] = getNextMarker(_el$4.nextSibling), _el$6 = _el$5.nextSibling, [_el$7, _co$2] = getNextMarker(_el$6.nextSibling);
|
|
318
321
|
insert(_el$, createComponent(Show, {
|