@seed-ship/mcp-ui-solid 6.17.0 → 6.18.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.
Files changed (156) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +50 -3
  3. package/dist/adapters/index.d.ts +2 -0
  4. package/dist/adapters/index.d.ts.map +1 -1
  5. package/dist/adapters/presentation.cjs +141 -0
  6. package/dist/adapters/presentation.cjs.map +1 -0
  7. package/dist/adapters/presentation.d.ts +68 -0
  8. package/dist/adapters/presentation.d.ts.map +1 -0
  9. package/dist/adapters/presentation.js +141 -0
  10. package/dist/adapters/presentation.js.map +1 -0
  11. package/dist/adapters.cjs +4 -0
  12. package/dist/adapters.cjs.map +1 -1
  13. package/dist/adapters.d.cts +2 -0
  14. package/dist/adapters.d.ts +2 -0
  15. package/dist/adapters.js +4 -0
  16. package/dist/adapters.js.map +1 -1
  17. package/dist/components/ChartJSRenderer.cjs +165 -65
  18. package/dist/components/ChartJSRenderer.cjs.map +1 -1
  19. package/dist/components/ChartJSRenderer.d.ts.map +1 -1
  20. package/dist/components/ChartJSRenderer.js +168 -68
  21. package/dist/components/ChartJSRenderer.js.map +1 -1
  22. package/dist/components/ComponentToolbar.cjs.map +1 -1
  23. package/dist/components/ComponentToolbar.d.ts.map +1 -1
  24. package/dist/components/ComponentToolbar.js.map +1 -1
  25. package/dist/components/EditableLayoutContext.cjs +17 -0
  26. package/dist/components/EditableLayoutContext.cjs.map +1 -0
  27. package/dist/components/EditableLayoutContext.d.ts +5 -0
  28. package/dist/components/EditableLayoutContext.d.ts.map +1 -0
  29. package/dist/components/EditableLayoutContext.js +17 -0
  30. package/dist/components/EditableLayoutContext.js.map +1 -0
  31. package/dist/components/EditableUIResourceRenderer.cjs +87 -84
  32. package/dist/components/EditableUIResourceRenderer.cjs.map +1 -1
  33. package/dist/components/EditableUIResourceRenderer.d.ts.map +1 -1
  34. package/dist/components/EditableUIResourceRenderer.js +87 -84
  35. package/dist/components/EditableUIResourceRenderer.js.map +1 -1
  36. package/dist/components/ElicitationForm.cjs.map +1 -1
  37. package/dist/components/ElicitationForm.js.map +1 -1
  38. package/dist/components/FeedbackInline.cjs +0 -1
  39. package/dist/components/FeedbackInline.cjs.map +1 -1
  40. package/dist/components/FeedbackInline.js +0 -1
  41. package/dist/components/FeedbackInline.js.map +1 -1
  42. package/dist/components/GraphRenderer.cjs.map +1 -1
  43. package/dist/components/GraphRenderer.d.ts.map +1 -1
  44. package/dist/components/GraphRenderer.js.map +1 -1
  45. package/dist/components/GridRenderer.cjs +12 -6
  46. package/dist/components/GridRenderer.cjs.map +1 -1
  47. package/dist/components/GridRenderer.d.ts.map +1 -1
  48. package/dist/components/GridRenderer.js +13 -7
  49. package/dist/components/GridRenderer.js.map +1 -1
  50. package/dist/components/MapRenderer.cjs.map +1 -1
  51. package/dist/components/MapRenderer.d.ts.map +1 -1
  52. package/dist/components/MapRenderer.js.map +1 -1
  53. package/dist/components/PresentationFeedback.cjs +0 -1
  54. package/dist/components/PresentationFeedback.cjs.map +1 -1
  55. package/dist/components/PresentationFeedback.js +0 -1
  56. package/dist/components/PresentationFeedback.js.map +1 -1
  57. package/dist/components/UIResourceRenderer.cjs +37 -22
  58. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  59. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  60. package/dist/components/UIResourceRenderer.js +38 -23
  61. package/dist/components/UIResourceRenderer.js.map +1 -1
  62. package/dist/components/VerifiedText.cjs +0 -4
  63. package/dist/components/VerifiedText.cjs.map +1 -1
  64. package/dist/components/VerifiedText.d.ts.map +1 -1
  65. package/dist/components/VerifiedText.js +0 -4
  66. package/dist/components/VerifiedText.js.map +1 -1
  67. package/dist/components/chart-data-table.cjs +73 -0
  68. package/dist/components/chart-data-table.cjs.map +1 -0
  69. package/dist/components/chart-data-table.d.ts +23 -0
  70. package/dist/components/chart-data-table.d.ts.map +1 -0
  71. package/dist/components/chart-data-table.js +73 -0
  72. package/dist/components/chart-data-table.js.map +1 -0
  73. package/dist/context/MCPUIStringsContext.cjs +10 -9
  74. package/dist/context/MCPUIStringsContext.cjs.map +1 -1
  75. package/dist/context/MCPUIStringsContext.d.ts +17 -5
  76. package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
  77. package/dist/context/MCPUIStringsContext.js +11 -10
  78. package/dist/context/MCPUIStringsContext.js.map +1 -1
  79. package/dist/hooks/createResponsiveGrid.cjs +37 -0
  80. package/dist/hooks/createResponsiveGrid.cjs.map +1 -0
  81. package/dist/hooks/createResponsiveGrid.d.ts +6 -0
  82. package/dist/hooks/createResponsiveGrid.d.ts.map +1 -0
  83. package/dist/hooks/createResponsiveGrid.js +37 -0
  84. package/dist/hooks/createResponsiveGrid.js.map +1 -0
  85. package/dist/index.cjs +1 -0
  86. package/dist/index.cjs.map +1 -1
  87. package/dist/index.js +1 -0
  88. package/dist/index.js.map +1 -1
  89. package/dist/mcp-ui-spec/dist/schemas.cjs +13 -1
  90. package/dist/mcp-ui-spec/dist/schemas.cjs.map +1 -1
  91. package/dist/mcp-ui-spec/dist/schemas.js +13 -1
  92. package/dist/mcp-ui-spec/dist/schemas.js.map +1 -1
  93. package/dist/services/chat-bus.cjs.map +1 -1
  94. package/dist/services/chat-bus.d.ts.map +1 -1
  95. package/dist/services/chat-bus.js.map +1 -1
  96. package/dist/services/chat-prompt-controller.cjs.map +1 -1
  97. package/dist/services/chat-prompt-controller.d.ts.map +1 -1
  98. package/dist/services/chat-prompt-controller.js.map +1 -1
  99. package/dist/services/component-registry.cjs +162 -22
  100. package/dist/services/component-registry.cjs.map +1 -1
  101. package/dist/services/component-registry.d.ts +6 -3
  102. package/dist/services/component-registry.d.ts.map +1 -1
  103. package/dist/services/component-registry.js +162 -22
  104. package/dist/services/component-registry.js.map +1 -1
  105. package/dist/services/telemetry.cjs +0 -1
  106. package/dist/services/telemetry.cjs.map +1 -1
  107. package/dist/services/telemetry.js +0 -1
  108. package/dist/services/telemetry.js.map +1 -1
  109. package/dist/services/validation.cjs +21 -7
  110. package/dist/services/validation.cjs.map +1 -1
  111. package/dist/services/validation.d.ts.map +1 -1
  112. package/dist/services/validation.js +21 -7
  113. package/dist/services/validation.js.map +1 -1
  114. package/dist/types/index.d.ts +43 -8
  115. package/dist/types/index.d.ts.map +1 -1
  116. package/dist/types.d.cts +43 -8
  117. package/dist/types.d.ts +43 -8
  118. package/docs/briefs/VISUALIZATION-FOUNDATION-2026-09-14.md +105 -0
  119. package/package.json +4 -4
  120. package/src/adapters/index.ts +18 -0
  121. package/src/adapters/presentation.test.ts +114 -0
  122. package/src/adapters/presentation.ts +229 -0
  123. package/src/components/ChartJSRenderer.test.tsx +325 -0
  124. package/src/components/ChartJSRenderer.tsx +162 -27
  125. package/src/components/ChatPrompt.test.tsx +1 -1
  126. package/src/components/ComponentToolbar.tsx +1 -1
  127. package/src/components/EditableLayoutContext.tsx +12 -0
  128. package/src/components/EditableUIResourceRenderer.tsx +11 -8
  129. package/src/components/ElicitationForm.tsx +1 -1
  130. package/src/components/FeedbackInline.tsx +1 -1
  131. package/src/components/GraphRenderer.test.tsx +1 -2
  132. package/src/components/GraphRenderer.tsx +0 -2
  133. package/src/components/GridRenderer.tsx +6 -4
  134. package/src/components/MapRenderer.tsx +0 -3
  135. package/src/components/PresentationFeedback.tsx +1 -1
  136. package/src/components/ResponsiveGrid.test.tsx +166 -0
  137. package/src/components/TableRenderer.pagination.test.tsx +31 -0
  138. package/src/components/UIResourceRenderer.tsx +14 -9
  139. package/src/components/VerifiedText.tsx +0 -5
  140. package/src/components/chart-data-table.ts +97 -0
  141. package/src/context/MCPUIStringsContext.test.tsx +60 -0
  142. package/src/context/MCPUIStringsContext.tsx +31 -12
  143. package/src/hooks/createResponsiveGrid.ts +41 -0
  144. package/src/services/chat-bus.test.ts +1 -1
  145. package/src/services/chat-bus.ts +0 -2
  146. package/src/services/chat-prompt-controller.ts +0 -8
  147. package/src/services/component-registry.test.ts +81 -2
  148. package/src/services/component-registry.ts +167 -23
  149. package/src/services/telemetry.ts +1 -1
  150. package/src/services/validation.test.ts +1 -14
  151. package/src/services/validation.ts +23 -6
  152. package/src/services/visualization-validation.test.ts +42 -0
  153. package/src/types/index.ts +50 -9
  154. package/src/types/visualization-contracts.test.ts +66 -0
  155. package/src/utils/perf.test.ts +3 -3
  156. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,34 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [6.18.0] - 2026-09-14
9
+
10
+ ### Added
11
+
12
+ - Pure, opt-in comparison/geography/evidence layout helpers in `/adapters`.
13
+ Caller-supplied IDs, payloads and provenance are preserved; helpers only
14
+ arrange components and reject incompatible slot types or duplicate IDs.
15
+ - Native chart/data view switch with keyboard-operable buttons, accessible
16
+ canvas description, localizable chrome and complete point/bubble data.
17
+ - Container-width reflow for read-only composite and nested grids below 640px;
18
+ original desktop coordinates return when space permits.
19
+
20
+ ### Fixed
21
+
22
+ - Align the LLM-facing chart/table/graph catalogue with native renderer/schema
23
+ capabilities, retaining the legacy `QuickchartRegistry` export.
24
+ - Expose existing table search and client paging options in public types and
25
+ carry bubble radii through the chart contract.
26
+ - Prevent unpositioned layout children from creating implicit extra columns.
27
+ - Guard asynchronous chart creation against superseded props and unmounts.
28
+ - Bound chart data scrolling and apply chart/table custom classes.
29
+ - Validate pagination controls and bubble radii at the renderer boundary;
30
+ clamp client pages when data shrinks or an initial page exceeds the row count.
31
+ - Preserve nested grid coordinates throughout editable layouts on small screens.
32
+
33
+ No new runtime dependency, cross-view filtering, host persistence or backend
34
+ wiring. Existing external-renderer trust settings remain unchanged.
35
+
8
36
  ## [6.17.0] - 2026-08-06
9
37
 
10
38
  Map contract parity across the spec, Solid public types, LLM-facing registry,
package/README.md CHANGED
@@ -5,6 +5,52 @@ SolidJS components + chat toolkit for MCP-generated UI. Part of the [MCP UI ecos
5
5
  [![npm version](https://img.shields.io/npm/v/@seed-ship/mcp-ui-solid.svg)](https://www.npmjs.com/package/@seed-ship/mcp-ui-solid)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
+ ## What's New in v6.18.0 — presentation foundations
9
+
10
+ - **Three composition helpers** in `@seed-ship/mcp-ui-solid/adapters`:
11
+ `createComparisonLayout`, `createGeographyLayout`, `createEvidenceLayout`.
12
+ They arrange supplied components without fetching, aggregating or inventing
13
+ data. Component IDs, source links and citation maps are preserved.
14
+ - **Container-responsive grids**: read-only layouts and nested grids stack in
15
+ source order below 640px of container width, including narrow desktop chat
16
+ panels. Desktop positions return when space is available. Editable drag/resize
17
+ mode keeps its explicit grid coordinates.
18
+ - **Native chart/data switch**: Chart.js charts expose an accessible Data view,
19
+ even when rendering succeeds, including point coordinates and bubble radii.
20
+ New chrome strings can be overridden with `MCPUIStringsProvider`.
21
+ - **Catalogue parity**: eight chart kinds, table search/paging controls, and
22
+ schema-supported graph layouts. QuickChart remains a host-only opt-in;
23
+ time axes require a compatible date adapter registered by the host.
24
+
25
+ ```tsx
26
+ import { UIResourceRenderer } from '@seed-ship/mcp-ui-solid'
27
+ import { createComparisonLayout } from '@seed-ship/mcp-ui-solid/adapters'
28
+
29
+ const layout = createComparisonLayout({
30
+ id: 'sales-comparison',
31
+ chart: {
32
+ id: 'sales-chart', type: 'chart',
33
+ params: {
34
+ type: 'bar', title: 'Sales (EUR)',
35
+ data: { labels: ['Lyon', 'Nantes'], datasets: [{ label: 'Sales (EUR)', data: [120, 80] }] },
36
+ },
37
+ },
38
+ table: {
39
+ id: 'sales-table', type: 'table',
40
+ params: {
41
+ columns: [{ key: 'city', label: 'Territory' }, { key: 'sales', label: 'Sales (EUR)' }],
42
+ rows: [{ city: 'Lyon', sales: 120 }, { city: 'Nantes', sales: 80 }],
43
+ },
44
+ },
45
+ })
46
+
47
+ const Comparison = () => <UIResourceRenderer content={layout} />
48
+ ```
49
+
50
+ These helpers are explicitly selected by the caller. They do not consume
51
+ `renderHints` automatically, link selections between views, persist preferences,
52
+ or verify factual claims. See the [MCPs / SolidStart handoff](./docs/briefs/VISUALIZATION-FOUNDATION-2026-09-14.md).
53
+
8
54
  ## What's New in v6.17.0
9
55
 
10
56
  - **Map type parity** — `center` and marker `position` now use the spec's
@@ -666,16 +712,17 @@ onScratchpad: (data) => dispatchScratchpad(data as ScratchpadEvent)
666
712
  const { state, pinned, close } = useScratchpadState()
667
713
  ```
668
714
 
669
- ## Component Renderers (19 types)
715
+ ## Component Renderers (20 types)
670
716
 
671
717
  | Type | Features |
672
718
  |------|----------|
673
- | `chart` | Bar, line, pie, scatter, bubble, polarArea, time-series. Native Chart.js or Quickchart fallback. PNG export. |
719
+ | `chart` | Bar, line, pie, doughnut, radar, scatter, bubble, polarArea. Native Chart.js with Chart/Data switch and PNG export; external QuickChart only on host opt-in. Time axes require a date adapter. |
674
720
  | `table` | Sortable, pagination, virtualization (10K+), CSV/TSV/JSON export |
675
721
  | `metric` | KPI cards with trends and sparklines |
676
722
  | `text` | Markdown via marked.js |
677
723
  | `code` | Syntax highlighting (highlight.js), line numbers, word wrap |
678
724
  | `map` | OpenStreetMap base tiles via Leaflet: markers, clustering, GeoJSON, choropleth, popups, multi-layer, PMTiles |
725
+ | `graph` | Node-link relationships with optional G6; seven schema-supported layouts and layout options |
679
726
  | `form` | 18 field types, conditional fields, persistence, tool call submit |
680
727
  | `modal` | Portal overlay, sizes sm-full, Escape/backdrop close |
681
728
  | `image-gallery` | Grid layout, lightbox, keyboard nav |
@@ -685,7 +732,7 @@ const { state, pinned, close } = useScratchpadState()
685
732
  | `link` | Styled link cards |
686
733
  | `action` | Tool call buttons |
687
734
  | `action-group` | Grouped actions with layout options |
688
- | `grid` | Nested 12-column CSS Grid |
735
+ | `grid` | Nested CSS Grid; read-only layouts stack in narrow containers |
689
736
  | `carousel` | Content carousel |
690
737
  | `artifact` | File download/preview |
691
738
  | `footer` | Metadata display |
@@ -16,4 +16,6 @@
16
16
  export { connectorResultToUILayout, connectorActionsToActionGroup } from './connector';
17
17
  export type { ConnectorResultToUILayoutOptions, ConnectorActionsToActionGroupOptions, } from './connector';
18
18
  export { macroRunToScratchpadState, macroInterrogationToChatPromptConfig } from './macro-run';
19
+ export { createComparisonLayout, createGeographyLayout, createEvidenceLayout, } from './presentation';
20
+ export type { ComparisonLayoutInput, GeographyLayoutInput, EvidenceLayoutInput, PresentationComponent, ChartComponent, TableComponent, MapComponent, MetricComponent, TextComponent, LinkComponent, } from './presentation';
19
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,yBAAyB,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AACvF,YAAY,EACV,gCAAgC,EAChC,oCAAoC,GACrC,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,yBAAyB,EAAE,oCAAoC,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,yBAAyB,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AACvF,YAAY,EACV,gCAAgC,EAChC,oCAAoC,GACrC,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,yBAAyB,EAAE,oCAAoC,EAAE,MAAM,aAAa,CAAC;AAE9F,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,EACb,aAAa,GACd,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const ID_PATTERN = /^[a-z0-9-]+$/;
4
+ const DEFAULT_GRID = { columns: 12, gap: "1rem" };
5
+ function createComparisonLayout(input) {
6
+ var _a, _b;
7
+ assertRecipeId(input.id);
8
+ const inputComponents = [
9
+ input.chart,
10
+ input.table,
11
+ ...input.metrics ?? []
12
+ ];
13
+ if (input.summary) inputComponents.push(input.summary);
14
+ assertUniqueComponentIds(inputComponents);
15
+ assertType(input.chart, "chart", "chart");
16
+ assertType(input.table, "table", "table");
17
+ (_a = input.metrics) == null ? void 0 : _a.forEach((metric, index) => assertType(metric, "metric", `metrics[${index}]`));
18
+ if (input.summary) assertType(input.summary, "text", "summary");
19
+ let row = 1;
20
+ const components = [];
21
+ if (input.summary) {
22
+ components.push(copyForLayout(input.summary, fullWidth(row++)));
23
+ }
24
+ components.push(...placeMetrics(input.metrics ?? [], row));
25
+ row += metricRows(((_b = input.metrics) == null ? void 0 : _b.length) ?? 0);
26
+ components.push(
27
+ copyForLayout(input.chart, { colStart: 1, colSpan: 7, rowStart: row }),
28
+ copyForLayout(input.table, { colStart: 8, colSpan: 5, rowStart: row })
29
+ );
30
+ return makeLayout(input.id, components, input.metadata);
31
+ }
32
+ function createGeographyLayout(input) {
33
+ var _a, _b;
34
+ assertRecipeId(input.id);
35
+ const inputComponents = [
36
+ input.map,
37
+ input.table,
38
+ ...input.metrics ?? []
39
+ ];
40
+ if (input.summary) inputComponents.push(input.summary);
41
+ assertUniqueComponentIds(inputComponents);
42
+ assertType(input.map, "map", "map");
43
+ assertType(input.table, "table", "table");
44
+ (_a = input.metrics) == null ? void 0 : _a.forEach((metric, index) => assertType(metric, "metric", `metrics[${index}]`));
45
+ if (input.summary) assertType(input.summary, "text", "summary");
46
+ let row = 1;
47
+ const components = [];
48
+ if (input.summary) {
49
+ components.push(copyForLayout(input.summary, fullWidth(row++)));
50
+ }
51
+ components.push(...placeMetrics(input.metrics ?? [], row));
52
+ row += metricRows(((_b = input.metrics) == null ? void 0 : _b.length) ?? 0);
53
+ components.push(
54
+ copyForLayout(input.map, { colStart: 1, colSpan: 8, rowStart: row }),
55
+ copyForLayout(input.table, { colStart: 9, colSpan: 4, rowStart: row })
56
+ );
57
+ return makeLayout(input.id, components, input.metadata);
58
+ }
59
+ function createEvidenceLayout(input) {
60
+ var _a;
61
+ assertRecipeId(input.id);
62
+ const pieces = [input.summary, input.table, ...input.sources ?? []];
63
+ assertType(input.summary, "text", "summary");
64
+ assertType(input.table, "table", "table");
65
+ (_a = input.sources) == null ? void 0 : _a.forEach((source, index) => assertType(source, "link", `sources[${index}]`));
66
+ assertUniqueComponentIds(pieces);
67
+ const components = [
68
+ copyForLayout(input.summary, fullWidth(1)),
69
+ copyForLayout(input.table, fullWidth(2)),
70
+ ...placeSources(input.sources ?? [], 3)
71
+ ];
72
+ return makeLayout(input.id, components, input.metadata);
73
+ }
74
+ function makeLayout(id, components, metadata) {
75
+ assertUniqueComponentIds(components);
76
+ return { id, components, grid: { ...DEFAULT_GRID }, ...metadata ? { metadata: { ...metadata } } : {} };
77
+ }
78
+ function fullWidth(rowStart) {
79
+ return { colStart: 1, colSpan: 12, rowStart };
80
+ }
81
+ function placeMetrics(metrics, rowStart) {
82
+ if (metrics.length === 0) return [];
83
+ const span = metrics.length === 1 ? 12 : metrics.length === 2 ? 6 : metrics.length === 3 ? 4 : 3;
84
+ return metrics.map((metric, index) => {
85
+ const column = index % Math.floor(12 / span) * span + 1;
86
+ const row = rowStart + Math.floor(index / Math.floor(12 / span));
87
+ return copyForLayout(metric, { colStart: column, colSpan: span, rowStart: row });
88
+ });
89
+ }
90
+ function metricRows(count) {
91
+ if (count === 0) return 0;
92
+ if (count <= 4) return 1;
93
+ return Math.ceil(count / 4);
94
+ }
95
+ function placeSources(sources, rowStart) {
96
+ return sources.map((source, index) => ({
97
+ ...copyForLayout(source, {
98
+ colStart: index % 3 * 4 + 1,
99
+ colSpan: 4,
100
+ rowStart: rowStart + Math.floor(index / 3)
101
+ })
102
+ }));
103
+ }
104
+ function copyForLayout(component, position) {
105
+ return {
106
+ ...component,
107
+ position: { ...position }
108
+ };
109
+ }
110
+ function assertRecipeId(id) {
111
+ if (typeof id !== "string" || !ID_PATTERN.test(id)) {
112
+ throw new Error("Presentation layout id must contain only lower-case letters, digits and hyphens.");
113
+ }
114
+ }
115
+ function assertType(component, expected, path) {
116
+ if ((component == null ? void 0 : component.type) !== expected) {
117
+ throw new Error(`${path} must be a ${expected} component.`);
118
+ }
119
+ }
120
+ function assertUniqueComponentIds(components) {
121
+ const ids = /* @__PURE__ */ new Set();
122
+ const visit = (component, path) => {
123
+ var _a;
124
+ if (!component || typeof component.id !== "string" || !ID_PATTERN.test(component.id)) {
125
+ throw new Error(`${path} must have a stable lower-case component id.`);
126
+ }
127
+ if (ids.has(component.id)) throw new Error(`Duplicate component id: ${component.id}`);
128
+ ids.add(component.id);
129
+ if (component.type === "grid") {
130
+ const children = (_a = component.params) == null ? void 0 : _a.children;
131
+ if (Array.isArray(children)) {
132
+ children.forEach((child, index) => visit(child, `${path}.children[${index}]`));
133
+ }
134
+ }
135
+ };
136
+ components.forEach((component, index) => visit(component, `components[${index}]`));
137
+ }
138
+ exports.createComparisonLayout = createComparisonLayout;
139
+ exports.createEvidenceLayout = createEvidenceLayout;
140
+ exports.createGeographyLayout = createGeographyLayout;
141
+ //# sourceMappingURL=presentation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation.cjs","sources":["../../src/adapters/presentation.ts"],"sourcesContent":["/**\n * Opt-in, pure presentation recipes for existing MCP-UI components.\n *\n * These helpers arrange caller-supplied components only. They never fetch,\n * aggregate, sort, infer confidence, or manufacture sources: data, params,\n * citations and component metadata remain the caller's responsibility.\n */\n\nimport type {\n ChartComponentParams,\n GridPosition,\n MapComponentParams,\n MetricComponentParams,\n TableComponentParams,\n TextComponentParams,\n UIComponent,\n UILayout,\n} from '../types'\nimport type { LinkComponentParams } from '@seed-ship/mcp-ui-spec'\n\ntype PresentationType = 'chart' | 'table' | 'map' | 'metric' | 'text' | 'link'\n\n/** A recipe owns the eventual grid position, so caller positions are optional. */\nexport type PresentationComponent<T extends PresentationType, Params> = Omit<\n UIComponent,\n 'type' | 'params' | 'position'\n> & {\n type: T\n params: Params\n position?: GridPosition\n}\n\nexport type ChartComponent = PresentationComponent<'chart', ChartComponentParams>\nexport type TableComponent = PresentationComponent<'table', TableComponentParams>\nexport type MapComponent = PresentationComponent<'map', MapComponentParams>\nexport type MetricComponent = PresentationComponent<'metric', MetricComponentParams>\nexport type TextComponent = PresentationComponent<'text', TextComponentParams>\nexport type LinkComponent = PresentationComponent<'link', LinkComponentParams>\n\nexport interface ComparisonLayoutInput {\n /** Stable layout id; lower-case letters, digits and hyphens only. */\n id: string\n chart: ChartComponent\n table: TableComponent\n metrics?: MetricComponent[]\n summary?: TextComponent\n metadata?: UILayout['metadata']\n}\n\nexport interface GeographyLayoutInput {\n /** Stable layout id; lower-case letters, digits and hyphens only. */\n id: string\n map: MapComponent\n table: TableComponent\n metrics?: MetricComponent[]\n summary?: TextComponent\n metadata?: UILayout['metadata']\n}\n\nexport interface EvidenceLayoutInput {\n /** Stable layout id; lower-case letters, digits and hyphens only. */\n id: string\n summary: TextComponent\n table: TableComponent\n sources?: LinkComponent[]\n metadata?: UILayout['metadata']\n}\n\nconst ID_PATTERN = /^[a-z0-9-]+$/\nconst DEFAULT_GRID = { columns: 12, gap: '1rem' } as const\n\n/**\n * Presents a comparison in reading order: optional context and KPIs, then a\n * chart beside the complete table. The supplied rows and chart series keep\n * their original order.\n */\nexport function createComparisonLayout(input: ComparisonLayoutInput): UILayout {\n assertRecipeId(input.id)\n const inputComponents: Array<PresentationComponent<PresentationType, unknown>> = [\n input.chart, input.table, ...(input.metrics ?? []),\n ]\n if (input.summary) inputComponents.push(input.summary)\n assertUniqueComponentIds(inputComponents)\n assertType(input.chart, 'chart', 'chart')\n assertType(input.table, 'table', 'table')\n input.metrics?.forEach((metric, index) => assertType(metric, 'metric', `metrics[${index}]`))\n if (input.summary) assertType(input.summary, 'text', 'summary')\n\n let row = 1\n const components: UIComponent[] = []\n if (input.summary) {\n components.push(copyForLayout(input.summary, fullWidth(row++)))\n }\n components.push(...placeMetrics(input.metrics ?? [], row))\n row += metricRows(input.metrics?.length ?? 0)\n components.push(\n copyForLayout(input.chart, { colStart: 1, colSpan: 7, rowStart: row }),\n copyForLayout(input.table, { colStart: 8, colSpan: 5, rowStart: row })\n )\n return makeLayout(input.id, components, input.metadata)\n}\n\n/**\n * Pairs a geographic overview with the corresponding inspectable table.\n * Map and table data are passed through unchanged, including GeoJSON and\n * citation maps.\n */\nexport function createGeographyLayout(input: GeographyLayoutInput): UILayout {\n assertRecipeId(input.id)\n const inputComponents: Array<PresentationComponent<PresentationType, unknown>> = [\n input.map, input.table, ...(input.metrics ?? []),\n ]\n if (input.summary) inputComponents.push(input.summary)\n assertUniqueComponentIds(inputComponents)\n assertType(input.map, 'map', 'map')\n assertType(input.table, 'table', 'table')\n input.metrics?.forEach((metric, index) => assertType(metric, 'metric', `metrics[${index}]`))\n if (input.summary) assertType(input.summary, 'text', 'summary')\n\n let row = 1\n const components: UIComponent[] = []\n if (input.summary) {\n components.push(copyForLayout(input.summary, fullWidth(row++)))\n }\n components.push(...placeMetrics(input.metrics ?? [], row))\n row += metricRows(input.metrics?.length ?? 0)\n components.push(\n copyForLayout(input.map, { colStart: 1, colSpan: 8, rowStart: row }),\n copyForLayout(input.table, { colStart: 9, colSpan: 4, rowStart: row })\n )\n return makeLayout(input.id, components, input.metadata)\n}\n\n/**\n * Puts the conclusion first, evidence table second, and supplied source links\n * last. Source order is deliberately preserved: this is a presentation recipe,\n * not a confidence or provenance ranking algorithm.\n */\nexport function createEvidenceLayout(input: EvidenceLayoutInput): UILayout {\n assertRecipeId(input.id)\n const pieces = [input.summary, input.table, ...(input.sources ?? [])]\n assertType(input.summary, 'text', 'summary')\n assertType(input.table, 'table', 'table')\n input.sources?.forEach((source, index) => assertType(source, 'link', `sources[${index}]`))\n assertUniqueComponentIds(pieces)\n\n const components: UIComponent[] = [\n copyForLayout(input.summary, fullWidth(1)),\n copyForLayout(input.table, fullWidth(2)),\n ...placeSources(input.sources ?? [], 3),\n ]\n return makeLayout(input.id, components, input.metadata)\n}\n\nfunction makeLayout(id: string, components: UIComponent[], metadata?: UILayout['metadata']): UILayout {\n assertUniqueComponentIds(components)\n return { id, components, grid: { ...DEFAULT_GRID }, ...(metadata ? { metadata: { ...metadata } } : {}) }\n}\n\nfunction fullWidth(rowStart: number): GridPosition {\n return { colStart: 1, colSpan: 12, rowStart }\n}\n\nfunction placeMetrics(metrics: MetricComponent[], rowStart: number): UIComponent[] {\n if (metrics.length === 0) return []\n const span = metrics.length === 1 ? 12 : metrics.length === 2 ? 6 : metrics.length === 3 ? 4 : 3\n return metrics.map((metric, index) => {\n const column = (index % Math.floor(12 / span)) * span + 1\n const row = rowStart + Math.floor(index / Math.floor(12 / span))\n return copyForLayout(metric, { colStart: column, colSpan: span, rowStart: row })\n })\n}\n\nfunction metricRows(count: number): number {\n if (count === 0) return 0\n if (count <= 4) return 1\n return Math.ceil(count / 4)\n}\n\nfunction placeSources(sources: LinkComponent[], rowStart: number): UIComponent[] {\n return sources.map((source, index) => ({\n ...copyForLayout(source, {\n colStart: (index % 3) * 4 + 1,\n colSpan: 4,\n rowStart: rowStart + Math.floor(index / 3),\n }),\n }))\n}\n\nfunction copyForLayout(\n component: PresentationComponent<PresentationType, unknown>,\n position: GridPosition\n): UIComponent {\n return {\n ...component,\n position: { ...position },\n } as UIComponent\n}\n\nfunction assertRecipeId(id: string): void {\n if (typeof id !== 'string' || !ID_PATTERN.test(id)) {\n throw new Error('Presentation layout id must contain only lower-case letters, digits and hyphens.')\n }\n}\n\nfunction assertType(component: { type: string }, expected: PresentationType, path: string): void {\n if (component?.type !== expected) {\n throw new Error(`${path} must be a ${expected} component.`)\n }\n}\n\n/** Validates source IDs recursively so nested GridRenderer children stay key-safe. */\nfunction assertUniqueComponentIds(components: Array<UIComponent | PresentationComponent<PresentationType, unknown>>): void {\n const ids = new Set<string>()\n const visit = (component: { id: unknown; type?: unknown; params?: unknown }, path: string): void => {\n if (!component || typeof component.id !== 'string' || !ID_PATTERN.test(component.id)) {\n throw new Error(`${path} must have a stable lower-case component id.`)\n }\n if (ids.has(component.id)) throw new Error(`Duplicate component id: ${component.id}`)\n ids.add(component.id)\n if (component.type === 'grid') {\n const children = (component.params as { children?: unknown })?.children\n if (Array.isArray(children)) {\n children.forEach((child, index) => visit(child as { id: unknown; type?: unknown; params?: unknown }, `${path}.children[${index}]`))\n }\n }\n }\n components.forEach((component, index) => visit(component, `components[${index}]`))\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Opt-in, pure presentation recipes for existing MCP-UI components.
3
+ *
4
+ * These helpers arrange caller-supplied components only. They never fetch,
5
+ * aggregate, sort, infer confidence, or manufacture sources: data, params,
6
+ * citations and component metadata remain the caller's responsibility.
7
+ */
8
+ import type { ChartComponentParams, GridPosition, MapComponentParams, MetricComponentParams, TableComponentParams, TextComponentParams, UIComponent, UILayout } from '../types';
9
+ import type { LinkComponentParams } from '@seed-ship/mcp-ui-spec';
10
+ type PresentationType = 'chart' | 'table' | 'map' | 'metric' | 'text' | 'link';
11
+ /** A recipe owns the eventual grid position, so caller positions are optional. */
12
+ export type PresentationComponent<T extends PresentationType, Params> = Omit<UIComponent, 'type' | 'params' | 'position'> & {
13
+ type: T;
14
+ params: Params;
15
+ position?: GridPosition;
16
+ };
17
+ export type ChartComponent = PresentationComponent<'chart', ChartComponentParams>;
18
+ export type TableComponent = PresentationComponent<'table', TableComponentParams>;
19
+ export type MapComponent = PresentationComponent<'map', MapComponentParams>;
20
+ export type MetricComponent = PresentationComponent<'metric', MetricComponentParams>;
21
+ export type TextComponent = PresentationComponent<'text', TextComponentParams>;
22
+ export type LinkComponent = PresentationComponent<'link', LinkComponentParams>;
23
+ export interface ComparisonLayoutInput {
24
+ /** Stable layout id; lower-case letters, digits and hyphens only. */
25
+ id: string;
26
+ chart: ChartComponent;
27
+ table: TableComponent;
28
+ metrics?: MetricComponent[];
29
+ summary?: TextComponent;
30
+ metadata?: UILayout['metadata'];
31
+ }
32
+ export interface GeographyLayoutInput {
33
+ /** Stable layout id; lower-case letters, digits and hyphens only. */
34
+ id: string;
35
+ map: MapComponent;
36
+ table: TableComponent;
37
+ metrics?: MetricComponent[];
38
+ summary?: TextComponent;
39
+ metadata?: UILayout['metadata'];
40
+ }
41
+ export interface EvidenceLayoutInput {
42
+ /** Stable layout id; lower-case letters, digits and hyphens only. */
43
+ id: string;
44
+ summary: TextComponent;
45
+ table: TableComponent;
46
+ sources?: LinkComponent[];
47
+ metadata?: UILayout['metadata'];
48
+ }
49
+ /**
50
+ * Presents a comparison in reading order: optional context and KPIs, then a
51
+ * chart beside the complete table. The supplied rows and chart series keep
52
+ * their original order.
53
+ */
54
+ export declare function createComparisonLayout(input: ComparisonLayoutInput): UILayout;
55
+ /**
56
+ * Pairs a geographic overview with the corresponding inspectable table.
57
+ * Map and table data are passed through unchanged, including GeoJSON and
58
+ * citation maps.
59
+ */
60
+ export declare function createGeographyLayout(input: GeographyLayoutInput): UILayout;
61
+ /**
62
+ * Puts the conclusion first, evidence table second, and supplied source links
63
+ * last. Source order is deliberately preserved: this is a presentation recipe,
64
+ * not a confidence or provenance ranking algorithm.
65
+ */
66
+ export declare function createEvidenceLayout(input: EvidenceLayoutInput): UILayout;
67
+ export {};
68
+ //# sourceMappingURL=presentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../src/adapters/presentation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,QAAQ,EACT,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEjE,KAAK,gBAAgB,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAA;AAE9E,kFAAkF;AAClF,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,gBAAgB,EAAE,MAAM,IAAI,IAAI,CAC1E,WAAW,EACX,MAAM,GAAG,QAAQ,GAAG,UAAU,CAC/B,GAAG;IACF,IAAI,EAAE,CAAC,CAAA;IACP,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAA;AACjF,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAA;AACjF,MAAM,MAAM,YAAY,GAAG,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAA;AAC3E,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAA;AACpF,MAAM,MAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;AAC9E,MAAM,MAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;AAE9E,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,cAAc,CAAA;IACrB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAA;IAC3B,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,QAAQ,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,YAAY,CAAA;IACjB,KAAK,EAAE,cAAc,CAAA;IACrB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAA;IAC3B,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,QAAQ,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,aAAa,CAAA;IACtB,KAAK,EAAE,cAAc,CAAA;IACrB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;IACzB,QAAQ,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAA;CAChC;AAKD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,GAAG,QAAQ,CAwB7E;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,oBAAoB,GAAG,QAAQ,CAwB3E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,GAAG,QAAQ,CAczE"}
@@ -0,0 +1,141 @@
1
+ const ID_PATTERN = /^[a-z0-9-]+$/;
2
+ const DEFAULT_GRID = { columns: 12, gap: "1rem" };
3
+ function createComparisonLayout(input) {
4
+ var _a, _b;
5
+ assertRecipeId(input.id);
6
+ const inputComponents = [
7
+ input.chart,
8
+ input.table,
9
+ ...input.metrics ?? []
10
+ ];
11
+ if (input.summary) inputComponents.push(input.summary);
12
+ assertUniqueComponentIds(inputComponents);
13
+ assertType(input.chart, "chart", "chart");
14
+ assertType(input.table, "table", "table");
15
+ (_a = input.metrics) == null ? void 0 : _a.forEach((metric, index) => assertType(metric, "metric", `metrics[${index}]`));
16
+ if (input.summary) assertType(input.summary, "text", "summary");
17
+ let row = 1;
18
+ const components = [];
19
+ if (input.summary) {
20
+ components.push(copyForLayout(input.summary, fullWidth(row++)));
21
+ }
22
+ components.push(...placeMetrics(input.metrics ?? [], row));
23
+ row += metricRows(((_b = input.metrics) == null ? void 0 : _b.length) ?? 0);
24
+ components.push(
25
+ copyForLayout(input.chart, { colStart: 1, colSpan: 7, rowStart: row }),
26
+ copyForLayout(input.table, { colStart: 8, colSpan: 5, rowStart: row })
27
+ );
28
+ return makeLayout(input.id, components, input.metadata);
29
+ }
30
+ function createGeographyLayout(input) {
31
+ var _a, _b;
32
+ assertRecipeId(input.id);
33
+ const inputComponents = [
34
+ input.map,
35
+ input.table,
36
+ ...input.metrics ?? []
37
+ ];
38
+ if (input.summary) inputComponents.push(input.summary);
39
+ assertUniqueComponentIds(inputComponents);
40
+ assertType(input.map, "map", "map");
41
+ assertType(input.table, "table", "table");
42
+ (_a = input.metrics) == null ? void 0 : _a.forEach((metric, index) => assertType(metric, "metric", `metrics[${index}]`));
43
+ if (input.summary) assertType(input.summary, "text", "summary");
44
+ let row = 1;
45
+ const components = [];
46
+ if (input.summary) {
47
+ components.push(copyForLayout(input.summary, fullWidth(row++)));
48
+ }
49
+ components.push(...placeMetrics(input.metrics ?? [], row));
50
+ row += metricRows(((_b = input.metrics) == null ? void 0 : _b.length) ?? 0);
51
+ components.push(
52
+ copyForLayout(input.map, { colStart: 1, colSpan: 8, rowStart: row }),
53
+ copyForLayout(input.table, { colStart: 9, colSpan: 4, rowStart: row })
54
+ );
55
+ return makeLayout(input.id, components, input.metadata);
56
+ }
57
+ function createEvidenceLayout(input) {
58
+ var _a;
59
+ assertRecipeId(input.id);
60
+ const pieces = [input.summary, input.table, ...input.sources ?? []];
61
+ assertType(input.summary, "text", "summary");
62
+ assertType(input.table, "table", "table");
63
+ (_a = input.sources) == null ? void 0 : _a.forEach((source, index) => assertType(source, "link", `sources[${index}]`));
64
+ assertUniqueComponentIds(pieces);
65
+ const components = [
66
+ copyForLayout(input.summary, fullWidth(1)),
67
+ copyForLayout(input.table, fullWidth(2)),
68
+ ...placeSources(input.sources ?? [], 3)
69
+ ];
70
+ return makeLayout(input.id, components, input.metadata);
71
+ }
72
+ function makeLayout(id, components, metadata) {
73
+ assertUniqueComponentIds(components);
74
+ return { id, components, grid: { ...DEFAULT_GRID }, ...metadata ? { metadata: { ...metadata } } : {} };
75
+ }
76
+ function fullWidth(rowStart) {
77
+ return { colStart: 1, colSpan: 12, rowStart };
78
+ }
79
+ function placeMetrics(metrics, rowStart) {
80
+ if (metrics.length === 0) return [];
81
+ const span = metrics.length === 1 ? 12 : metrics.length === 2 ? 6 : metrics.length === 3 ? 4 : 3;
82
+ return metrics.map((metric, index) => {
83
+ const column = index % Math.floor(12 / span) * span + 1;
84
+ const row = rowStart + Math.floor(index / Math.floor(12 / span));
85
+ return copyForLayout(metric, { colStart: column, colSpan: span, rowStart: row });
86
+ });
87
+ }
88
+ function metricRows(count) {
89
+ if (count === 0) return 0;
90
+ if (count <= 4) return 1;
91
+ return Math.ceil(count / 4);
92
+ }
93
+ function placeSources(sources, rowStart) {
94
+ return sources.map((source, index) => ({
95
+ ...copyForLayout(source, {
96
+ colStart: index % 3 * 4 + 1,
97
+ colSpan: 4,
98
+ rowStart: rowStart + Math.floor(index / 3)
99
+ })
100
+ }));
101
+ }
102
+ function copyForLayout(component, position) {
103
+ return {
104
+ ...component,
105
+ position: { ...position }
106
+ };
107
+ }
108
+ function assertRecipeId(id) {
109
+ if (typeof id !== "string" || !ID_PATTERN.test(id)) {
110
+ throw new Error("Presentation layout id must contain only lower-case letters, digits and hyphens.");
111
+ }
112
+ }
113
+ function assertType(component, expected, path) {
114
+ if ((component == null ? void 0 : component.type) !== expected) {
115
+ throw new Error(`${path} must be a ${expected} component.`);
116
+ }
117
+ }
118
+ function assertUniqueComponentIds(components) {
119
+ const ids = /* @__PURE__ */ new Set();
120
+ const visit = (component, path) => {
121
+ var _a;
122
+ if (!component || typeof component.id !== "string" || !ID_PATTERN.test(component.id)) {
123
+ throw new Error(`${path} must have a stable lower-case component id.`);
124
+ }
125
+ if (ids.has(component.id)) throw new Error(`Duplicate component id: ${component.id}`);
126
+ ids.add(component.id);
127
+ if (component.type === "grid") {
128
+ const children = (_a = component.params) == null ? void 0 : _a.children;
129
+ if (Array.isArray(children)) {
130
+ children.forEach((child, index) => visit(child, `${path}.children[${index}]`));
131
+ }
132
+ }
133
+ };
134
+ components.forEach((component, index) => visit(component, `components[${index}]`));
135
+ }
136
+ export {
137
+ createComparisonLayout,
138
+ createEvidenceLayout,
139
+ createGeographyLayout
140
+ };
141
+ //# sourceMappingURL=presentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation.js","sources":["../../src/adapters/presentation.ts"],"sourcesContent":["/**\n * Opt-in, pure presentation recipes for existing MCP-UI components.\n *\n * These helpers arrange caller-supplied components only. They never fetch,\n * aggregate, sort, infer confidence, or manufacture sources: data, params,\n * citations and component metadata remain the caller's responsibility.\n */\n\nimport type {\n ChartComponentParams,\n GridPosition,\n MapComponentParams,\n MetricComponentParams,\n TableComponentParams,\n TextComponentParams,\n UIComponent,\n UILayout,\n} from '../types'\nimport type { LinkComponentParams } from '@seed-ship/mcp-ui-spec'\n\ntype PresentationType = 'chart' | 'table' | 'map' | 'metric' | 'text' | 'link'\n\n/** A recipe owns the eventual grid position, so caller positions are optional. */\nexport type PresentationComponent<T extends PresentationType, Params> = Omit<\n UIComponent,\n 'type' | 'params' | 'position'\n> & {\n type: T\n params: Params\n position?: GridPosition\n}\n\nexport type ChartComponent = PresentationComponent<'chart', ChartComponentParams>\nexport type TableComponent = PresentationComponent<'table', TableComponentParams>\nexport type MapComponent = PresentationComponent<'map', MapComponentParams>\nexport type MetricComponent = PresentationComponent<'metric', MetricComponentParams>\nexport type TextComponent = PresentationComponent<'text', TextComponentParams>\nexport type LinkComponent = PresentationComponent<'link', LinkComponentParams>\n\nexport interface ComparisonLayoutInput {\n /** Stable layout id; lower-case letters, digits and hyphens only. */\n id: string\n chart: ChartComponent\n table: TableComponent\n metrics?: MetricComponent[]\n summary?: TextComponent\n metadata?: UILayout['metadata']\n}\n\nexport interface GeographyLayoutInput {\n /** Stable layout id; lower-case letters, digits and hyphens only. */\n id: string\n map: MapComponent\n table: TableComponent\n metrics?: MetricComponent[]\n summary?: TextComponent\n metadata?: UILayout['metadata']\n}\n\nexport interface EvidenceLayoutInput {\n /** Stable layout id; lower-case letters, digits and hyphens only. */\n id: string\n summary: TextComponent\n table: TableComponent\n sources?: LinkComponent[]\n metadata?: UILayout['metadata']\n}\n\nconst ID_PATTERN = /^[a-z0-9-]+$/\nconst DEFAULT_GRID = { columns: 12, gap: '1rem' } as const\n\n/**\n * Presents a comparison in reading order: optional context and KPIs, then a\n * chart beside the complete table. The supplied rows and chart series keep\n * their original order.\n */\nexport function createComparisonLayout(input: ComparisonLayoutInput): UILayout {\n assertRecipeId(input.id)\n const inputComponents: Array<PresentationComponent<PresentationType, unknown>> = [\n input.chart, input.table, ...(input.metrics ?? []),\n ]\n if (input.summary) inputComponents.push(input.summary)\n assertUniqueComponentIds(inputComponents)\n assertType(input.chart, 'chart', 'chart')\n assertType(input.table, 'table', 'table')\n input.metrics?.forEach((metric, index) => assertType(metric, 'metric', `metrics[${index}]`))\n if (input.summary) assertType(input.summary, 'text', 'summary')\n\n let row = 1\n const components: UIComponent[] = []\n if (input.summary) {\n components.push(copyForLayout(input.summary, fullWidth(row++)))\n }\n components.push(...placeMetrics(input.metrics ?? [], row))\n row += metricRows(input.metrics?.length ?? 0)\n components.push(\n copyForLayout(input.chart, { colStart: 1, colSpan: 7, rowStart: row }),\n copyForLayout(input.table, { colStart: 8, colSpan: 5, rowStart: row })\n )\n return makeLayout(input.id, components, input.metadata)\n}\n\n/**\n * Pairs a geographic overview with the corresponding inspectable table.\n * Map and table data are passed through unchanged, including GeoJSON and\n * citation maps.\n */\nexport function createGeographyLayout(input: GeographyLayoutInput): UILayout {\n assertRecipeId(input.id)\n const inputComponents: Array<PresentationComponent<PresentationType, unknown>> = [\n input.map, input.table, ...(input.metrics ?? []),\n ]\n if (input.summary) inputComponents.push(input.summary)\n assertUniqueComponentIds(inputComponents)\n assertType(input.map, 'map', 'map')\n assertType(input.table, 'table', 'table')\n input.metrics?.forEach((metric, index) => assertType(metric, 'metric', `metrics[${index}]`))\n if (input.summary) assertType(input.summary, 'text', 'summary')\n\n let row = 1\n const components: UIComponent[] = []\n if (input.summary) {\n components.push(copyForLayout(input.summary, fullWidth(row++)))\n }\n components.push(...placeMetrics(input.metrics ?? [], row))\n row += metricRows(input.metrics?.length ?? 0)\n components.push(\n copyForLayout(input.map, { colStart: 1, colSpan: 8, rowStart: row }),\n copyForLayout(input.table, { colStart: 9, colSpan: 4, rowStart: row })\n )\n return makeLayout(input.id, components, input.metadata)\n}\n\n/**\n * Puts the conclusion first, evidence table second, and supplied source links\n * last. Source order is deliberately preserved: this is a presentation recipe,\n * not a confidence or provenance ranking algorithm.\n */\nexport function createEvidenceLayout(input: EvidenceLayoutInput): UILayout {\n assertRecipeId(input.id)\n const pieces = [input.summary, input.table, ...(input.sources ?? [])]\n assertType(input.summary, 'text', 'summary')\n assertType(input.table, 'table', 'table')\n input.sources?.forEach((source, index) => assertType(source, 'link', `sources[${index}]`))\n assertUniqueComponentIds(pieces)\n\n const components: UIComponent[] = [\n copyForLayout(input.summary, fullWidth(1)),\n copyForLayout(input.table, fullWidth(2)),\n ...placeSources(input.sources ?? [], 3),\n ]\n return makeLayout(input.id, components, input.metadata)\n}\n\nfunction makeLayout(id: string, components: UIComponent[], metadata?: UILayout['metadata']): UILayout {\n assertUniqueComponentIds(components)\n return { id, components, grid: { ...DEFAULT_GRID }, ...(metadata ? { metadata: { ...metadata } } : {}) }\n}\n\nfunction fullWidth(rowStart: number): GridPosition {\n return { colStart: 1, colSpan: 12, rowStart }\n}\n\nfunction placeMetrics(metrics: MetricComponent[], rowStart: number): UIComponent[] {\n if (metrics.length === 0) return []\n const span = metrics.length === 1 ? 12 : metrics.length === 2 ? 6 : metrics.length === 3 ? 4 : 3\n return metrics.map((metric, index) => {\n const column = (index % Math.floor(12 / span)) * span + 1\n const row = rowStart + Math.floor(index / Math.floor(12 / span))\n return copyForLayout(metric, { colStart: column, colSpan: span, rowStart: row })\n })\n}\n\nfunction metricRows(count: number): number {\n if (count === 0) return 0\n if (count <= 4) return 1\n return Math.ceil(count / 4)\n}\n\nfunction placeSources(sources: LinkComponent[], rowStart: number): UIComponent[] {\n return sources.map((source, index) => ({\n ...copyForLayout(source, {\n colStart: (index % 3) * 4 + 1,\n colSpan: 4,\n rowStart: rowStart + Math.floor(index / 3),\n }),\n }))\n}\n\nfunction copyForLayout(\n component: PresentationComponent<PresentationType, unknown>,\n position: GridPosition\n): UIComponent {\n return {\n ...component,\n position: { ...position },\n } as UIComponent\n}\n\nfunction assertRecipeId(id: string): void {\n if (typeof id !== 'string' || !ID_PATTERN.test(id)) {\n throw new Error('Presentation layout id must contain only lower-case letters, digits and hyphens.')\n }\n}\n\nfunction assertType(component: { type: string }, expected: PresentationType, path: string): void {\n if (component?.type !== expected) {\n throw new Error(`${path} must be a ${expected} component.`)\n }\n}\n\n/** Validates source IDs recursively so nested GridRenderer children stay key-safe. */\nfunction assertUniqueComponentIds(components: Array<UIComponent | PresentationComponent<PresentationType, unknown>>): void {\n const ids = new Set<string>()\n const visit = (component: { id: unknown; type?: unknown; params?: unknown }, path: string): void => {\n if (!component || typeof component.id !== 'string' || !ID_PATTERN.test(component.id)) {\n throw new Error(`${path} must have a stable lower-case component id.`)\n }\n if (ids.has(component.id)) throw new Error(`Duplicate component id: ${component.id}`)\n ids.add(component.id)\n if (component.type === 'grid') {\n const children = (component.params as { children?: unknown })?.children\n if (Array.isArray(children)) {\n children.forEach((child, index) => visit(child as { id: unknown; type?: unknown; params?: unknown }, `${path}.children[${index}]`))\n }\n }\n }\n components.forEach((component, index) => visit(component, `components[${index}]`))\n}\n"],"names":[],"mappings":"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"}
package/dist/adapters.cjs CHANGED
@@ -2,8 +2,12 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const connector = require("./adapters/connector.cjs");
4
4
  const macroRun = require("./adapters/macro-run.cjs");
5
+ const presentation = require("./adapters/presentation.cjs");
5
6
  exports.connectorActionsToActionGroup = connector.connectorActionsToActionGroup;
6
7
  exports.connectorResultToUILayout = connector.connectorResultToUILayout;
7
8
  exports.macroInterrogationToChatPromptConfig = macroRun.macroInterrogationToChatPromptConfig;
8
9
  exports.macroRunToScratchpadState = macroRun.macroRunToScratchpadState;
10
+ exports.createComparisonLayout = presentation.createComparisonLayout;
11
+ exports.createEvidenceLayout = presentation.createEvidenceLayout;
12
+ exports.createGeographyLayout = presentation.createGeographyLayout;
9
13
  //# sourceMappingURL=adapters.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapters.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
1
+ {"version":3,"file":"adapters.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
@@ -16,4 +16,6 @@
16
16
  export { connectorResultToUILayout, connectorActionsToActionGroup } from './connector';
17
17
  export type { ConnectorResultToUILayoutOptions, ConnectorActionsToActionGroupOptions, } from './connector';
18
18
  export { macroRunToScratchpadState, macroInterrogationToChatPromptConfig } from './macro-run';
19
+ export { createComparisonLayout, createGeographyLayout, createEvidenceLayout, } from './presentation';
20
+ export type { ComparisonLayoutInput, GeographyLayoutInput, EvidenceLayoutInput, PresentationComponent, ChartComponent, TableComponent, MapComponent, MetricComponent, TextComponent, LinkComponent, } from './presentation';
19
21
  //# sourceMappingURL=index.d.ts.map
@@ -16,4 +16,6 @@
16
16
  export { connectorResultToUILayout, connectorActionsToActionGroup } from './connector';
17
17
  export type { ConnectorResultToUILayoutOptions, ConnectorActionsToActionGroupOptions, } from './connector';
18
18
  export { macroRunToScratchpadState, macroInterrogationToChatPromptConfig } from './macro-run';
19
+ export { createComparisonLayout, createGeographyLayout, createEvidenceLayout, } from './presentation';
20
+ export type { ComparisonLayoutInput, GeographyLayoutInput, EvidenceLayoutInput, PresentationComponent, ChartComponent, TableComponent, MapComponent, MetricComponent, TextComponent, LinkComponent, } from './presentation';
19
21
  //# sourceMappingURL=index.d.ts.map
package/dist/adapters.js CHANGED
@@ -1,8 +1,12 @@
1
1
  import { connectorActionsToActionGroup, connectorResultToUILayout } from "./adapters/connector.js";
2
2
  import { macroInterrogationToChatPromptConfig, macroRunToScratchpadState } from "./adapters/macro-run.js";
3
+ import { createComparisonLayout, createEvidenceLayout, createGeographyLayout } from "./adapters/presentation.js";
3
4
  export {
4
5
  connectorActionsToActionGroup,
5
6
  connectorResultToUILayout,
7
+ createComparisonLayout,
8
+ createEvidenceLayout,
9
+ createGeographyLayout,
6
10
  macroInterrogationToChatPromptConfig,
7
11
  macroRunToScratchpadState
8
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"adapters.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
1
+ {"version":3,"file":"adapters.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}