@seed-ship/mcp-ui-solid 6.19.1 → 6.21.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 +663 -0
- package/README.md +911 -4
- 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/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/IframeFallbackLink.cjs +37 -0
- package/dist/components/IframeFallbackLink.cjs.map +1 -0
- package/dist/components/IframeFallbackLink.d.ts +23 -0
- package/dist/components/IframeFallbackLink.d.ts.map +1 -0
- package/dist/components/IframeFallbackLink.js +37 -0
- package/dist/components/IframeFallbackLink.js.map +1 -0
- 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 +481 -365
- 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 +484 -368
- 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 +51 -20
- package/dist/components/VideoRenderer.cjs.map +1 -1
- package/dist/components/VideoRenderer.d.ts.map +1 -1
- package/dist/components/VideoRenderer.js +51 -20
- 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/MCPUIConfigContext.cjs +29 -0
- package/dist/context/MCPUIConfigContext.cjs.map +1 -0
- package/dist/context/MCPUIConfigContext.d.ts +124 -0
- package/dist/context/MCPUIConfigContext.d.ts.map +1 -0
- package/dist/context/MCPUIConfigContext.js +29 -0
- package/dist/context/MCPUIConfigContext.js.map +1 -0
- package/dist/context/MCPUIStringsContext.cjs +287 -2
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +607 -3
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +287 -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 +29 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -3
- package/dist/index.js.map +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/validation.cjs +52 -26
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts +67 -2
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +52 -26
- 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/utils/iframe-coep.cjs +30 -0
- package/dist/utils/iframe-coep.cjs.map +1 -0
- package/dist/utils/iframe-coep.d.ts +46 -0
- package/dist/utils/iframe-coep.d.ts.map +1 -0
- package/dist/utils/iframe-coep.js +30 -0
- package/dist/utils/iframe-coep.js.map +1 -0
- package/dist/validation.cjs +5 -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 +6 -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/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/IframeFallbackLink.tsx +57 -0
- 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 +176 -67
- package/src/components/VerifiedText.tsx +19 -9
- package/src/components/VideoRenderer.tsx +26 -4
- package/src/components/chart-data-table.ts +68 -14
- package/src/context/MCPActionContext.tsx +4 -1
- package/src/context/MCPUIConfigContext.tsx +151 -0
- package/src/context/MCPUIStringsContext.tsx +1014 -1
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useStreamingUI.ts +64 -10
- package/src/index.ts +38 -0
- package/src/services/index.ts +1 -0
- package/src/services/validation.ts +131 -32
- package/src/solid-jsx-attrs.d.ts +24 -0
- package/src/utils/degraded-projections.ts +75 -12
- package/src/utils/format-string.ts +33 -0
- package/src/utils/iframe-coep.ts +74 -0
- package/src/validation.ts +9 -0
|
@@ -10,6 +10,42 @@
|
|
|
10
10
|
* isn't left with a blank space, not faithful reproductions of the chart/
|
|
11
11
|
* map/graph.
|
|
12
12
|
*/
|
|
13
|
+
/**
|
|
14
|
+
* Column headers and series names of the degraded tables.
|
|
15
|
+
*
|
|
16
|
+
* The projections are pure helpers with no access to `MCPUIStrings`, so the
|
|
17
|
+
* wording is injected: each function takes an optional trailing `labels`
|
|
18
|
+
* partial, and the renderers feed it from `useMCPUIStrings()`. Left out, the
|
|
19
|
+
* English defaults below apply — the pre-v6.20.0 behaviour.
|
|
20
|
+
*
|
|
21
|
+
* @since v6.20.0
|
|
22
|
+
*/
|
|
23
|
+
export interface DegradedProjectionLabels {
|
|
24
|
+
/** Graph edge table — source column. */
|
|
25
|
+
source: string;
|
|
26
|
+
/** Graph edge table — target column. */
|
|
27
|
+
target: string;
|
|
28
|
+
/** Graph edge / node table — label column. */
|
|
29
|
+
label: string;
|
|
30
|
+
/** Graph node table — node id column. */
|
|
31
|
+
node: string;
|
|
32
|
+
/** Map table — feature type column. */
|
|
33
|
+
type: string;
|
|
34
|
+
/** Map table — latitude column. */
|
|
35
|
+
lat: string;
|
|
36
|
+
/** Map table — longitude column. */
|
|
37
|
+
lng: string;
|
|
38
|
+
/** Map table — property summary column. */
|
|
39
|
+
info: string;
|
|
40
|
+
/** Map table — `Type` cell of a marker row (v6.20.0, 6th pass). */
|
|
41
|
+
marker: string;
|
|
42
|
+
/** Map table — `Type` cell of a GeoJSON feature without a geometry type (v6.20.0). */
|
|
43
|
+
feature: string;
|
|
44
|
+
/** Chart table — fallback dataset name. Template — `{n}`. */
|
|
45
|
+
series: string;
|
|
46
|
+
}
|
|
47
|
+
/** English defaults for {@link DegradedProjectionLabels}. */
|
|
48
|
+
export declare const DEGRADED_PROJECTION_LABELS: DegradedProjectionLabels;
|
|
13
49
|
export interface DegradedTable {
|
|
14
50
|
columns: string[];
|
|
15
51
|
rows: Array<Array<string | number>>;
|
|
@@ -30,7 +66,7 @@ export declare function graphToDegradedTable(params: {
|
|
|
30
66
|
label?: string;
|
|
31
67
|
weight?: number;
|
|
32
68
|
}>;
|
|
33
|
-
}): DegradedTable;
|
|
69
|
+
}, labels?: Partial<DegradedProjectionLabels>): DegradedTable;
|
|
34
70
|
/**
|
|
35
71
|
* Map → a coordinate table. Markers become Lat/Lng/Label rows; GeoJSON
|
|
36
72
|
* features become Type / Lat / Lng (+ a compact properties summary). So a
|
|
@@ -46,7 +82,7 @@ export declare function mapToDegradedTable(params: {
|
|
|
46
82
|
popup?: string;
|
|
47
83
|
}>;
|
|
48
84
|
geojson?: unknown;
|
|
49
|
-
}): DegradedTable;
|
|
85
|
+
}, labels?: Partial<DegradedProjectionLabels>): DegradedTable;
|
|
50
86
|
/**
|
|
51
87
|
* Chart → a series table: one row per label, one column per dataset. So a
|
|
52
88
|
* chart that can't draw still shows its numbers. Point/object data (scatter,
|
|
@@ -60,5 +96,5 @@ export declare function chartToDegradedTable(params: {
|
|
|
60
96
|
data?: unknown[];
|
|
61
97
|
}>;
|
|
62
98
|
};
|
|
63
|
-
}): DegradedTable;
|
|
99
|
+
}, labels?: Partial<DegradedProjectionLabels>): DegradedTable;
|
|
64
100
|
//# sourceMappingURL=degraded-projections.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"degraded-projections.d.ts","sourceRoot":"","sources":["../../src/utils/degraded-projections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"degraded-projections.d.ts","sourceRoot":"","sources":["../../src/utils/degraded-projections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB;IACvC,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,6DAA6D;AAC7D,eAAO,MAAM,0BAA0B,EAAE,wBAYxC,CAAC;AAOF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;CACrC;AAmBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpF,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,aAAa,CAmB5D;AAoBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,aAAa,CA+B5D;AAID;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,KAAK,CAAC;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAA;SAAE,CAAC,CAAC;KACxD,CAAC;CACH,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,aAAa,CAe5D"}
|
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
import { formatMCPUIString } from "./format-string.js";
|
|
2
|
+
const DEGRADED_PROJECTION_LABELS = {
|
|
3
|
+
source: "Source",
|
|
4
|
+
target: "Target",
|
|
5
|
+
label: "Label",
|
|
6
|
+
node: "Node",
|
|
7
|
+
type: "Type",
|
|
8
|
+
lat: "Lat",
|
|
9
|
+
lng: "Lng",
|
|
10
|
+
info: "Info",
|
|
11
|
+
marker: "marker",
|
|
12
|
+
feature: "feature",
|
|
13
|
+
series: "Series {n}"
|
|
14
|
+
};
|
|
15
|
+
const withLabels = (labels) => ({
|
|
16
|
+
...DEGRADED_PROJECTION_LABELS,
|
|
17
|
+
...labels
|
|
18
|
+
});
|
|
1
19
|
const MAX_PROJECTED_ROWS = 200;
|
|
2
20
|
function cell(value) {
|
|
3
21
|
if (value == null) return "";
|
|
@@ -10,11 +28,12 @@ function cell(value) {
|
|
|
10
28
|
}
|
|
11
29
|
return String(value);
|
|
12
30
|
}
|
|
13
|
-
function graphToDegradedTable(params) {
|
|
31
|
+
function graphToDegradedTable(params, labels) {
|
|
32
|
+
const l = withLabels(labels);
|
|
14
33
|
const edges = params.edges ?? [];
|
|
15
34
|
if (edges.length > 0) {
|
|
16
35
|
return {
|
|
17
|
-
columns: [
|
|
36
|
+
columns: [l.source, l.target, l.label],
|
|
18
37
|
rows: edges.slice(0, MAX_PROJECTED_ROWS).map((e) => {
|
|
19
38
|
const label = [e.weight != null ? String(e.weight) : "", e.label ?? ""].filter(Boolean).join(" · ");
|
|
20
39
|
return [cell(e.source), cell(e.target), label];
|
|
@@ -23,7 +42,7 @@ function graphToDegradedTable(params) {
|
|
|
23
42
|
}
|
|
24
43
|
const nodes = params.nodes ?? [];
|
|
25
44
|
return {
|
|
26
|
-
columns: [
|
|
45
|
+
columns: [l.node, l.label],
|
|
27
46
|
rows: nodes.slice(0, MAX_PROJECTED_ROWS).map((n) => [cell(n.id), cell(n.label ?? n.id)])
|
|
28
47
|
};
|
|
29
48
|
}
|
|
@@ -35,13 +54,14 @@ function firstLngLat(coords) {
|
|
|
35
54
|
}
|
|
36
55
|
return null;
|
|
37
56
|
}
|
|
38
|
-
function mapToDegradedTable(params) {
|
|
57
|
+
function mapToDegradedTable(params, labels) {
|
|
39
58
|
var _a, _b, _c, _d;
|
|
59
|
+
const l = withLabels(labels);
|
|
40
60
|
const rows = [];
|
|
41
61
|
for (const m of params.markers ?? []) {
|
|
42
62
|
const lat = Array.isArray(m.position) ? m.position[0] : (_a = m.position) == null ? void 0 : _a.lat;
|
|
43
63
|
const lng = Array.isArray(m.position) ? m.position[1] : (_b = m.position) == null ? void 0 : _b.lng;
|
|
44
|
-
rows.push([
|
|
64
|
+
rows.push([l.marker, cell(lat), cell(lng), cell(m.tooltip ?? m.popup ?? "")]);
|
|
45
65
|
}
|
|
46
66
|
const fc = params.geojson;
|
|
47
67
|
const features = Array.isArray(fc == null ? void 0 : fc.features) ? fc.features : [];
|
|
@@ -50,29 +70,33 @@ function mapToDegradedTable(params) {
|
|
|
50
70
|
const props = f.properties ?? {};
|
|
51
71
|
const propSummary = Object.keys(props).slice(0, 3).map((k) => `${k}=${cell(props[k])}`).join(", ");
|
|
52
72
|
rows.push([
|
|
53
|
-
cell(((_d = f.geometry) == null ? void 0 : _d.type) ??
|
|
73
|
+
cell(((_d = f.geometry) == null ? void 0 : _d.type) ?? l.feature),
|
|
54
74
|
ll ? cell(ll[1]) : "",
|
|
55
75
|
ll ? cell(ll[0]) : "",
|
|
56
76
|
propSummary
|
|
57
77
|
]);
|
|
58
78
|
}
|
|
59
79
|
return {
|
|
60
|
-
columns: [
|
|
80
|
+
columns: [l.type, l.lat, l.lng, l.info],
|
|
61
81
|
rows: rows.slice(0, MAX_PROJECTED_ROWS)
|
|
62
82
|
};
|
|
63
83
|
}
|
|
64
|
-
function chartToDegradedTable(params) {
|
|
84
|
+
function chartToDegradedTable(params, labels) {
|
|
65
85
|
var _a, _b;
|
|
86
|
+
const l = withLabels(labels);
|
|
66
87
|
const datasets = ((_a = params.data) == null ? void 0 : _a.datasets) ?? [];
|
|
67
|
-
const
|
|
68
|
-
const rowCount = Math.max(
|
|
88
|
+
const dataLabels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
|
|
89
|
+
const rowCount = Math.max(dataLabels.length, ...datasets.map((d) => {
|
|
69
90
|
var _a2;
|
|
70
91
|
return ((_a2 = d.data) == null ? void 0 : _a2.length) ?? 0;
|
|
71
92
|
}), 0);
|
|
72
|
-
const columns = [
|
|
93
|
+
const columns = [
|
|
94
|
+
"",
|
|
95
|
+
...datasets.map((d, i) => d.label ?? formatMCPUIString(l.series, { n: i + 1 }))
|
|
96
|
+
];
|
|
73
97
|
const rows = [];
|
|
74
98
|
for (let r = 0; r < Math.min(rowCount, MAX_PROJECTED_ROWS); r++) {
|
|
75
|
-
rows.push([cell(
|
|
99
|
+
rows.push([cell(dataLabels[r] ?? r + 1), ...datasets.map((d) => {
|
|
76
100
|
var _a2;
|
|
77
101
|
return cell((_a2 = d.data) == null ? void 0 : _a2[r]);
|
|
78
102
|
})]);
|
|
@@ -80,6 +104,7 @@ function chartToDegradedTable(params) {
|
|
|
80
104
|
return { columns, rows };
|
|
81
105
|
}
|
|
82
106
|
export {
|
|
107
|
+
DEGRADED_PROJECTION_LABELS,
|
|
83
108
|
chartToDegradedTable,
|
|
84
109
|
graphToDegradedTable,
|
|
85
110
|
mapToDegradedTable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"degraded-projections.js","sources":["../../src/utils/degraded-projections.ts"],"sourcesContent":["/**\n * Degraded-fallback projections (audit 2026-05-30, P2.5).\n *\n * Pure functions that turn a heavy renderer's params into a flat\n * `{ columns, rows }` table for `<DegradedFallback>` — the middle rung of\n * the fallback ladder shown when the native render (G6 / Leaflet / Chart.js)\n * is unavailable or throws. No peer deps, no side effects, fully testable.\n *\n * These are best-effort views: they surface the underlying data so the user\n * isn't left with a blank space, not faithful reproductions of the chart/\n * map/graph.\n */\n\nexport interface DegradedTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\nconst MAX_PROJECTED_ROWS = 200;\n\n/** Compact a value to a single table cell string. */\nfunction cell(value: unknown): string {\n if (value == null) return '';\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n\n// ─── Graph ───────────────────────────────────────────────────────────────\n\n/**\n * Graph → edge table when edges exist (Source / Target / Label), else a\n * node list (Node / Label). The graph renderer can therefore degrade to a\n * readable relationship listing instead of a blank canvas.\n */\nexport function graphToDegradedTable(params: {\n nodes?: Array<{ id: string; label?: string }>;\n edges?: Array<{ source: string; target: string; label?: string; weight?: number }>;\n}): DegradedTable {\n const edges = params.edges ?? [];\n if (edges.length > 0) {\n return {\n columns: ['Source', 'Target', 'Label'],\n rows: edges.slice(0, MAX_PROJECTED_ROWS).map((e) => {\n const label = [e.weight != null ? String(e.weight) : '', e.label ?? '']\n .filter(Boolean)\n .join(' · ');\n return [cell(e.source), cell(e.target), label];\n }),\n };\n }\n const nodes = params.nodes ?? [];\n return {\n columns: ['Node', 'Label'],\n rows: nodes.slice(0, MAX_PROJECTED_ROWS).map((n) => [cell(n.id), cell(n.label ?? n.id)]),\n };\n}\n\n// ─── Map ───────────────────────────────────────────────────────────────────\n\ninterface GeoJSONLikeFeature {\n geometry?: { type?: string; coordinates?: unknown } | null;\n properties?: Record<string, unknown> | null;\n}\n\n/** Pull a representative `[lng, lat]` pair out of a geometry's coordinates. */\nfunction firstLngLat(coords: unknown): [number, number] | null {\n let c: unknown = coords;\n // Descend nested arrays until we reach a [number, number, ...] position.\n while (Array.isArray(c) && Array.isArray(c[0])) c = c[0];\n if (Array.isArray(c) && typeof c[0] === 'number' && typeof c[1] === 'number') {\n return [c[0], c[1]];\n }\n return null;\n}\n\n/**\n * Map → a coordinate table. Markers become Lat/Lng/Label rows; GeoJSON\n * features become Type / Lat / Lng (+ a compact properties summary). So a\n * map that can't paint still lists where its points are.\n */\nexport function mapToDegradedTable(params: {\n markers?: Array<{\n position: [number, number] | { lat: number; lng: number };\n tooltip?: string;\n popup?: string;\n }>;\n geojson?: unknown;\n}): DegradedTable {\n const rows: Array<Array<string | number>> = [];\n\n for (const m of params.markers ?? []) {\n const lat = Array.isArray(m.position) ? m.position[0] : m.position?.lat;\n const lng = Array.isArray(m.position) ? m.position[1] : m.position?.lng;\n rows.push(['marker', cell(lat), cell(lng), cell(m.tooltip ?? m.popup ?? '')]);\n }\n\n const fc = params.geojson as { features?: GeoJSONLikeFeature[] } | undefined;\n const features = Array.isArray(fc?.features) ? fc!.features : [];\n for (const f of features) {\n const ll = firstLngLat(f.geometry?.coordinates);\n const props = f.properties ?? {};\n const propSummary = Object.keys(props)\n .slice(0, 3)\n .map((k) => `${k}=${cell(props[k])}`)\n .join(', ');\n rows.push([\n cell(f.geometry?.type ?? 'feature'),\n ll ? cell(ll[1]) : '',\n ll ? cell(ll[0]) : '',\n propSummary,\n ]);\n }\n\n return {\n columns: ['Type', 'Lat', 'Lng', 'Info'],\n rows: rows.slice(0, MAX_PROJECTED_ROWS),\n };\n}\n\n// ─── Chart ───────────────────────────────────────────────────────────────\n\n/**\n * Chart → a series table: one row per label, one column per dataset. So a\n * chart that can't draw still shows its numbers. Point/object data (scatter,\n * bubble, time series) is stringified per cell.\n */\nexport function chartToDegradedTable(params: {\n data?: {\n labels?: Array<string | number>;\n datasets?: Array<{ label?: string; data?: unknown[] }>;\n };\n}): DegradedTable {\n const datasets = params.data?.datasets ?? [];\n const labels = params.data?.labels ?? [];\n const rowCount = Math.max(labels.length, ...datasets.map((d) => d.data?.length ?? 0), 0);\n\n const columns = ['', ...datasets.map((d, i) => d.label ?? `Series ${i + 1}`)];\n const rows: Array<Array<string | number>> = [];\n for (let r = 0; r < Math.min(rowCount, MAX_PROJECTED_ROWS); r++) {\n rows.push([cell(labels[r] ?? r + 1), ...datasets.map((d) => cell(d.data?.[r]))]);\n }\n return { columns, rows };\n}\n"],"names":["_a"],"mappings":"AAkBA,MAAM,qBAAqB;AAG3B,SAAS,KAAK,OAAwB;AACpC,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI;AACF,aAAO,KAAK,UAAU,KAAK;AAAA,IAC7B,QAAQ;AACN,aAAO,OAAO,KAAK;AAAA,IACrB;AAAA,EACF;AACA,SAAO,OAAO,KAAK;AACrB;AASO,SAAS,qBAAqB,QAGnB;AAChB,QAAM,QAAQ,OAAO,SAAS,CAAA;AAC9B,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO;AAAA,MACL,SAAS,CAAC,UAAU,UAAU,OAAO;AAAA,MACrC,MAAM,MAAM,MAAM,GAAG,kBAAkB,EAAE,IAAI,CAAC,MAAM;AAClD,cAAM,QAAQ,CAAC,EAAE,UAAU,OAAO,OAAO,EAAE,MAAM,IAAI,IAAI,EAAE,SAAS,EAAE,EACnE,OAAO,OAAO,EACd,KAAK,KAAK;AACb,eAAO,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,MAAM,GAAG,KAAK;AAAA,MAC/C,CAAC;AAAA,IAAA;AAAA,EAEL;AACA,QAAM,QAAQ,OAAO,SAAS,CAAA;AAC9B,SAAO;AAAA,IACL,SAAS,CAAC,QAAQ,OAAO;AAAA,IACzB,MAAM,MAAM,MAAM,GAAG,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AAAA,EAAA;AAE3F;AAUA,SAAS,YAAY,QAA0C;AAC7D,MAAI,IAAa;AAEjB,SAAO,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,EAAE,CAAC,CAAC,EAAG,KAAI,EAAE,CAAC;AACvD,MAAI,MAAM,QAAQ,CAAC,KAAK,OAAO,EAAE,CAAC,MAAM,YAAY,OAAO,EAAE,CAAC,MAAM,UAAU;AAC5E,WAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;AAAA,EACpB;AACA,SAAO;AACT;AAOO,SAAS,mBAAmB,QAOjB;AA3ElB;AA4EE,QAAM,OAAsC,CAAA;AAE5C,aAAW,KAAK,OAAO,WAAW,CAAA,GAAI;AACpC,UAAM,MAAM,MAAM,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,CAAC,KAAI,OAAE,aAAF,mBAAY;AACpE,UAAM,MAAM,MAAM,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,CAAC,KAAI,OAAE,aAAF,mBAAY;AACpE,SAAK,KAAK,CAAC,UAAU,KAAK,GAAG,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;AAAA,EAC9E;AAEA,QAAM,KAAK,OAAO;AAClB,QAAM,WAAW,MAAM,QAAQ,yBAAI,QAAQ,IAAI,GAAI,WAAW,CAAA;AAC9D,aAAW,KAAK,UAAU;AACxB,UAAM,KAAK,aAAY,OAAE,aAAF,mBAAY,WAAW;AAC9C,UAAM,QAAQ,EAAE,cAAc,CAAA;AAC9B,UAAM,cAAc,OAAO,KAAK,KAAK,EAClC,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,EACnC,KAAK,IAAI;AACZ,SAAK,KAAK;AAAA,MACR,OAAK,OAAE,aAAF,mBAAY,SAAQ,SAAS;AAAA,MAClC,KAAK,KAAK,GAAG,CAAC,CAAC,IAAI;AAAA,MACnB,KAAK,KAAK,GAAG,CAAC,CAAC,IAAI;AAAA,MACnB;AAAA,IAAA,CACD;AAAA,EACH;AAEA,SAAO;AAAA,IACL,SAAS,CAAC,QAAQ,OAAO,OAAO,MAAM;AAAA,IACtC,MAAM,KAAK,MAAM,GAAG,kBAAkB;AAAA,EAAA;AAE1C;AASO,SAAS,qBAAqB,QAKnB;AAvHlB;AAwHE,QAAM,aAAW,YAAO,SAAP,mBAAa,aAAY,CAAA;AAC1C,QAAM,WAAS,YAAO,SAAP,mBAAa,WAAU,CAAA;AACtC,QAAM,WAAW,KAAK,IAAI,OAAO,QAAQ,GAAG,SAAS,IAAI,CAAC;AA1H5D,QAAAA;AA0HkE,aAAAA,MAAA,EAAE,SAAF,gBAAAA,IAAQ,WAAU;AAAA,GAAC,GAAG,CAAC;AAEvF,QAAM,UAAU,CAAC,IAAI,GAAG,SAAS,IAAI,CAAC,GAAG,MAAM,EAAE,SAAS,UAAU,IAAI,CAAC,EAAE,CAAC;AAC5E,QAAM,OAAsC,CAAA;AAC5C,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,UAAU,kBAAkB,GAAG,KAAK;AAC/D,SAAK,KAAK,CAAC,KAAK,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,GAAG,SAAS,IAAI,CAAC;AA/H1D,UAAAA;AA+HgE,mBAAKA,MAAA,EAAE,SAAF,gBAAAA,IAAS,EAAE;AAAA,KAAC,CAAC,CAAC;AAAA,EACjF;AACA,SAAO,EAAE,SAAS,KAAA;AACpB;"}
|
|
1
|
+
{"version":3,"file":"degraded-projections.js","sources":["../../src/utils/degraded-projections.ts"],"sourcesContent":["/**\n * Degraded-fallback projections (audit 2026-05-30, P2.5).\n *\n * Pure functions that turn a heavy renderer's params into a flat\n * `{ columns, rows }` table for `<DegradedFallback>` — the middle rung of\n * the fallback ladder shown when the native render (G6 / Leaflet / Chart.js)\n * is unavailable or throws. No peer deps, no side effects, fully testable.\n *\n * These are best-effort views: they surface the underlying data so the user\n * isn't left with a blank space, not faithful reproductions of the chart/\n * map/graph.\n */\n\nimport { formatMCPUIString } from './format-string';\n\n/**\n * Column headers and series names of the degraded tables.\n *\n * The projections are pure helpers with no access to `MCPUIStrings`, so the\n * wording is injected: each function takes an optional trailing `labels`\n * partial, and the renderers feed it from `useMCPUIStrings()`. Left out, the\n * English defaults below apply — the pre-v6.20.0 behaviour.\n *\n * @since v6.20.0\n */\nexport interface DegradedProjectionLabels {\n /** Graph edge table — source column. */\n source: string;\n /** Graph edge table — target column. */\n target: string;\n /** Graph edge / node table — label column. */\n label: string;\n /** Graph node table — node id column. */\n node: string;\n /** Map table — feature type column. */\n type: string;\n /** Map table — latitude column. */\n lat: string;\n /** Map table — longitude column. */\n lng: string;\n /** Map table — property summary column. */\n info: string;\n /** Map table — `Type` cell of a marker row (v6.20.0, 6th pass). */\n marker: string;\n /** Map table — `Type` cell of a GeoJSON feature without a geometry type (v6.20.0). */\n feature: string;\n /** Chart table — fallback dataset name. Template — `{n}`. */\n series: string;\n}\n\n/** English defaults for {@link DegradedProjectionLabels}. */\nexport const DEGRADED_PROJECTION_LABELS: DegradedProjectionLabels = {\n source: 'Source',\n target: 'Target',\n label: 'Label',\n node: 'Node',\n type: 'Type',\n lat: 'Lat',\n lng: 'Lng',\n info: 'Info',\n marker: 'marker',\n feature: 'feature',\n series: 'Series {n}',\n};\n\nconst withLabels = (labels?: Partial<DegradedProjectionLabels>): DegradedProjectionLabels => ({\n ...DEGRADED_PROJECTION_LABELS,\n ...labels,\n});\n\nexport interface DegradedTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\nconst MAX_PROJECTED_ROWS = 200;\n\n/** Compact a value to a single table cell string. */\nfunction cell(value: unknown): string {\n if (value == null) return '';\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n\n// ─── Graph ───────────────────────────────────────────────────────────────\n\n/**\n * Graph → edge table when edges exist (Source / Target / Label), else a\n * node list (Node / Label). The graph renderer can therefore degrade to a\n * readable relationship listing instead of a blank canvas.\n */\nexport function graphToDegradedTable(params: {\n nodes?: Array<{ id: string; label?: string }>;\n edges?: Array<{ source: string; target: string; label?: string; weight?: number }>;\n}, labels?: Partial<DegradedProjectionLabels>): DegradedTable {\n const l = withLabels(labels);\n const edges = params.edges ?? [];\n if (edges.length > 0) {\n return {\n columns: [l.source, l.target, l.label],\n rows: edges.slice(0, MAX_PROJECTED_ROWS).map((e) => {\n const label = [e.weight != null ? String(e.weight) : '', e.label ?? '']\n .filter(Boolean)\n .join(' · ');\n return [cell(e.source), cell(e.target), label];\n }),\n };\n }\n const nodes = params.nodes ?? [];\n return {\n columns: [l.node, l.label],\n rows: nodes.slice(0, MAX_PROJECTED_ROWS).map((n) => [cell(n.id), cell(n.label ?? n.id)]),\n };\n}\n\n// ─── Map ───────────────────────────────────────────────────────────────────\n\ninterface GeoJSONLikeFeature {\n geometry?: { type?: string; coordinates?: unknown } | null;\n properties?: Record<string, unknown> | null;\n}\n\n/** Pull a representative `[lng, lat]` pair out of a geometry's coordinates. */\nfunction firstLngLat(coords: unknown): [number, number] | null {\n let c: unknown = coords;\n // Descend nested arrays until we reach a [number, number, ...] position.\n while (Array.isArray(c) && Array.isArray(c[0])) c = c[0];\n if (Array.isArray(c) && typeof c[0] === 'number' && typeof c[1] === 'number') {\n return [c[0], c[1]];\n }\n return null;\n}\n\n/**\n * Map → a coordinate table. Markers become Lat/Lng/Label rows; GeoJSON\n * features become Type / Lat / Lng (+ a compact properties summary). So a\n * map that can't paint still lists where its points are.\n */\nexport function mapToDegradedTable(params: {\n markers?: Array<{\n position: [number, number] | { lat: number; lng: number };\n tooltip?: string;\n popup?: string;\n }>;\n geojson?: unknown;\n}, labels?: Partial<DegradedProjectionLabels>): DegradedTable {\n const l = withLabels(labels);\n const rows: Array<Array<string | number>> = [];\n\n for (const m of params.markers ?? []) {\n const lat = Array.isArray(m.position) ? m.position[0] : m.position?.lat;\n const lng = Array.isArray(m.position) ? m.position[1] : m.position?.lng;\n rows.push([l.marker, cell(lat), cell(lng), cell(m.tooltip ?? m.popup ?? '')]);\n }\n\n const fc = params.geojson as { features?: GeoJSONLikeFeature[] } | undefined;\n const features = Array.isArray(fc?.features) ? fc!.features : [];\n for (const f of features) {\n const ll = firstLngLat(f.geometry?.coordinates);\n const props = f.properties ?? {};\n const propSummary = Object.keys(props)\n .slice(0, 3)\n .map((k) => `${k}=${cell(props[k])}`)\n .join(', ');\n rows.push([\n cell(f.geometry?.type ?? l.feature),\n ll ? cell(ll[1]) : '',\n ll ? cell(ll[0]) : '',\n propSummary,\n ]);\n }\n\n return {\n columns: [l.type, l.lat, l.lng, l.info],\n rows: rows.slice(0, MAX_PROJECTED_ROWS),\n };\n}\n\n// ─── Chart ───────────────────────────────────────────────────────────────\n\n/**\n * Chart → a series table: one row per label, one column per dataset. So a\n * chart that can't draw still shows its numbers. Point/object data (scatter,\n * bubble, time series) is stringified per cell.\n */\nexport function chartToDegradedTable(params: {\n data?: {\n labels?: Array<string | number>;\n datasets?: Array<{ label?: string; data?: unknown[] }>;\n };\n}, labels?: Partial<DegradedProjectionLabels>): DegradedTable {\n const l = withLabels(labels);\n const datasets = params.data?.datasets ?? [];\n const dataLabels = params.data?.labels ?? [];\n const rowCount = Math.max(dataLabels.length, ...datasets.map((d) => d.data?.length ?? 0), 0);\n\n const columns = [\n '',\n ...datasets.map((d, i) => d.label ?? formatMCPUIString(l.series, { n: i + 1 })),\n ];\n const rows: Array<Array<string | number>> = [];\n for (let r = 0; r < Math.min(rowCount, MAX_PROJECTED_ROWS); r++) {\n rows.push([cell(dataLabels[r] ?? r + 1), ...datasets.map((d) => cell(d.data?.[r]))]);\n }\n return { columns, rows };\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
function formatMCPUIString(template, vars) {
|
|
4
|
+
return template.replace(
|
|
5
|
+
/\{(\w+)\}/g,
|
|
6
|
+
(match, name) => Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
exports.formatMCPUIString = formatMCPUIString;
|
|
10
|
+
//# sourceMappingURL=format-string.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-string.cjs","sources":["../../src/utils/format-string.ts"],"sourcesContent":["/**\n * `formatMCPUIString` — the chrome-string template helper, runtime-free.\n *\n * @since v6.20.0 (extracted from `MCPUIStringsContext` so the pure adapters\n * under `src/adapters` can interpolate their own message templates without\n * importing `solid-js`). `MCPUIStringsContext` re-exports it, so every\n * existing import path — including the root barrel — keeps working.\n *\n * This module imports nothing. It must stay that way: `src/adapters/*` is\n * published as a dedicated subpath that never pulls in the renderer.\n */\n\n/**\n * Substitutes `{name}` placeholders in a chrome string template.\n *\n * Only the keys present in `vars` are replaced; an unknown placeholder is\n * left verbatim so a mistyped or locale-specific template degrades to\n * visible text rather than to `undefined`.\n *\n * @example\n * ```ts\n * formatMCPUIString('Sort by {column}', { column: 'Revenue' }) // 'Sort by Revenue'\n * formatMCPUIString('Export CSV ({count} rows)', { count: 42 }) // 'Export CSV (42 rows)'\n * ```\n */\nexport function formatMCPUIString(\n template: string,\n vars: Record<string, string | number>\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) =>\n Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match\n )\n}\n"],"names":[],"mappings":";;AAyBO,SAAS,kBACd,UACA,MACQ;AACR,SAAO,SAAS;AAAA,IAAQ;AAAA,IAAc,CAAC,OAAO,SAC5C,OAAO,UAAU,eAAe,KAAK,MAAM,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI;AAAA,EAAA;AAE5E;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `formatMCPUIString` — the chrome-string template helper, runtime-free.
|
|
3
|
+
*
|
|
4
|
+
* @since v6.20.0 (extracted from `MCPUIStringsContext` so the pure adapters
|
|
5
|
+
* under `src/adapters` can interpolate their own message templates without
|
|
6
|
+
* importing `solid-js`). `MCPUIStringsContext` re-exports it, so every
|
|
7
|
+
* existing import path — including the root barrel — keeps working.
|
|
8
|
+
*
|
|
9
|
+
* This module imports nothing. It must stay that way: `src/adapters/*` is
|
|
10
|
+
* published as a dedicated subpath that never pulls in the renderer.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Substitutes `{name}` placeholders in a chrome string template.
|
|
14
|
+
*
|
|
15
|
+
* Only the keys present in `vars` are replaced; an unknown placeholder is
|
|
16
|
+
* left verbatim so a mistyped or locale-specific template degrades to
|
|
17
|
+
* visible text rather than to `undefined`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* formatMCPUIString('Sort by {column}', { column: 'Revenue' }) // 'Sort by Revenue'
|
|
22
|
+
* formatMCPUIString('Export CSV ({count} rows)', { count: 42 }) // 'Export CSV (42 rows)'
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatMCPUIString(template: string, vars: Record<string, string | number>): string;
|
|
26
|
+
//# sourceMappingURL=format-string.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-string.d.ts","sourceRoot":"","sources":["../../src/utils/format-string.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GACpC,MAAM,CAIR"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function formatMCPUIString(template, vars) {
|
|
2
|
+
return template.replace(
|
|
3
|
+
/\{(\w+)\}/g,
|
|
4
|
+
(match, name) => Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match
|
|
5
|
+
);
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
formatMCPUIString
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=format-string.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-string.js","sources":["../../src/utils/format-string.ts"],"sourcesContent":["/**\n * `formatMCPUIString` — the chrome-string template helper, runtime-free.\n *\n * @since v6.20.0 (extracted from `MCPUIStringsContext` so the pure adapters\n * under `src/adapters` can interpolate their own message templates without\n * importing `solid-js`). `MCPUIStringsContext` re-exports it, so every\n * existing import path — including the root barrel — keeps working.\n *\n * This module imports nothing. It must stay that way: `src/adapters/*` is\n * published as a dedicated subpath that never pulls in the renderer.\n */\n\n/**\n * Substitutes `{name}` placeholders in a chrome string template.\n *\n * Only the keys present in `vars` are replaced; an unknown placeholder is\n * left verbatim so a mistyped or locale-specific template degrades to\n * visible text rather than to `undefined`.\n *\n * @example\n * ```ts\n * formatMCPUIString('Sort by {column}', { column: 'Revenue' }) // 'Sort by Revenue'\n * formatMCPUIString('Export CSV ({count} rows)', { count: 42 }) // 'Export CSV (42 rows)'\n * ```\n */\nexport function formatMCPUIString(\n template: string,\n vars: Record<string, string | number>\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) =>\n Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match\n )\n}\n"],"names":[],"mappings":"AAyBO,SAAS,kBACd,UACA,MACQ;AACR,SAAO,SAAS;AAAA,IAAQ;AAAA,IAAc,CAAC,OAAO,SAC5C,OAAO,UAAU,eAAe,KAAK,MAAM,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI;AAAA,EAAA;AAE5E;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const solidJs = require("solid-js");
|
|
4
|
+
const validation = require("../services/validation.cjs");
|
|
5
|
+
function shouldSetCredentialless(url, config, options) {
|
|
6
|
+
const mode = config.iframeCredentialless;
|
|
7
|
+
if (mode === "always") return true;
|
|
8
|
+
if (mode === "never") return false;
|
|
9
|
+
if (!options.sandboxedWithoutSameOrigin) return false;
|
|
10
|
+
return !validation.isTrustedIframeDomain(url, {
|
|
11
|
+
customTrustedDomains: config.customTrustedIframeDomains
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function createCrossOriginIsolated() {
|
|
15
|
+
const [isolated, setIsolated] = solidJs.createSignal(false);
|
|
16
|
+
solidJs.onMount(() => {
|
|
17
|
+
setIsolated(typeof window !== "undefined" && window.crossOriginIsolated === true);
|
|
18
|
+
});
|
|
19
|
+
return isolated;
|
|
20
|
+
}
|
|
21
|
+
function shouldShowIframeFallbackLink(config, crossOriginIsolated) {
|
|
22
|
+
const mode = config.iframeFallbackLink;
|
|
23
|
+
if (mode === "always") return true;
|
|
24
|
+
if (mode === "never") return false;
|
|
25
|
+
return crossOriginIsolated;
|
|
26
|
+
}
|
|
27
|
+
exports.createCrossOriginIsolated = createCrossOriginIsolated;
|
|
28
|
+
exports.shouldSetCredentialless = shouldSetCredentialless;
|
|
29
|
+
exports.shouldShowIframeFallbackLink = shouldShowIframeFallbackLink;
|
|
30
|
+
//# sourceMappingURL=iframe-coep.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iframe-coep.cjs","sources":["../../src/utils/iframe-coep.ts"],"sourcesContent":["/**\n * COEP helpers for the two iframes the library renders\n * (`IframeRenderer` in `UIResourceRenderer.tsx`, and the YouTube / Vimeo\n * embed in `VideoRenderer.tsx`).\n *\n * @since v6.21.0\n *\n * A host that serves `Cross-Origin-Embedder-Policy: credentialless` makes the\n * browser refuse any cross-origin iframe whose own document sends no COEP\n * header. The HTML attribute `credentialless` on the `<iframe>` lifts that,\n * at the price of the embedded document losing access to the cookies and\n * storage of its own origin — see `MCPUIConfigContext` for the policy.\n */\n\nimport { createSignal, onMount, type Accessor } from 'solid-js'\nimport { isTrustedIframeDomain } from '../services/validation'\nimport type { MCPUIConfig } from '../context/MCPUIConfigContext'\n\n/**\n * Does this iframe get the boolean `credentialless` attribute?\n *\n * `'auto'` (the default) says yes only when the embed has nothing to lose:\n * the host is not trusted AND the iframe already runs without cookies because\n * its `sandbox` has no `allow-same-origin` (`sandboxedWithoutSameOrigin`).\n * The video embed carries no sandbox, so in `'auto'` it keeps its provider\n * cookies and a COEP host must opt in with `'always'`.\n *\n * An unparsable URL is not trusted, so it gets the attribute.\n */\nexport function shouldSetCredentialless(\n url: string,\n config: MCPUIConfig,\n options: { sandboxedWithoutSameOrigin: boolean }\n): boolean {\n const mode = config.iframeCredentialless\n if (mode === 'always') return true\n if (mode === 'never') return false\n if (!options.sandboxedWithoutSameOrigin) return false\n return !isTrustedIframeDomain(url, {\n customTrustedDomains: config.customTrustedIframeDomains,\n })\n}\n\n/**\n * `window.crossOriginIsolated`, read **after mount** into a signal.\n *\n * Reading it during render would make the server emit markup the client\n * cannot reproduce; the signal starts at `false` (the SSR value) and flips\n * once mounted, so hydration always matches.\n */\nexport function createCrossOriginIsolated(): Accessor<boolean> {\n const [isolated, setIsolated] = createSignal(false)\n onMount(() => {\n setIsolated(typeof window !== 'undefined' && window.crossOriginIsolated === true)\n })\n return isolated\n}\n\n/**\n * Does the \"open in a new tab\" link show under an embed?\n *\n * `'auto'` shows it only on a cross-origin-isolated page — exactly where COEP\n * can block the frame, and where the blocking is silent (a refused\n * cross-origin document fires no `error` event the parent can observe).\n */\nexport function shouldShowIframeFallbackLink(\n config: MCPUIConfig,\n crossOriginIsolated: boolean\n): boolean {\n const mode = config.iframeFallbackLink\n if (mode === 'always') return true\n if (mode === 'never') return false\n return crossOriginIsolated\n}\n"],"names":["isTrustedIframeDomain","createSignal","onMount"],"mappings":";;;;AA6BO,SAAS,wBACd,KACA,QACA,SACS;AACT,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI,SAAS,QAAS,QAAO;AAC7B,MAAI,CAAC,QAAQ,2BAA4B,QAAO;AAChD,SAAO,CAACA,WAAAA,sBAAsB,KAAK;AAAA,IACjC,sBAAsB,OAAO;AAAA,EAAA,CAC9B;AACH;AASO,SAAS,4BAA+C;AAC7D,QAAM,CAAC,UAAU,WAAW,IAAIC,QAAAA,aAAa,KAAK;AAClDC,UAAAA,QAAQ,MAAM;AACZ,gBAAY,OAAO,WAAW,eAAe,OAAO,wBAAwB,IAAI;AAAA,EAClF,CAAC;AACD,SAAO;AACT;AASO,SAAS,6BACd,QACA,qBACS;AACT,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI,SAAS,QAAS,QAAO;AAC7B,SAAO;AACT;;;;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COEP helpers for the two iframes the library renders
|
|
3
|
+
* (`IframeRenderer` in `UIResourceRenderer.tsx`, and the YouTube / Vimeo
|
|
4
|
+
* embed in `VideoRenderer.tsx`).
|
|
5
|
+
*
|
|
6
|
+
* @since v6.21.0
|
|
7
|
+
*
|
|
8
|
+
* A host that serves `Cross-Origin-Embedder-Policy: credentialless` makes the
|
|
9
|
+
* browser refuse any cross-origin iframe whose own document sends no COEP
|
|
10
|
+
* header. The HTML attribute `credentialless` on the `<iframe>` lifts that,
|
|
11
|
+
* at the price of the embedded document losing access to the cookies and
|
|
12
|
+
* storage of its own origin — see `MCPUIConfigContext` for the policy.
|
|
13
|
+
*/
|
|
14
|
+
import { type Accessor } from 'solid-js';
|
|
15
|
+
import type { MCPUIConfig } from '../context/MCPUIConfigContext';
|
|
16
|
+
/**
|
|
17
|
+
* Does this iframe get the boolean `credentialless` attribute?
|
|
18
|
+
*
|
|
19
|
+
* `'auto'` (the default) says yes only when the embed has nothing to lose:
|
|
20
|
+
* the host is not trusted AND the iframe already runs without cookies because
|
|
21
|
+
* its `sandbox` has no `allow-same-origin` (`sandboxedWithoutSameOrigin`).
|
|
22
|
+
* The video embed carries no sandbox, so in `'auto'` it keeps its provider
|
|
23
|
+
* cookies and a COEP host must opt in with `'always'`.
|
|
24
|
+
*
|
|
25
|
+
* An unparsable URL is not trusted, so it gets the attribute.
|
|
26
|
+
*/
|
|
27
|
+
export declare function shouldSetCredentialless(url: string, config: MCPUIConfig, options: {
|
|
28
|
+
sandboxedWithoutSameOrigin: boolean;
|
|
29
|
+
}): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* `window.crossOriginIsolated`, read **after mount** into a signal.
|
|
32
|
+
*
|
|
33
|
+
* Reading it during render would make the server emit markup the client
|
|
34
|
+
* cannot reproduce; the signal starts at `false` (the SSR value) and flips
|
|
35
|
+
* once mounted, so hydration always matches.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createCrossOriginIsolated(): Accessor<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Does the "open in a new tab" link show under an embed?
|
|
40
|
+
*
|
|
41
|
+
* `'auto'` shows it only on a cross-origin-isolated page — exactly where COEP
|
|
42
|
+
* can block the frame, and where the blocking is silent (a refused
|
|
43
|
+
* cross-origin document fires no `error` event the parent can observe).
|
|
44
|
+
*/
|
|
45
|
+
export declare function shouldShowIframeFallbackLink(config: MCPUIConfig, crossOriginIsolated: boolean): boolean;
|
|
46
|
+
//# sourceMappingURL=iframe-coep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iframe-coep.d.ts","sourceRoot":"","sources":["../../src/utils/iframe-coep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAE/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAEhE;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE;IAAE,0BAA0B,EAAE,OAAO,CAAA;CAAE,GAC/C,OAAO,CAQT;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,IAAI,QAAQ,CAAC,OAAO,CAAC,CAM7D;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,WAAW,EACnB,mBAAmB,EAAE,OAAO,GAC3B,OAAO,CAKT"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createSignal, onMount } from "solid-js";
|
|
2
|
+
import { isTrustedIframeDomain } from "../services/validation.js";
|
|
3
|
+
function shouldSetCredentialless(url, config, options) {
|
|
4
|
+
const mode = config.iframeCredentialless;
|
|
5
|
+
if (mode === "always") return true;
|
|
6
|
+
if (mode === "never") return false;
|
|
7
|
+
if (!options.sandboxedWithoutSameOrigin) return false;
|
|
8
|
+
return !isTrustedIframeDomain(url, {
|
|
9
|
+
customTrustedDomains: config.customTrustedIframeDomains
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function createCrossOriginIsolated() {
|
|
13
|
+
const [isolated, setIsolated] = createSignal(false);
|
|
14
|
+
onMount(() => {
|
|
15
|
+
setIsolated(typeof window !== "undefined" && window.crossOriginIsolated === true);
|
|
16
|
+
});
|
|
17
|
+
return isolated;
|
|
18
|
+
}
|
|
19
|
+
function shouldShowIframeFallbackLink(config, crossOriginIsolated) {
|
|
20
|
+
const mode = config.iframeFallbackLink;
|
|
21
|
+
if (mode === "always") return true;
|
|
22
|
+
if (mode === "never") return false;
|
|
23
|
+
return crossOriginIsolated;
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
createCrossOriginIsolated,
|
|
27
|
+
shouldSetCredentialless,
|
|
28
|
+
shouldShowIframeFallbackLink
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=iframe-coep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iframe-coep.js","sources":["../../src/utils/iframe-coep.ts"],"sourcesContent":["/**\n * COEP helpers for the two iframes the library renders\n * (`IframeRenderer` in `UIResourceRenderer.tsx`, and the YouTube / Vimeo\n * embed in `VideoRenderer.tsx`).\n *\n * @since v6.21.0\n *\n * A host that serves `Cross-Origin-Embedder-Policy: credentialless` makes the\n * browser refuse any cross-origin iframe whose own document sends no COEP\n * header. The HTML attribute `credentialless` on the `<iframe>` lifts that,\n * at the price of the embedded document losing access to the cookies and\n * storage of its own origin — see `MCPUIConfigContext` for the policy.\n */\n\nimport { createSignal, onMount, type Accessor } from 'solid-js'\nimport { isTrustedIframeDomain } from '../services/validation'\nimport type { MCPUIConfig } from '../context/MCPUIConfigContext'\n\n/**\n * Does this iframe get the boolean `credentialless` attribute?\n *\n * `'auto'` (the default) says yes only when the embed has nothing to lose:\n * the host is not trusted AND the iframe already runs without cookies because\n * its `sandbox` has no `allow-same-origin` (`sandboxedWithoutSameOrigin`).\n * The video embed carries no sandbox, so in `'auto'` it keeps its provider\n * cookies and a COEP host must opt in with `'always'`.\n *\n * An unparsable URL is not trusted, so it gets the attribute.\n */\nexport function shouldSetCredentialless(\n url: string,\n config: MCPUIConfig,\n options: { sandboxedWithoutSameOrigin: boolean }\n): boolean {\n const mode = config.iframeCredentialless\n if (mode === 'always') return true\n if (mode === 'never') return false\n if (!options.sandboxedWithoutSameOrigin) return false\n return !isTrustedIframeDomain(url, {\n customTrustedDomains: config.customTrustedIframeDomains,\n })\n}\n\n/**\n * `window.crossOriginIsolated`, read **after mount** into a signal.\n *\n * Reading it during render would make the server emit markup the client\n * cannot reproduce; the signal starts at `false` (the SSR value) and flips\n * once mounted, so hydration always matches.\n */\nexport function createCrossOriginIsolated(): Accessor<boolean> {\n const [isolated, setIsolated] = createSignal(false)\n onMount(() => {\n setIsolated(typeof window !== 'undefined' && window.crossOriginIsolated === true)\n })\n return isolated\n}\n\n/**\n * Does the \"open in a new tab\" link show under an embed?\n *\n * `'auto'` shows it only on a cross-origin-isolated page — exactly where COEP\n * can block the frame, and where the blocking is silent (a refused\n * cross-origin document fires no `error` event the parent can observe).\n */\nexport function shouldShowIframeFallbackLink(\n config: MCPUIConfig,\n crossOriginIsolated: boolean\n): boolean {\n const mode = config.iframeFallbackLink\n if (mode === 'always') return true\n if (mode === 'never') return false\n return crossOriginIsolated\n}\n"],"names":[],"mappings":";;AA6BO,SAAS,wBACd,KACA,QACA,SACS;AACT,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI,SAAS,QAAS,QAAO;AAC7B,MAAI,CAAC,QAAQ,2BAA4B,QAAO;AAChD,SAAO,CAAC,sBAAsB,KAAK;AAAA,IACjC,sBAAsB,OAAO;AAAA,EAAA,CAC9B;AACH;AASO,SAAS,4BAA+C;AAC7D,QAAM,CAAC,UAAU,WAAW,IAAI,aAAa,KAAK;AAClD,UAAQ,MAAM;AACZ,gBAAY,OAAO,WAAW,eAAe,OAAO,wBAAwB,IAAI;AAAA,EAClF,CAAC;AACD,SAAO;AACT;AASO,SAAS,6BACd,QACA,qBACS;AACT,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI,SAAS,QAAS,QAAO;AAC7B,SAAO;AACT;"}
|
package/dist/validation.cjs
CHANGED
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const validation = require("./services/validation.cjs");
|
|
4
4
|
exports.DEFAULT_RESOURCE_LIMITS = validation.DEFAULT_RESOURCE_LIMITS;
|
|
5
|
+
exports.DEFAULT_VALIDATION_MESSAGES = validation.DEFAULT_VALIDATION_MESSAGES;
|
|
6
|
+
exports.getIframeSandbox = validation.getIframeSandbox;
|
|
7
|
+
exports.isTrustedIframeDomain = validation.isTrustedIframeDomain;
|
|
5
8
|
exports.sanitizeString = validation.sanitizeString;
|
|
6
9
|
exports.validateChartComponent = validation.validateChartComponent;
|
|
7
10
|
exports.validateComponent = validation.validateComponent;
|
|
11
|
+
exports.validateFieldValue = validation.validateFieldValue;
|
|
12
|
+
exports.validateFormData = validation.validateFormData;
|
|
8
13
|
exports.validateGridPosition = validation.validateGridPosition;
|
|
9
14
|
exports.validateIframeDomain = validation.validateIframeDomain;
|
|
10
15
|
exports.validateLayout = validation.validateLayout;
|
package/dist/validation.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validation.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
|
package/dist/validation.d.cts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* import { validateLayout } from '@seed-ship/mcp-ui-solid/validation'
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
|
-
export { validateComponent, validateLayout, validateGridPosition, validateChartComponent, validateTableComponent, validatePayloadSize, validateIframeDomain, sanitizeString, DEFAULT_RESOURCE_LIMITS, } from './services/validation';
|
|
12
|
+
export { validateComponent, validateLayout, validateGridPosition, validateChartComponent, validateTableComponent, validatePayloadSize, validateIframeDomain, getIframeSandbox, isTrustedIframeDomain, sanitizeString, DEFAULT_RESOURCE_LIMITS, validateFieldValue, validateFormData, DEFAULT_VALIDATION_MESSAGES, } from './services/validation';
|
|
13
|
+
export type { FormValidationMessages } from './services/validation';
|
|
13
14
|
export type { UIComponent, UILayout, GridPosition, ComponentType, ChartComponentParams, TableComponentParams, MetricComponentParams, TextComponentParams, ValidationResult, ResourceLimits, } from './types';
|
|
14
15
|
//# sourceMappingURL=validation.d.ts.map
|
package/dist/validation.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* import { validateLayout } from '@seed-ship/mcp-ui-solid/validation'
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
|
-
export { validateComponent, validateLayout, validateGridPosition, validateChartComponent, validateTableComponent, validatePayloadSize, validateIframeDomain, sanitizeString, DEFAULT_RESOURCE_LIMITS, } from './services/validation';
|
|
12
|
+
export { validateComponent, validateLayout, validateGridPosition, validateChartComponent, validateTableComponent, validatePayloadSize, validateIframeDomain, getIframeSandbox, isTrustedIframeDomain, sanitizeString, DEFAULT_RESOURCE_LIMITS, validateFieldValue, validateFormData, DEFAULT_VALIDATION_MESSAGES, } from './services/validation';
|
|
13
|
+
export type { FormValidationMessages } from './services/validation';
|
|
13
14
|
export type { UIComponent, UILayout, GridPosition, ComponentType, ChartComponentParams, TableComponentParams, MetricComponentParams, TextComponentParams, ValidationResult, ResourceLimits, } from './types';
|
|
14
15
|
//# sourceMappingURL=validation.d.ts.map
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,uBAAuB,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAGhB,qBAAqB,EACrB,cAAc,EACd,uBAAuB,EAEvB,kBAAkB,EAClB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,YAAY,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAA"}
|
package/dist/validation.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { DEFAULT_RESOURCE_LIMITS, sanitizeString, validateChartComponent, validateComponent, validateGridPosition, validateIframeDomain, validateLayout, validatePayloadSize, validateTableComponent } from "./services/validation.js";
|
|
1
|
+
import { DEFAULT_RESOURCE_LIMITS, DEFAULT_VALIDATION_MESSAGES, getIframeSandbox, isTrustedIframeDomain, sanitizeString, validateChartComponent, validateComponent, validateFieldValue, validateFormData, validateGridPosition, validateIframeDomain, validateLayout, validatePayloadSize, validateTableComponent } from "./services/validation.js";
|
|
2
2
|
export {
|
|
3
3
|
DEFAULT_RESOURCE_LIMITS,
|
|
4
|
+
DEFAULT_VALIDATION_MESSAGES,
|
|
5
|
+
getIframeSandbox,
|
|
6
|
+
isTrustedIframeDomain,
|
|
4
7
|
sanitizeString,
|
|
5
8
|
validateChartComponent,
|
|
6
9
|
validateComponent,
|
|
10
|
+
validateFieldValue,
|
|
11
|
+
validateFormData,
|
|
7
12
|
validateGridPosition,
|
|
8
13
|
validateIframeDomain,
|
|
9
14
|
validateLayout,
|
package/package.json
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
type ConnectorAction,
|
|
30
30
|
} from '@seed-ship/mcp-ui-spec'
|
|
31
31
|
import { z } from 'zod'
|
|
32
|
+
import { formatMCPUIString } from '../utils/format-string'
|
|
32
33
|
|
|
33
34
|
// ─────────────────────────────────────────────────────────────
|
|
34
35
|
// connectorActionsToActionGroup
|
|
@@ -74,11 +75,57 @@ export function connectorActionsToActionGroup(
|
|
|
74
75
|
// connectorResultToUILayout
|
|
75
76
|
// ─────────────────────────────────────────────────────────────
|
|
76
77
|
|
|
78
|
+
/**
|
|
79
|
+
* The visible wording of the two degraded states (R2).
|
|
80
|
+
*
|
|
81
|
+
* These paragraphs are rendered as `text` components, so unlike the payload
|
|
82
|
+
* they are the LIBRARY's own chrome. They cannot go through
|
|
83
|
+
* `MCPUIStrings` — the adapters are runtime-free and never import
|
|
84
|
+
* `solid-js` — so a host localizes them through
|
|
85
|
+
* `ConnectorResultToUILayoutOptions.messages` instead.
|
|
86
|
+
*
|
|
87
|
+
* Every field is a template resolved with `formatMCPUIString`.
|
|
88
|
+
*
|
|
89
|
+
* @since v6.20.0 — the defaults used to be hardcoded French.
|
|
90
|
+
*/
|
|
91
|
+
export interface ConnectorAdapterMessages {
|
|
92
|
+
/**
|
|
93
|
+
* Unreadable payload (tier 3). Template — `{versionSuffix}` is
|
|
94
|
+
* `degradedVersionSuffix` when the payload carried a string
|
|
95
|
+
* `schemaVersion`, and `''` otherwise.
|
|
96
|
+
*/
|
|
97
|
+
degradedNotice: string
|
|
98
|
+
/** Inserted into `degradedNotice`. Template — `{version}`. */
|
|
99
|
+
degradedVersionSuffix: string
|
|
100
|
+
/**
|
|
101
|
+
* Usable envelope, unknown version (tier 2). Template — `{version}` = the
|
|
102
|
+
* version read, `{expected}` = `CONNECTOR_DYNAMIC_RESULT_V1`.
|
|
103
|
+
*/
|
|
104
|
+
versionWarning: string
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** English defaults for {@link ConnectorAdapterMessages}. */
|
|
108
|
+
export const DEFAULT_CONNECTOR_MESSAGES: ConnectorAdapterMessages = {
|
|
109
|
+
degradedNotice:
|
|
110
|
+
'### Result not rendered\n\nThe connector result could not be interpreted{versionSuffix}. This explicit state replaces a silent disappearance of the rendering.',
|
|
111
|
+
degradedVersionSuffix: ' (schema: `{version}`)',
|
|
112
|
+
versionWarning:
|
|
113
|
+
'> \u26A0 Unrecognized connector schema (`{version}`, expected `{expected}`). The rendering below is in degraded mode.',
|
|
114
|
+
}
|
|
115
|
+
|
|
77
116
|
export interface ConnectorResultToUILayoutOptions {
|
|
78
117
|
/** Layout id. Default derived from `connectorId` + `queryHash` / `toolName`. */
|
|
79
118
|
id?: string
|
|
80
119
|
/** Heading for the actions `action-group`. */
|
|
81
120
|
actionsTitle?: string
|
|
121
|
+
/**
|
|
122
|
+
* Partial override of the degraded-state wording, merged over
|
|
123
|
+
* {@link DEFAULT_CONNECTOR_MESSAGES}. Hosts that render in another
|
|
124
|
+
* language pass their own paragraphs here.
|
|
125
|
+
*
|
|
126
|
+
* @since v6.20.0
|
|
127
|
+
*/
|
|
128
|
+
messages?: Partial<ConnectorAdapterMessages>
|
|
82
129
|
}
|
|
83
130
|
|
|
84
131
|
/**
|
|
@@ -144,6 +191,7 @@ export function connectorResultToUILayout(
|
|
|
144
191
|
options: ConnectorResultToUILayoutOptions = {}
|
|
145
192
|
): UILayout {
|
|
146
193
|
const strict = ConnectorDynamicResultV1Schema.safeParse(result)
|
|
194
|
+
const messages: ConnectorAdapterMessages = { ...DEFAULT_CONNECTOR_MESSAGES, ...options.messages }
|
|
147
195
|
|
|
148
196
|
// ── Tier 3 : unreadable ───────────────────────────────────
|
|
149
197
|
if (!strict.success) {
|
|
@@ -158,9 +206,12 @@ export function connectorResultToUILayout(
|
|
|
158
206
|
components: [
|
|
159
207
|
degradedTextComponent(
|
|
160
208
|
'connector-degraded-notice',
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
209
|
+
formatMCPUIString(messages.degradedNotice, {
|
|
210
|
+
versionSuffix:
|
|
211
|
+
typeof version === 'string'
|
|
212
|
+
? formatMCPUIString(messages.degradedVersionSuffix, { version })
|
|
213
|
+
: '',
|
|
214
|
+
})
|
|
164
215
|
),
|
|
165
216
|
],
|
|
166
217
|
grid: { ...DEFAULT_GRID },
|
|
@@ -171,7 +222,10 @@ export function connectorResultToUILayout(
|
|
|
171
222
|
const components: UIComponent[] = [
|
|
172
223
|
degradedTextComponent(
|
|
173
224
|
'connector-version-warning',
|
|
174
|
-
|
|
225
|
+
formatMCPUIString(messages.versionWarning, {
|
|
226
|
+
version: r.schemaVersion,
|
|
227
|
+
expected: CONNECTOR_DYNAMIC_RESULT_V1,
|
|
228
|
+
})
|
|
175
229
|
),
|
|
176
230
|
...collectComponents(r),
|
|
177
231
|
]
|