@seed-ship/mcp-ui-solid 6.19.0 → 6.20.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 +532 -0
- package/README.md +798 -1
- package/dist/adapters/connector.cjs +15 -4
- package/dist/adapters/connector.cjs.map +1 -1
- package/dist/adapters/connector.d.ts +38 -0
- package/dist/adapters/connector.d.ts.map +1 -1
- package/dist/adapters/connector.js +15 -4
- package/dist/adapters/connector.js.map +1 -1
- package/dist/adapters/index.d.ts +4 -3
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/macro-run.cjs +25 -13
- package/dist/adapters/macro-run.cjs.map +1 -1
- package/dist/adapters/macro-run.d.ts +37 -2
- package/dist/adapters/macro-run.d.ts.map +1 -1
- package/dist/adapters/macro-run.js +25 -13
- package/dist/adapters/macro-run.js.map +1 -1
- package/dist/adapters.cjs +2 -0
- package/dist/adapters.cjs.map +1 -1
- package/dist/adapters.js +4 -2
- package/dist/components/ActionGroupRenderer.cjs +3 -1
- package/dist/components/ActionGroupRenderer.cjs.map +1 -1
- package/dist/components/ActionGroupRenderer.d.ts.map +1 -1
- package/dist/components/ActionGroupRenderer.js +3 -1
- package/dist/components/ActionGroupRenderer.js.map +1 -1
- package/dist/components/AgentCard.cjs +11 -8
- package/dist/components/AgentCard.cjs.map +1 -1
- package/dist/components/AgentCard.d.ts.map +1 -1
- package/dist/components/AgentCard.js +11 -8
- package/dist/components/AgentCard.js.map +1 -1
- package/dist/components/AgentHandoff.cjs +6 -1
- package/dist/components/AgentHandoff.cjs.map +1 -1
- package/dist/components/AgentHandoff.d.ts.map +1 -1
- package/dist/components/AgentHandoff.js +6 -1
- package/dist/components/AgentHandoff.js.map +1 -1
- package/dist/components/ArtifactRenderer.cjs +25 -6
- package/dist/components/ArtifactRenderer.cjs.map +1 -1
- package/dist/components/ArtifactRenderer.d.ts.map +1 -1
- package/dist/components/ArtifactRenderer.js +25 -6
- package/dist/components/ArtifactRenderer.js.map +1 -1
- package/dist/components/AutocompleteDropdown.cjs +30 -24
- package/dist/components/AutocompleteDropdown.cjs.map +1 -1
- package/dist/components/AutocompleteDropdown.d.ts.map +1 -1
- package/dist/components/AutocompleteDropdown.js +30 -24
- package/dist/components/AutocompleteDropdown.js.map +1 -1
- package/dist/components/AutocompleteFormField.cjs +3 -1
- package/dist/components/AutocompleteFormField.cjs.map +1 -1
- package/dist/components/AutocompleteFormField.d.ts.map +1 -1
- package/dist/components/AutocompleteFormField.js +4 -2
- package/dist/components/AutocompleteFormField.js.map +1 -1
- package/dist/components/BriefingDiff.cjs +45 -39
- package/dist/components/BriefingDiff.cjs.map +1 -1
- package/dist/components/BriefingDiff.d.ts.map +1 -1
- package/dist/components/BriefingDiff.js +45 -39
- package/dist/components/BriefingDiff.js.map +1 -1
- package/dist/components/CarouselRenderer.cjs +8 -2
- package/dist/components/CarouselRenderer.cjs.map +1 -1
- package/dist/components/CarouselRenderer.d.ts.map +1 -1
- package/dist/components/CarouselRenderer.js +8 -2
- package/dist/components/CarouselRenderer.js.map +1 -1
- package/dist/components/ChartJSRenderer.cjs +60 -36
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +61 -37
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/ChatPrompt.cjs +15 -9
- package/dist/components/ChatPrompt.cjs.map +1 -1
- package/dist/components/ChatPrompt.d.ts.map +1 -1
- package/dist/components/ChatPrompt.js +15 -9
- package/dist/components/ChatPrompt.js.map +1 -1
- package/dist/components/CodeBlockRenderer.cjs +34 -16
- package/dist/components/CodeBlockRenderer.cjs.map +1 -1
- package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
- package/dist/components/CodeBlockRenderer.js +34 -16
- package/dist/components/CodeBlockRenderer.js.map +1 -1
- package/dist/components/DataPreviewSection.cjs +91 -44
- package/dist/components/DataPreviewSection.cjs.map +1 -1
- package/dist/components/DataPreviewSection.d.ts.map +1 -1
- package/dist/components/DataPreviewSection.js +92 -45
- package/dist/components/DataPreviewSection.js.map +1 -1
- package/dist/components/DegradedFallback.cjs +20 -16
- package/dist/components/DegradedFallback.cjs.map +1 -1
- package/dist/components/DegradedFallback.d.ts.map +1 -1
- package/dist/components/DegradedFallback.js +20 -16
- package/dist/components/DegradedFallback.js.map +1 -1
- package/dist/components/FeedbackInline.cjs +19 -3
- package/dist/components/FeedbackInline.cjs.map +1 -1
- package/dist/components/FeedbackInline.js +19 -3
- package/dist/components/FeedbackInline.js.map +1 -1
- package/dist/components/FooterRenderer.cjs +21 -17
- package/dist/components/FooterRenderer.cjs.map +1 -1
- package/dist/components/FooterRenderer.d.ts.map +1 -1
- package/dist/components/FooterRenderer.js +21 -17
- package/dist/components/FooterRenderer.js.map +1 -1
- package/dist/components/FormFieldRenderer.cjs +116 -93
- package/dist/components/FormFieldRenderer.cjs.map +1 -1
- package/dist/components/FormFieldRenderer.d.ts.map +1 -1
- package/dist/components/FormFieldRenderer.js +116 -93
- package/dist/components/FormFieldRenderer.js.map +1 -1
- package/dist/components/FormRenderer.cjs +55 -31
- package/dist/components/FormRenderer.cjs.map +1 -1
- package/dist/components/FormRenderer.d.ts.map +1 -1
- package/dist/components/FormRenderer.js +55 -31
- package/dist/components/FormRenderer.js.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.cjs +20 -15
- package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.d.ts.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.js +20 -15
- package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
- package/dist/components/GraphRenderer.cjs +56 -33
- package/dist/components/GraphRenderer.cjs.map +1 -1
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +56 -33
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/components/ImageGalleryRenderer.cjs +13 -4
- package/dist/components/ImageGalleryRenderer.cjs.map +1 -1
- package/dist/components/ImageGalleryRenderer.d.ts.map +1 -1
- package/dist/components/ImageGalleryRenderer.js +13 -4
- package/dist/components/ImageGalleryRenderer.js.map +1 -1
- package/dist/components/LightboxOverlay.cjs +16 -8
- package/dist/components/LightboxOverlay.cjs.map +1 -1
- package/dist/components/LightboxOverlay.d.ts.map +1 -1
- package/dist/components/LightboxOverlay.js +17 -9
- package/dist/components/LightboxOverlay.js.map +1 -1
- package/dist/components/MapRenderer.cjs +59 -29
- package/dist/components/MapRenderer.cjs.map +1 -1
- package/dist/components/MapRenderer.d.ts +10 -2
- package/dist/components/MapRenderer.d.ts.map +1 -1
- package/dist/components/MapRenderer.js +60 -30
- package/dist/components/MapRenderer.js.map +1 -1
- package/dist/components/ModalRenderer.cjs +4 -1
- package/dist/components/ModalRenderer.cjs.map +1 -1
- package/dist/components/ModalRenderer.d.ts.map +1 -1
- package/dist/components/ModalRenderer.js +5 -2
- package/dist/components/ModalRenderer.js.map +1 -1
- package/dist/components/ScratchpadPanel.cjs +578 -535
- package/dist/components/ScratchpadPanel.cjs.map +1 -1
- package/dist/components/ScratchpadPanel.d.ts.map +1 -1
- package/dist/components/ScratchpadPanel.js +578 -535
- package/dist/components/ScratchpadPanel.js.map +1 -1
- package/dist/components/StreamingUIRenderer.cjs +92 -28
- package/dist/components/StreamingUIRenderer.cjs.map +1 -1
- package/dist/components/StreamingUIRenderer.d.ts.map +1 -1
- package/dist/components/StreamingUIRenderer.js +92 -28
- package/dist/components/StreamingUIRenderer.js.map +1 -1
- package/dist/components/UIResourceRenderer.cjs +456 -363
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts +21 -0
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +458 -365
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/VerifiedText.cjs +39 -20
- package/dist/components/VerifiedText.cjs.map +1 -1
- package/dist/components/VerifiedText.d.ts +2 -1
- package/dist/components/VerifiedText.d.ts.map +1 -1
- package/dist/components/VerifiedText.js +39 -20
- package/dist/components/VerifiedText.js.map +1 -1
- package/dist/components/VideoRenderer.cjs +10 -5
- package/dist/components/VideoRenderer.cjs.map +1 -1
- package/dist/components/VideoRenderer.d.ts.map +1 -1
- package/dist/components/VideoRenderer.js +10 -5
- package/dist/components/VideoRenderer.js.map +1 -1
- package/dist/components/chart-data-table.cjs +38 -17
- package/dist/components/chart-data-table.cjs.map +1 -1
- package/dist/components/chart-data-table.d.ts +30 -1
- package/dist/components/chart-data-table.d.ts.map +1 -1
- package/dist/components/chart-data-table.js +38 -17
- package/dist/components/chart-data-table.js.map +1 -1
- package/dist/context/MCPActionContext.cjs +3 -1
- package/dist/context/MCPActionContext.cjs.map +1 -1
- package/dist/context/MCPActionContext.d.ts.map +1 -1
- package/dist/context/MCPActionContext.js +3 -1
- package/dist/context/MCPActionContext.js.map +1 -1
- package/dist/context/MCPUIStringsContext.cjs +285 -2
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +600 -3
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +285 -2
- package/dist/context/MCPUIStringsContext.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useStreamingUI.cjs +28 -10
- package/dist/hooks/useStreamingUI.cjs.map +1 -1
- package/dist/hooks/useStreamingUI.d.ts +37 -0
- package/dist/hooks/useStreamingUI.d.ts.map +1 -1
- package/dist/hooks/useStreamingUI.js +28 -10
- package/dist/hooks/useStreamingUI.js.map +1 -1
- package/dist/hooks.cjs +1 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.js +2 -1
- package/dist/index.cjs +23 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -3
- package/dist/index.js.map +1 -1
- package/dist/services/validation.cjs +41 -16
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts +47 -2
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +41 -16
- package/dist/services/validation.js.map +1 -1
- package/dist/utils/degraded-projections.cjs +37 -12
- package/dist/utils/degraded-projections.cjs.map +1 -1
- package/dist/utils/degraded-projections.d.ts +39 -3
- package/dist/utils/degraded-projections.d.ts.map +1 -1
- package/dist/utils/degraded-projections.js +37 -12
- package/dist/utils/degraded-projections.js.map +1 -1
- package/dist/utils/format-string.cjs +10 -0
- package/dist/utils/format-string.cjs.map +1 -0
- package/dist/utils/format-string.d.ts +26 -0
- package/dist/utils/format-string.d.ts.map +1 -0
- package/dist/utils/format-string.js +10 -0
- package/dist/utils/format-string.js.map +1 -0
- package/dist/validation.cjs +3 -0
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.cts +2 -1
- package/dist/validation.d.ts +2 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +4 -1
- package/package.json +1 -1
- package/src/adapters/connector.ts +58 -4
- package/src/adapters/index.ts +12 -2
- package/src/adapters/macro-run.ts +71 -11
- package/src/components/ActionGroupRenderer.tsx +3 -1
- package/src/components/AgentCard.tsx +27 -9
- package/src/components/AgentHandoff.tsx +4 -1
- package/src/components/ArtifactRenderer.tsx +17 -5
- package/src/components/AutocompleteDropdown.tsx +8 -6
- package/src/components/AutocompleteFormField.tsx +5 -1
- package/src/components/BriefingDiff.tsx +11 -3
- package/src/components/CarouselRenderer.tsx +4 -2
- package/src/components/ChartJSRenderer.tsx +18 -9
- package/src/components/ChatPrompt.tsx +13 -8
- package/src/components/CodeBlockRenderer.tsx +12 -10
- package/src/components/DataPreviewSection.tsx +92 -26
- package/src/components/DegradedFallback.tsx +4 -2
- package/src/components/FeedbackInline.tsx +2 -2
- package/src/components/FooterRenderer.tsx +3 -1
- package/src/components/FormFieldRenderer.tsx +34 -19
- package/src/components/FormRenderer.tsx +38 -10
- package/src/components/GenerativeUIErrorBoundary.tsx +8 -3
- package/src/components/GraphRenderer.tsx +31 -16
- package/src/components/ImageGalleryRenderer.tsx +8 -4
- package/src/components/LightboxOverlay.tsx +6 -4
- package/src/components/MapRenderer.tsx +57 -20
- package/src/components/ModalRenderer.tsx +3 -1
- package/src/components/ScratchpadPanel.tsx +95 -44
- package/src/components/StreamingUIRenderer.tsx +41 -11
- package/src/components/UIResourceRenderer.tsx +145 -63
- package/src/components/VerifiedText.tsx +19 -9
- package/src/components/VideoRenderer.tsx +6 -4
- package/src/components/chart-data-table.ts +68 -14
- package/src/context/MCPActionContext.tsx +4 -1
- package/src/context/MCPUIStringsContext.tsx +1004 -1
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useStreamingUI.ts +64 -10
- package/src/index.ts +23 -0
- package/src/services/validation.ts +93 -16
- package/src/utils/degraded-projections.ts +75 -12
- package/src/utils/format-string.ts +33 -0
- package/src/validation.ts +5 -0
|
@@ -30,6 +30,7 @@ import { DegradedFallback } from './DegradedFallback';
|
|
|
30
30
|
import { graphToDegradedTable } from '../utils/degraded-projections';
|
|
31
31
|
import { escapeHtml } from '../utils/escape-html';
|
|
32
32
|
import { useTelemetry } from '../context/MCPUITelemetryContext';
|
|
33
|
+
import { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext';
|
|
33
34
|
|
|
34
35
|
// Module-scoped lazy import promise — first call triggers the dynamic
|
|
35
36
|
// import, subsequent calls reuse the resolved module.
|
|
@@ -220,6 +221,7 @@ export interface GraphRendererProps {
|
|
|
220
221
|
}
|
|
221
222
|
|
|
222
223
|
export const GraphRenderer: Component<GraphRendererProps> = (props) => {
|
|
224
|
+
const strings = useMCPUIStrings();
|
|
223
225
|
const params = () => props.component.params as GraphComponentParams;
|
|
224
226
|
const isExpanded = useExpanded();
|
|
225
227
|
const telemetry = useTelemetry();
|
|
@@ -296,7 +298,7 @@ export const GraphRenderer: Component<GraphRendererProps> = (props) => {
|
|
|
296
298
|
graphInstance = new (Graph as any)(config);
|
|
297
299
|
await graphInstance.render();
|
|
298
300
|
} catch (err) {
|
|
299
|
-
const message = err instanceof Error ? err.message :
|
|
301
|
+
const message = err instanceof Error ? err.message : strings.graphRenderError;
|
|
300
302
|
setError(message);
|
|
301
303
|
// Fallback ladder (P2.5): the native G6 render threw — emit telemetry
|
|
302
304
|
// so the failure is observable, then degrade to the edge/node table
|
|
@@ -344,13 +346,13 @@ export const GraphRenderer: Component<GraphRendererProps> = (props) => {
|
|
|
344
346
|
const url = (canvas as HTMLCanvasElement).toDataURL('image/png');
|
|
345
347
|
await downloadDataUrl(url, `${graphFilenameStem(params())}.png`);
|
|
346
348
|
} else {
|
|
347
|
-
setError(
|
|
349
|
+
setError(strings.graphPngUnsupported);
|
|
348
350
|
}
|
|
349
351
|
} else {
|
|
350
352
|
await downloadDataUrl(dataUrl, `${graphFilenameStem(params())}.png`);
|
|
351
353
|
}
|
|
352
354
|
} catch (err) {
|
|
353
|
-
setError(err instanceof Error ? err.message :
|
|
355
|
+
setError(err instanceof Error ? err.message : strings.graphPngExportFailed);
|
|
354
356
|
}
|
|
355
357
|
setExportMenuOpen(false);
|
|
356
358
|
};
|
|
@@ -371,7 +373,7 @@ export const GraphRenderer: Component<GraphRendererProps> = (props) => {
|
|
|
371
373
|
>
|
|
372
374
|
<div class="w-full p-4 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg">
|
|
373
375
|
<p class="text-sm font-medium text-yellow-900 dark:text-yellow-100">
|
|
374
|
-
|
|
376
|
+
{strings.graphUnavailable}
|
|
375
377
|
</p>
|
|
376
378
|
<p class="text-xs text-yellow-700 dark:text-yellow-300 mt-1">
|
|
377
379
|
Install <code>@antv/g6</code> peer dependency to render <code>type: "graph"</code>{' '}
|
|
@@ -382,9 +384,9 @@ export const GraphRenderer: Component<GraphRendererProps> = (props) => {
|
|
|
382
384
|
}
|
|
383
385
|
>
|
|
384
386
|
<ExpandableWrapper
|
|
385
|
-
title={params().title ??
|
|
387
|
+
title={params().title ?? strings.graphTitle}
|
|
386
388
|
copyData={toJSON(params())}
|
|
387
|
-
copyLabel=
|
|
389
|
+
copyLabel={strings.graphCopy}
|
|
388
390
|
toolbarVariant={props.toolbarVariant}
|
|
389
391
|
>
|
|
390
392
|
<div
|
|
@@ -399,12 +401,12 @@ export const GraphRenderer: Component<GraphRendererProps> = (props) => {
|
|
|
399
401
|
type="button"
|
|
400
402
|
onClick={() => setExportMenuOpen((v) => !v)}
|
|
401
403
|
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"
|
|
402
|
-
title=
|
|
403
|
-
aria-label=
|
|
404
|
+
title={strings.graphExport}
|
|
405
|
+
aria-label={strings.graphExport}
|
|
404
406
|
aria-haspopup="menu"
|
|
405
407
|
aria-expanded={exportMenuOpen()}
|
|
406
408
|
>
|
|
407
|
-
|
|
409
|
+
{strings.graphExportMenu}
|
|
408
410
|
</button>
|
|
409
411
|
<PortalDropdownMenu
|
|
410
412
|
open={exportMenuOpen()}
|
|
@@ -415,13 +417,21 @@ export const GraphRenderer: Component<GraphRendererProps> = (props) => {
|
|
|
415
417
|
>
|
|
416
418
|
<For
|
|
417
419
|
each={[
|
|
418
|
-
{ label: 'Download PNG', onClick: handleExportPNG, hint: 'visual snapshot' },
|
|
419
420
|
{
|
|
420
|
-
label:
|
|
421
|
+
label: strings.graphDownloadPng,
|
|
422
|
+
onClick: handleExportPNG,
|
|
423
|
+
hint: strings.graphDownloadPngHint,
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
label: strings.graphDownloadMermaid,
|
|
421
427
|
onClick: handleExportMermaid,
|
|
422
|
-
hint:
|
|
428
|
+
hint: strings.graphDownloadMermaidHint,
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
label: strings.graphDownloadJson,
|
|
432
|
+
onClick: handleExportJSON,
|
|
433
|
+
hint: strings.graphDownloadJsonHint,
|
|
423
434
|
},
|
|
424
|
-
{ label: 'Download JSON', onClick: handleExportJSON, hint: 'raw data' },
|
|
425
435
|
]}
|
|
426
436
|
>
|
|
427
437
|
{(item) => (
|
|
@@ -454,9 +464,14 @@ export const GraphRenderer: Component<GraphRendererProps> = (props) => {
|
|
|
454
464
|
rather than showing a bare message. Export menu stays usable. */}
|
|
455
465
|
<Show when={error()}>
|
|
456
466
|
<DegradedFallback
|
|
457
|
-
message={
|
|
458
|
-
caption=
|
|
459
|
-
{...graphToDegradedTable(params()
|
|
467
|
+
message={formatMCPUIString(strings.graphRenderFailed, { error: String(error()) })}
|
|
468
|
+
caption={strings.graphDegradedCaption}
|
|
469
|
+
{...graphToDegradedTable(params(), {
|
|
470
|
+
source: strings.degradedColSource,
|
|
471
|
+
target: strings.degradedColTarget,
|
|
472
|
+
label: strings.degradedColLabel,
|
|
473
|
+
node: strings.degradedColNode,
|
|
474
|
+
})}
|
|
460
475
|
/>
|
|
461
476
|
</Show>
|
|
462
477
|
</div>
|
|
@@ -8,6 +8,7 @@ import type { UIComponent, ImageGalleryParams } from '../types'
|
|
|
8
8
|
import { LightboxOverlay } from './LightboxOverlay'
|
|
9
9
|
import { ExpandableWrapper, useExpanded } from './ExpandableWrapper'
|
|
10
10
|
import { safeUrl } from '../utils/safe-url'
|
|
11
|
+
import { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'
|
|
11
12
|
|
|
12
13
|
export interface ImageGalleryRendererProps {
|
|
13
14
|
/**
|
|
@@ -37,6 +38,7 @@ function imagesToTextList(p: ImageGalleryParams | undefined): string {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export const ImageGalleryRenderer: Component<ImageGalleryRendererProps> = (props) => {
|
|
41
|
+
const strings = useMCPUIStrings()
|
|
40
42
|
const [selectedIndex, setSelectedIndex] = createSignal<number | null>(null)
|
|
41
43
|
const isExpanded = useExpanded()
|
|
42
44
|
|
|
@@ -91,9 +93,9 @@ export const ImageGalleryRenderer: Component<ImageGalleryRendererProps> = (props
|
|
|
91
93
|
|
|
92
94
|
return (
|
|
93
95
|
<ExpandableWrapper
|
|
94
|
-
title={params()?.title ||
|
|
96
|
+
title={params()?.title || strings.galleryTitle}
|
|
95
97
|
copyData={imagesToTextList(params())}
|
|
96
|
-
copyLabel=
|
|
98
|
+
copyLabel={strings.galleryCopy}
|
|
97
99
|
toolbarVariant={props.toolbarVariant}
|
|
98
100
|
>
|
|
99
101
|
<div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${
|
|
@@ -114,11 +116,13 @@ export const ImageGalleryRenderer: Component<ImageGalleryRendererProps> = (props
|
|
|
114
116
|
class={`relative overflow-hidden rounded-md focus:ring-2 focus:ring-blue-500 focus:outline-none group ${aspectClass()}`}
|
|
115
117
|
onClick={() => handleImageClick(index())}
|
|
116
118
|
type="button"
|
|
117
|
-
aria-label={
|
|
119
|
+
aria-label={
|
|
120
|
+
image.alt || formatMCPUIString(strings.galleryViewImage, { index: index() + 1 })
|
|
121
|
+
}
|
|
118
122
|
>
|
|
119
123
|
<img
|
|
120
124
|
src={safeUrl(image.thumbnail || image.url, { allowDataImage: true })}
|
|
121
|
-
alt={image.alt ||
|
|
125
|
+
alt={image.alt || formatMCPUIString(strings.galleryImageAlt, { index: index() + 1 })}
|
|
122
126
|
srcset={image.srcset}
|
|
123
127
|
sizes={image.sizes}
|
|
124
128
|
class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200"
|
|
@@ -7,6 +7,7 @@ import { Component, Show, createEffect, onCleanup } from 'solid-js'
|
|
|
7
7
|
import { Portal } from 'solid-js/web'
|
|
8
8
|
import type { GalleryImage } from '../types'
|
|
9
9
|
import { safeUrl } from '../utils/safe-url'
|
|
10
|
+
import { useMCPUIStrings } from '../context/MCPUIStringsContext'
|
|
10
11
|
|
|
11
12
|
export interface LightboxOverlayProps {
|
|
12
13
|
/**
|
|
@@ -31,6 +32,7 @@ export interface LightboxOverlayProps {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export const LightboxOverlay: Component<LightboxOverlayProps> = (props) => {
|
|
35
|
+
const strings = useMCPUIStrings()
|
|
34
36
|
const isOpen = () => props.selectedIndex !== null
|
|
35
37
|
const currentImage = () =>
|
|
36
38
|
props.selectedIndex !== null ? props.images[props.selectedIndex] : null
|
|
@@ -85,13 +87,13 @@ export const LightboxOverlay: Component<LightboxOverlayProps> = (props) => {
|
|
|
85
87
|
onClick={props.onClose}
|
|
86
88
|
role="dialog"
|
|
87
89
|
aria-modal="true"
|
|
88
|
-
aria-label=
|
|
90
|
+
aria-label={strings.lightboxLabel}
|
|
89
91
|
>
|
|
90
92
|
{/* Close button */}
|
|
91
93
|
<button
|
|
92
94
|
class="absolute top-4 right-4 text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors"
|
|
93
95
|
onClick={props.onClose}
|
|
94
|
-
aria-label=
|
|
96
|
+
aria-label={strings.lightboxClose}
|
|
95
97
|
>
|
|
96
98
|
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
97
99
|
<path
|
|
@@ -111,7 +113,7 @@ export const LightboxOverlay: Component<LightboxOverlayProps> = (props) => {
|
|
|
111
113
|
e.stopPropagation()
|
|
112
114
|
handlePrev()
|
|
113
115
|
}}
|
|
114
|
-
aria-label=
|
|
116
|
+
aria-label={strings.lightboxPrevious}
|
|
115
117
|
>
|
|
116
118
|
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
117
119
|
<path
|
|
@@ -132,7 +134,7 @@ export const LightboxOverlay: Component<LightboxOverlayProps> = (props) => {
|
|
|
132
134
|
e.stopPropagation()
|
|
133
135
|
handleNext()
|
|
134
136
|
}}
|
|
135
|
-
aria-label=
|
|
137
|
+
aria-label={strings.lightboxNext}
|
|
136
138
|
>
|
|
137
139
|
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
138
140
|
<path
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* v3.1.0: GeoJSON, choropleth, popups, multi-layer, PMTiles
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js';
|
|
7
|
+
import { Component, createEffect, onCleanup, createSignal, Show, untrack } from 'solid-js';
|
|
8
8
|
import { isServer } from 'solid-js/web';
|
|
9
9
|
import type {
|
|
10
10
|
UIComponent,
|
|
@@ -18,6 +18,11 @@ import { DegradedFallback } from './DegradedFallback';
|
|
|
18
18
|
import { mapToDegradedTable } from '../utils/degraded-projections';
|
|
19
19
|
import { escapeHtml } from '../utils/escape-html';
|
|
20
20
|
import { useTelemetry } from '../context/MCPUITelemetryContext';
|
|
21
|
+
import {
|
|
22
|
+
DEFAULT_MCPUI_STRINGS,
|
|
23
|
+
formatMCPUIString,
|
|
24
|
+
useMCPUIStrings,
|
|
25
|
+
} from '../context/MCPUIStringsContext';
|
|
21
26
|
|
|
22
27
|
// Lazy load leaflet (it doesn't support SSR well)
|
|
23
28
|
let L: any = null;
|
|
@@ -137,7 +142,9 @@ function buildStyleFn(
|
|
|
137
142
|
export function buildPopupContent(
|
|
138
143
|
feature: any,
|
|
139
144
|
popup: MapPopupConfig | undefined,
|
|
140
|
-
allowHtml = false
|
|
145
|
+
allowHtml = false,
|
|
146
|
+
/** BCP-47 tag for numeric values (`MCPUIStrings.locale`). Was `'fr-FR'` before 6.20.0. */
|
|
147
|
+
locale: string = DEFAULT_MCPUI_STRINGS.locale
|
|
141
148
|
): string | null {
|
|
142
149
|
if (!popup || !feature?.properties) return null;
|
|
143
150
|
const props = feature.properties;
|
|
@@ -162,7 +169,7 @@ export function buildPopupContent(
|
|
|
162
169
|
if (key === popup.titleField) continue;
|
|
163
170
|
const val = props[key];
|
|
164
171
|
if (val == null) continue;
|
|
165
|
-
const formatted = typeof val === 'number' ? val.toLocaleString(
|
|
172
|
+
const formatted = typeof val === 'number' ? val.toLocaleString(locale) : String(val);
|
|
166
173
|
parts.push(
|
|
167
174
|
`<span style="color:#666;font-size:11px">${escapeHtml(key)}</span>: ${escapeHtml(formatted)}`
|
|
168
175
|
);
|
|
@@ -204,7 +211,13 @@ export function addGeoJSONLayer(
|
|
|
204
211
|
geojson: unknown,
|
|
205
212
|
style?: MapGeoJSONStyle,
|
|
206
213
|
popup?: MapPopupConfig,
|
|
207
|
-
allowHtml = false
|
|
214
|
+
allowHtml = false,
|
|
215
|
+
/**
|
|
216
|
+
* BCP-47 tag forwarded to {@link buildPopupContent}, or a getter. With a
|
|
217
|
+
* getter, each popup is bound to a function Leaflet evaluates when the popup
|
|
218
|
+
* opens, so it follows locale changes without rebuilding the layer.
|
|
219
|
+
*/
|
|
220
|
+
locale: string | (() => string) = DEFAULT_MCPUI_STRINGS.locale
|
|
208
221
|
): any {
|
|
209
222
|
const styleFn = buildStyleFn(style);
|
|
210
223
|
|
|
@@ -223,9 +236,18 @@ export function addGeoJSONLayer(
|
|
|
223
236
|
});
|
|
224
237
|
},
|
|
225
238
|
onEachFeature: (feature: any, featureLayer: any) => {
|
|
226
|
-
|
|
239
|
+
// `untrack`: onEachFeature runs synchronously inside the map setup effect
|
|
240
|
+
// when Leaflet is already loaded. A tracked read there would subscribe
|
|
241
|
+
// that non-idempotent effect to the locale.
|
|
242
|
+
const currentLocale = () => (typeof locale === 'function' ? untrack(locale) : locale);
|
|
243
|
+
const html = buildPopupContent(feature, popup, allowHtml, currentLocale());
|
|
227
244
|
if (html) {
|
|
228
|
-
featureLayer.bindPopup(
|
|
245
|
+
featureLayer.bindPopup(
|
|
246
|
+
typeof locale === 'function'
|
|
247
|
+
? () => buildPopupContent(feature, popup, allowHtml, currentLocale()) ?? ''
|
|
248
|
+
: html,
|
|
249
|
+
{ maxWidth: 300 }
|
|
250
|
+
);
|
|
229
251
|
}
|
|
230
252
|
},
|
|
231
253
|
});
|
|
@@ -264,6 +286,7 @@ function mapToGeoJSON(p: MapComponentParams | undefined): string {
|
|
|
264
286
|
}
|
|
265
287
|
|
|
266
288
|
export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
289
|
+
const strings = useMCPUIStrings();
|
|
267
290
|
let mapContainer: HTMLDivElement | undefined;
|
|
268
291
|
let mapInstance: any = null;
|
|
269
292
|
const [isLeafletLoaded, setIsLeafletLoaded] = createSignal(false);
|
|
@@ -305,7 +328,7 @@ export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
|
305
328
|
setIsLeafletLoaded(true);
|
|
306
329
|
} catch (e) {
|
|
307
330
|
console.warn('Failed to load leaflet', e);
|
|
308
|
-
setError(
|
|
331
|
+
setError(strings.mapLibraryUnavailable);
|
|
309
332
|
return;
|
|
310
333
|
}
|
|
311
334
|
} else {
|
|
@@ -418,7 +441,11 @@ export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
|
418
441
|
p.geojson,
|
|
419
442
|
p.geojsonStyle,
|
|
420
443
|
p.popup,
|
|
421
|
-
allowHtml()
|
|
444
|
+
allowHtml(),
|
|
445
|
+
// A getter, not a value: popups read the current locale when they
|
|
446
|
+
// open. Tracking the locale here would re-run this effect, which is
|
|
447
|
+
// not idempotent (layer control, PMTiles layer, view reset).
|
|
448
|
+
() => strings.locale
|
|
422
449
|
);
|
|
423
450
|
allBoundsLayers.push(geoLayer);
|
|
424
451
|
}
|
|
@@ -434,7 +461,8 @@ export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
|
434
461
|
layerDef.geojson,
|
|
435
462
|
layerDef.style || p?.geojsonStyle,
|
|
436
463
|
layerDef.popup || p?.popup,
|
|
437
|
-
allowHtml()
|
|
464
|
+
allowHtml(),
|
|
465
|
+
() => strings.locale
|
|
438
466
|
);
|
|
439
467
|
|
|
440
468
|
overlays[layerDef.name] = geoLayer;
|
|
@@ -501,14 +529,16 @@ export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
|
501
529
|
// most common cause is the optional `protomaps-leaflet` peer not
|
|
502
530
|
// being installed.
|
|
503
531
|
const detail = e instanceof Error ? e.message : String(e);
|
|
504
|
-
|
|
532
|
+
// English diagnostic for logs and telemetry (P7); the visible
|
|
533
|
+
// banner reads the localized `mapPmtilesUnavailable` key.
|
|
534
|
+
const diagnostic =
|
|
505
535
|
'PMTiles layer unavailable — the optional "protomaps-leaflet" ' +
|
|
506
536
|
'peer dependency failed to load or render.';
|
|
507
|
-
console.warn('[MCP-UI] ' +
|
|
508
|
-
setPmtilesError(
|
|
537
|
+
console.warn('[MCP-UI] ' + diagnostic, e);
|
|
538
|
+
setPmtilesError(strings.mapPmtilesUnavailable);
|
|
509
539
|
telemetry?.dispatch({
|
|
510
540
|
type: 'render:error',
|
|
511
|
-
errorMessage: `${
|
|
541
|
+
errorMessage: `${diagnostic} (${detail})`,
|
|
512
542
|
id: props.component?.id ?? '',
|
|
513
543
|
componentType: 'map',
|
|
514
544
|
ts: Date.now(),
|
|
@@ -529,7 +559,7 @@ export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
|
529
559
|
} catch (err) {
|
|
530
560
|
// Fallback ladder (P2.5): a Leaflet drawing failure degrades to
|
|
531
561
|
// the coordinate table below instead of a blank/partial map.
|
|
532
|
-
const message = err instanceof Error ? err.message :
|
|
562
|
+
const message = err instanceof Error ? err.message : strings.mapRenderError;
|
|
533
563
|
setError(message);
|
|
534
564
|
telemetry?.dispatch({
|
|
535
565
|
type: 'render:error',
|
|
@@ -552,9 +582,9 @@ export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
|
552
582
|
|
|
553
583
|
return (
|
|
554
584
|
<ExpandableWrapper
|
|
555
|
-
title={
|
|
585
|
+
title={strings.mapTitle}
|
|
556
586
|
copyData={mapToGeoJSON(params())}
|
|
557
|
-
copyLabel=
|
|
587
|
+
copyLabel={strings.mapCopy}
|
|
558
588
|
toolbarVariant={props.toolbarVariant}
|
|
559
589
|
>
|
|
560
590
|
<div
|
|
@@ -567,9 +597,16 @@ export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
|
567
597
|
rather than a bare error string. */}
|
|
568
598
|
<div class="p-3">
|
|
569
599
|
<DegradedFallback
|
|
570
|
-
message={
|
|
571
|
-
caption=
|
|
572
|
-
{...mapToDegradedTable(params() ?? {}
|
|
600
|
+
message={formatMCPUIString(strings.mapRenderFailed, { error: String(error()) })}
|
|
601
|
+
caption={strings.mapDegradedCaption}
|
|
602
|
+
{...mapToDegradedTable(params() ?? {}, {
|
|
603
|
+
type: strings.degradedColType,
|
|
604
|
+
lat: strings.degradedColLat,
|
|
605
|
+
lng: strings.degradedColLng,
|
|
606
|
+
info: strings.degradedColInfo,
|
|
607
|
+
marker: strings.degradedMarker,
|
|
608
|
+
feature: strings.degradedFeature,
|
|
609
|
+
})}
|
|
573
610
|
/>
|
|
574
611
|
</div>
|
|
575
612
|
</Show>
|
|
@@ -581,7 +618,7 @@ export const MapRenderer: Component<MapRendererProps> = (props) => {
|
|
|
581
618
|
role="alert"
|
|
582
619
|
class="m-2 rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200"
|
|
583
620
|
>
|
|
584
|
-
{pmtilesError()}
|
|
621
|
+
{pmtilesError()} {strings.mapBaseMapStillShown}
|
|
585
622
|
</div>
|
|
586
623
|
</Show>
|
|
587
624
|
<div
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { Component, Show, createSignal, createEffect, onCleanup, JSX } from 'solid-js'
|
|
7
7
|
import { Portal } from 'solid-js/web'
|
|
8
8
|
import type { UIComponent, ModalComponentParams } from '../types'
|
|
9
|
+
import { useMCPUIStrings } from '../context/MCPUIStringsContext'
|
|
9
10
|
|
|
10
11
|
export interface ModalRendererProps {
|
|
11
12
|
/**
|
|
@@ -72,6 +73,7 @@ export interface ModalRendererProps {
|
|
|
72
73
|
* ```
|
|
73
74
|
*/
|
|
74
75
|
export const ModalRenderer: Component<ModalRendererProps> = (props) => {
|
|
76
|
+
const strings = useMCPUIStrings()
|
|
75
77
|
const [isVisible, setIsVisible] = createSignal(false)
|
|
76
78
|
|
|
77
79
|
const params = () => props.params || (props.component?.params as ModalComponentParams) || {}
|
|
@@ -185,7 +187,7 @@ export const ModalRenderer: Component<ModalRendererProps> = (props) => {
|
|
|
185
187
|
<button
|
|
186
188
|
onClick={handleClose}
|
|
187
189
|
class="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
|
|
188
|
-
aria-label=
|
|
190
|
+
aria-label={strings.modalClose}
|
|
189
191
|
>
|
|
190
192
|
<svg
|
|
191
193
|
class="w-5 h-5"
|