@seed-ship/mcp-ui-solid 6.22.0 → 6.24.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 +219 -0
- package/README.md +209 -2
- package/dist/components/ChartJSRenderer.cjs +192 -66
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +192 -66
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/DegradedFallback.cjs +34 -2
- package/dist/components/DegradedFallback.cjs.map +1 -1
- package/dist/components/DegradedFallback.d.ts +7 -0
- package/dist/components/DegradedFallback.d.ts.map +1 -1
- package/dist/components/DegradedFallback.js +34 -2
- package/dist/components/DegradedFallback.js.map +1 -1
- package/dist/components/MissingValue.cjs +43 -0
- package/dist/components/MissingValue.cjs.map +1 -0
- package/dist/components/MissingValue.d.ts +27 -0
- package/dist/components/MissingValue.d.ts.map +1 -0
- package/dist/components/MissingValue.js +43 -0
- package/dist/components/MissingValue.js.map +1 -0
- package/dist/components/UIResourceRenderer.cjs +250 -202
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts +2 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +250 -202
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/chart-data-table.cjs +30 -5
- package/dist/components/chart-data-table.cjs.map +1 -1
- package/dist/components/chart-data-table.d.ts +18 -1
- package/dist/components/chart-data-table.d.ts.map +1 -1
- package/dist/components/chart-data-table.js +30 -5
- package/dist/components/chart-data-table.js.map +1 -1
- package/dist/components/chart-missing-plugin.cjs +194 -0
- package/dist/components/chart-missing-plugin.cjs.map +1 -0
- package/dist/components/chart-missing-plugin.d.ts +127 -0
- package/dist/components/chart-missing-plugin.d.ts.map +1 -0
- package/dist/components/chart-missing-plugin.js +194 -0
- package/dist/components/chart-missing-plugin.js.map +1 -0
- package/dist/context/MCPUIConfigContext.cjs.map +1 -1
- package/dist/context/MCPUIConfigContext.d.ts +57 -28
- package/dist/context/MCPUIConfigContext.d.ts.map +1 -1
- package/dist/context/MCPUIConfigContext.js.map +1 -1
- package/dist/context/MCPUIMathContext.cjs +19 -0
- package/dist/context/MCPUIMathContext.cjs.map +1 -0
- package/dist/context/MCPUIMathContext.d.ts +18 -0
- package/dist/context/MCPUIMathContext.d.ts.map +1 -0
- package/dist/context/MCPUIMathContext.js +19 -0
- package/dist/context/MCPUIMathContext.js.map +1 -0
- package/dist/context/MCPUIStringsContext.cjs +12 -1
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +62 -0
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +12 -1
- package/dist/context/MCPUIStringsContext.js.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/katex.cjs +23 -0
- package/dist/plugins/katex.cjs.map +1 -0
- package/dist/plugins/katex.d.cts +7 -0
- package/dist/plugins/katex.d.ts +7 -0
- package/dist/plugins/katex.d.ts.map +1 -0
- package/dist/plugins/katex.js +23 -0
- package/dist/plugins/katex.js.map +1 -0
- package/dist/services/component-registry.cjs +9 -2
- package/dist/services/component-registry.cjs.map +1 -1
- package/dist/services/component-registry.d.ts.map +1 -1
- package/dist/services/component-registry.js +9 -2
- package/dist/services/component-registry.js.map +1 -1
- package/dist/services/validation.cjs +31 -8
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +31 -8
- package/dist/services/validation.js.map +1 -1
- package/dist/types/index.d.ts +14 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/degraded-projections.cjs +19 -3
- package/dist/utils/degraded-projections.cjs.map +1 -1
- package/dist/utils/degraded-projections.d.ts +22 -2
- package/dist/utils/degraded-projections.d.ts.map +1 -1
- package/dist/utils/degraded-projections.js +19 -3
- package/dist/utils/degraded-projections.js.map +1 -1
- package/dist/utils/iframe-coep.cjs.map +1 -1
- package/dist/utils/iframe-coep.d.ts +7 -6
- package/dist/utils/iframe-coep.d.ts.map +1 -1
- package/dist/utils/iframe-coep.js.map +1 -1
- package/dist/utils/math-markdown.cjs +240 -0
- package/dist/utils/math-markdown.cjs.map +1 -0
- package/dist/utils/math-markdown.d.ts +16 -0
- package/dist/utils/math-markdown.d.ts.map +1 -0
- package/dist/utils/math-markdown.js +240 -0
- package/dist/utils/math-markdown.js.map +1 -0
- package/dist/utils/missing-value.cjs +60 -0
- package/dist/utils/missing-value.cjs.map +1 -0
- package/dist/utils/missing-value.d.ts +79 -0
- package/dist/utils/missing-value.d.ts.map +1 -0
- package/dist/utils/missing-value.js +60 -0
- package/dist/utils/missing-value.js.map +1 -0
- package/package.json +23 -4
- package/src/components/ChartJSRenderer.tsx +159 -6
- package/src/components/DegradedFallback.tsx +24 -2
- package/src/components/MissingValue.tsx +61 -0
- package/src/components/UIResourceRenderer.tsx +64 -10
- package/src/components/chart-data-table.ts +50 -6
- package/src/components/chart-missing-plugin.ts +334 -0
- package/src/context/MCPUIConfigContext.tsx +57 -28
- package/src/context/MCPUIMathContext.tsx +32 -0
- package/src/context/MCPUIStringsContext.tsx +76 -0
- package/src/index.ts +4 -0
- package/src/plugins/katex.ts +25 -0
- package/src/services/component-registry.ts +10 -2
- package/src/services/validation.ts +44 -9
- package/src/types/index.ts +13 -1
- package/src/utils/degraded-projections.ts +44 -4
- package/src/utils/iframe-coep.ts +7 -6
- package/src/utils/math-markdown.ts +222 -0
- package/src/utils/missing-value.ts +127 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,220 @@ 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.24.0] - 2026-10-03
|
|
9
|
+
|
|
10
|
+
Explicit missing values in charts and tables, and a unit per chart — lot 1 of
|
|
11
|
+
the GeoAI display brief (`deposium_geoai/docs/handoffs/2026-10-03-mcp-ui-geoai-display-brief.md`).
|
|
12
|
+
Released with `@seed-ship/mcp-ui-spec` 5.7.0, whose chart schema accepts both;
|
|
13
|
+
the dependency floor moves to `^5.7.0`.
|
|
14
|
+
|
|
15
|
+
### The rule
|
|
16
|
+
|
|
17
|
+
Absence is never zero. A `null` keeps its slot — its label stays on the axis,
|
|
18
|
+
its row stays in the table — and every view marks it, visibly and for screen
|
|
19
|
+
readers. Until now `validateComponent` refused any chart carrying a `null`, so
|
|
20
|
+
a host that drops invalid components (Deposium's chat does) showed nothing.
|
|
21
|
+
|
|
22
|
+
Only an explicit entry is a missing value: `null` (or a non-finite number, or a
|
|
23
|
+
point whose `y` is one). A dataset with no entry at all (`data: []`) is not —
|
|
24
|
+
it renders exactly as it did in 6.23.0.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **Charts accept `null`** in line, bar, radar, scatter and bubble datasets,
|
|
29
|
+
as a number slot or as a point's `y`:
|
|
30
|
+
- a line or a radar breaks at the missing value: `spanGaps: false` is set on
|
|
31
|
+
every dataset of a chart that has one, so nothing joins the neighbours,
|
|
32
|
+
and the date stays on the axis;
|
|
33
|
+
- a missing bar is drawn as a dashed outline at the baseline, so it cannot
|
|
34
|
+
be read as a zero bar (Chart.js draws nothing for both). Stacked or
|
|
35
|
+
overlaid bars get no outline — their baseline belongs to the series below,
|
|
36
|
+
so an outline there would point at the wrong series — and their note says
|
|
37
|
+
the values are not plotted;
|
|
38
|
+
- scatter and bubble charts leave the point out;
|
|
39
|
+
- a series whose every entry is missing keeps its legend entry, marked
|
|
40
|
+
`chartLegendNoData` ("(no data)"), and a chart with nothing to plot says
|
|
41
|
+
so in its plot area (`chartNoData`);
|
|
42
|
+
- a note under the chart explains how this chart shows a missing value
|
|
43
|
+
(`chartMissingGaps`, `chartMissingBars`, `chartMissingPoints`), shown when
|
|
44
|
+
a reader can actually see the mark, and names the series with no data
|
|
45
|
+
(`chartSeriesNoData`, joined with `Intl.ListFormat` in the strings
|
|
46
|
+
`locale`). The canvas's `aria-describedby` includes it. DOM hooks:
|
|
47
|
+
`[data-mcp-chart-notes]` and
|
|
48
|
+
`[data-mcp-chart-note="gaps|bars|omitted|no-data"]`;
|
|
49
|
+
- a tooltip names a missing bar (`missingValue`) instead of printing `0`.
|
|
50
|
+
|
|
51
|
+
Pie, doughnut and polar-area charts refuse `null`, as a bare value or as a
|
|
52
|
+
point's `y`, because Chart.js parses a missing share as `0` and would draw
|
|
53
|
+
every other share wrong. `validateChartComponent` reports
|
|
54
|
+
`MISSING_VALUE_UNSUPPORTED`. If a host bypasses validation, the renderer
|
|
55
|
+
shows its data table with `chartMissingUnsupported` instead of a misleading
|
|
56
|
+
chart.
|
|
57
|
+
- **`unit`** on chart params: the value-axis title (bar, line, scatter and
|
|
58
|
+
bubble, unless `options.scales` already sets one), the tooltip value
|
|
59
|
+
(`chartValueWithUnit`, except on scatter and bubble, whose value is a pair)
|
|
60
|
+
and the column headers of the data view and of the degraded table
|
|
61
|
+
(`chartLabelWithUnit`). `validateChartComponent` reports `INVALID_UNIT` for
|
|
62
|
+
a non-string unit or one longer than 32 characters; an empty string is
|
|
63
|
+
tolerated and means "no unit".
|
|
64
|
+
- **Tables.** A cell that already displayed as `-` — `null`, `undefined`, an
|
|
65
|
+
empty or whitespace-only string, `"undefined"` (after the backend's
|
|
66
|
+
`"X – undefined"` debris is stripped) or a literal `-` — is now muted,
|
|
67
|
+
hidden from assistive technology and followed by a visually-hidden
|
|
68
|
+
`missingValue`. A legend (`missingValueLegend`, `[data-mcp-missing-legend]`)
|
|
69
|
+
follows any table with such a cell. It is computed on every row, so it does
|
|
70
|
+
not flicker while paging. Missing cells sort last in both directions (an
|
|
71
|
+
empty string no longer sorts as `0`), a numeric column is detected from its
|
|
72
|
+
first present value, and search never matches a missing cell.
|
|
73
|
+
- **The chart data view and the degraded tables** mark missing cells the same
|
|
74
|
+
way, under the same legend. `chartToDataTable` and `chartToDegradedTable`
|
|
75
|
+
return an extra `missing` matrix shaped like `rows`, which still hold `''`.
|
|
76
|
+
One exception: the degraded table prints point data (scatter, bubble,
|
|
77
|
+
`{x, y}` series) as JSON, where `"y":null` reads as such, and does not mark
|
|
78
|
+
it. `DegradedFallback` takes an optional `missing` prop; the graph and map
|
|
79
|
+
degraded tables do not change.
|
|
80
|
+
- Ten `MCPUIStrings` keys (275 → 285), English defaults, French in the README
|
|
81
|
+
dictionary: `missingValue`, `missingValueLegend`, `chartMissingGaps`,
|
|
82
|
+
`chartMissingBars`, `chartMissingPoints`, `chartSeriesNoData`,
|
|
83
|
+
`chartLegendNoData`, `chartValueWithUnit`, `chartLabelWithUnit`,
|
|
84
|
+
`chartMissingUnsupported`.
|
|
85
|
+
- `examples/geoai-daily-forecast/`: a synthetic, clearly labelled GeoAI pilot
|
|
86
|
+
(daily table, one chart per variable, comparison, map, thresholds, sources
|
|
87
|
+
and limits) built with `createComparisonLayout`, `createGeographyLayout` and
|
|
88
|
+
`createEvidenceLayout`, with tests for the brief's validation criteria that a
|
|
89
|
+
library can check. Not published, since it is outside `files`;
|
|
90
|
+
type-checked by `pnpm typecheck` (`tsconfig.examples.json`).
|
|
91
|
+
|
|
92
|
+
### Unchanged on purpose
|
|
93
|
+
|
|
94
|
+
- A chart with no missing entry and no unit builds exactly the 6.23.0
|
|
95
|
+
Chart.js config, and a table with no missing cell renders the 6.23.0 DOM
|
|
96
|
+
(both tested; the table against a capture taken before the change).
|
|
97
|
+
- `renderCellValue` still returns `-` for a missing value; it now shares its
|
|
98
|
+
`"X – undefined"` cleanup with the table marks, so both always agree. CSV
|
|
99
|
+
and TSV exports still write an empty field, JSON still writes `null`.
|
|
100
|
+
- Chart.js's default interaction (`nearest`, `intersect: true`) is kept. A
|
|
101
|
+
missing bar has no height, so its tooltip only appears in `index` mode.
|
|
102
|
+
- No time axis is introduced: daily dates are categorical ISO labels. The
|
|
103
|
+
opt-in QuickChart renderer receives the payload as before; the unit and the
|
|
104
|
+
missing-value outlines, notes and legend belong to the native renderer.
|
|
105
|
+
|
|
106
|
+
### Changed — for code that reads these types
|
|
107
|
+
|
|
108
|
+
- `ChartComponentParams` datasets' `data` is now `Array<number | null>`, or
|
|
109
|
+
points whose `y` is `number | null`. Code that reads chart payloads under
|
|
110
|
+
`strictNullChecks` has to handle the missing value.
|
|
111
|
+
- `chartToDataTable` and `chartToDegradedTable` always return the extra
|
|
112
|
+
`missing` matrix; code asserting their exact shape sees one more key.
|
|
113
|
+
- `ChartDataTableLabels.withUnit` and `DegradedProjectionLabels.withUnit` are
|
|
114
|
+
new **optional** fields, so a complete labels table written for
|
|
115
|
+
6.20.0–6.23.0 as an object literal still type-checks (a
|
|
116
|
+
`Record<keyof …, string>` does not, as with any new key).
|
|
117
|
+
`CHART_DATA_TABLE_LABELS` and `DEGRADED_PROJECTION_LABELS` are now typed
|
|
118
|
+
`Required<…>`.
|
|
119
|
+
- The `INVALID_DATA_TYPE` and `INVALID_POINT_DATA` messages now mention
|
|
120
|
+
`null`; the codes do not change.
|
|
121
|
+
|
|
122
|
+
### For hosts
|
|
123
|
+
|
|
124
|
+
- **Deposium (consumer):** bump to 6.24.0 and add the ten keys to the French
|
|
125
|
+
dictionary; `satisfies Required<MCPUIStrings>` fails until they are there.
|
|
126
|
+
The visually-hidden text uses an inline style, not Tailwind's `sr-only`, so
|
|
127
|
+
the Tailwind configuration needs no change.
|
|
128
|
+
- **Producers:** emit `null` only in line, bar, radar, scatter and bubble
|
|
129
|
+
charts, never `0` for a missing value and never a shortened array. A
|
|
130
|
+
hand-copied schema mirror needs both `null` and `unit` (see the spec 5.7.0
|
|
131
|
+
changelog).
|
|
132
|
+
|
|
133
|
+
## [6.23.0] - 2026-09-18
|
|
134
|
+
|
|
135
|
+
### Added
|
|
136
|
+
|
|
137
|
+
- Opt-in `MCPUIMathProvider` and `MathRenderer` for markdown text and table
|
|
138
|
+
cells, including virtualized tables; separate optional `/plugins/katex`
|
|
139
|
+
adapter. No new required config fields and no KaTeX import from the root.
|
|
140
|
+
- Bounded dollar-delimited math parsing, currency guards, isolated Marked
|
|
141
|
+
instances, sanitized MathML-only rendering and literal fallback. Styles,
|
|
142
|
+
annotation subtrees, executable markup and trusted TeX commands stay blocked.
|
|
143
|
+
- SSR keeps escaped source until the existing client hydration upgrade;
|
|
144
|
+
original text/data is retained for copy and export. No CSS or font install.
|
|
145
|
+
- Optional KaTeX peer pinned to 0.18.4 to preserve Node 20 installation
|
|
146
|
+
compatibility; later 0.18.x releases currently require Node >=22.12 via
|
|
147
|
+
Commander. Cell links retain the existing new-tab, rel and styling policy.
|
|
148
|
+
|
|
149
|
+
## [6.22.1] - 2026-09-18
|
|
150
|
+
|
|
151
|
+
Fixes a typing regression 6.22.0 introduced. Runtime behaviour is identical.
|
|
152
|
+
|
|
153
|
+
### The mistake
|
|
154
|
+
|
|
155
|
+
6.22.0 made every `MCPUIConfig` field optional so that adding a policy key
|
|
156
|
+
would stop breaking consumers who *author* a complete config. That fixed one
|
|
157
|
+
direction and broke the other: `MCPUIConfig` is a published type, so anyone who
|
|
158
|
+
*reads* one — `const policy: IframePolicy = config.iframePolicy` — suddenly
|
|
159
|
+
faced `… | undefined` and stopped compiling under `strictNullChecks`. Trading
|
|
160
|
+
one compile break for the opposite one is not a fix.
|
|
161
|
+
|
|
162
|
+
The two demands genuinely conflict, and one name cannot serve both: an author
|
|
163
|
+
must be allowed to omit a key, a reader must never meet `undefined`.
|
|
164
|
+
|
|
165
|
+
### The fix — two names
|
|
166
|
+
|
|
167
|
+
- **`MCPUIConfigInput`** (new, exported): what a host writes. Every field
|
|
168
|
+
optional, so a new policy key is always additive. This is what
|
|
169
|
+
`MCPUIConfigProvider`'s `config` prop takes. Note it is NOT what
|
|
170
|
+
`MCPUIConfigContext.Provider` takes — see below.
|
|
171
|
+
- **`MCPUIConfig`**: what the library hands back — an interface extending
|
|
172
|
+
`Required<MCPUIConfigInput>`, every key present, which is the 6.21.0 meaning
|
|
173
|
+
restored. Keeping it an interface also preserves consumer extension and
|
|
174
|
+
declaration merging. `useMCPUIConfig()`, `DEFAULT_MCPUI_CONFIG` and
|
|
175
|
+
`MCPUIConfigContext` carry it.
|
|
176
|
+
|
|
177
|
+
`MCPUIConfigContext` keeps the resolved type on purpose: it is exported, so
|
|
178
|
+
`useContext(MCPUIConfigContext)` is a public read surface and typing it with the
|
|
179
|
+
input view would leave a direct reader on `IframePolicy | undefined` — the very
|
|
180
|
+
regression being undone. A host that bypasses `MCPUIConfigProvider` therefore
|
|
181
|
+
passes a complete value, `{ ...DEFAULT_MCPUI_CONFIG, ...mine }`; passing only
|
|
182
|
+
some keys is what the provider's `config` prop is for. `useMCPUIConfig()` still
|
|
183
|
+
merges at runtime, so an untyped host cannot break a renderer.
|
|
184
|
+
|
|
185
|
+
Derived rather than declared twice, so a key is written once and the two views
|
|
186
|
+
cannot drift. The guard test now pins **both** halves: every `MCPUIConfigInput`
|
|
187
|
+
field stays optional, and `MCPUIConfig` stays an interface extending
|
|
188
|
+
`Required<…>`. The contract typecheck also pins interface extension and
|
|
189
|
+
declaration merging. Both sides were verified to fail when their corresponding
|
|
190
|
+
regression is reintroduced.
|
|
191
|
+
|
|
192
|
+
### How this got through
|
|
193
|
+
|
|
194
|
+
Through 6.22.0, `pnpm typecheck` ran the main `tsconfig.json` alone, and that
|
|
195
|
+
config excludes `**/*.test.ts(x)`: a type-level claim written in a test file
|
|
196
|
+
failed nothing. 6.22.0 shipped both a broken `MCPUIConfig` and a fixture
|
|
197
|
+
annotated with the wrong type, and neither `typecheck` nor `test` said a word.
|
|
198
|
+
`typecheck` now runs a second pass, `tsconfig.contracts.json`, which
|
|
199
|
+
type-checks the handful of test files whose `satisfies` and annotations *are*
|
|
200
|
+
the test. Including every test file instead would surface 53 unrelated errors,
|
|
201
|
+
so that stays a separate piece of work.
|
|
202
|
+
|
|
203
|
+
### Upgrading
|
|
204
|
+
|
|
205
|
+
Reading is exactly as it was in 6.21.0, whether through `useMCPUIConfig()`,
|
|
206
|
+
`useContext(MCPUIConfigContext)` or a value typed `MCPUIConfig`.
|
|
207
|
+
`MCPUIConfigProvider`'s `config` prop still accepts everything it accepted
|
|
208
|
+
before, `Partial<MCPUIConfig>` included.
|
|
209
|
+
|
|
210
|
+
Two authoring patterns stop compiling, coming from 6.21.0 or from 6.22.0:
|
|
211
|
+
|
|
212
|
+
- **A config annotated `MCPUIConfig`.** From 6.22.0 a partial one fails; from
|
|
213
|
+
6.21.0 a complete one fails too, since it lacks `chartZoom`. Annotate it
|
|
214
|
+
`MCPUIConfigInput` instead.
|
|
215
|
+
- **A value handed straight to `<MCPUIConfigContext.Provider>`**, annotated or
|
|
216
|
+
not: an inline literal fails the same way. Spread the defaults,
|
|
217
|
+
`{ ...DEFAULT_MCPUI_CONFIG, ...mine }`, or pass the keys to
|
|
218
|
+
`<MCPUIConfigProvider config={…}>`, which does that merge for you.
|
|
219
|
+
|
|
220
|
+
Both replacements keep compiling when the library adds its next policy key.
|
|
221
|
+
|
|
8
222
|
## [6.22.0] - 2026-09-18
|
|
9
223
|
|
|
10
224
|
Wheel zoom and drag pan on the surfaces that could not be read when the content
|
|
@@ -50,6 +264,11 @@ expanded view only, and why inline zoom is opt-in.
|
|
|
50
264
|
|
|
51
265
|
### Changed
|
|
52
266
|
|
|
267
|
+
> **Superseded by 6.22.1.** Making the fields of the published `MCPUIConfig`
|
|
268
|
+
> optional broke every consumer that *reads* one. 6.22.1 moves the optional
|
|
269
|
+
> fields to a new `MCPUIConfigInput` and restores `MCPUIConfig` as the
|
|
270
|
+
> resolved type. The entry below describes 6.22.0 as published.
|
|
271
|
+
|
|
53
272
|
- **Every `MCPUIConfig` field is now optional**, as `MCPUIStrings` has always
|
|
54
273
|
been. `MCPUIConfig` grows a key in a minor release each time the library
|
|
55
274
|
gains a policy switch — `iframeFallbackLink` in 6.21.0, `chartZoom` here —
|
package/README.md
CHANGED
|
@@ -5,6 +5,75 @@ SolidJS components + chat toolkit for MCP-generated UI. Part of the [MCP UI ecos
|
|
|
5
5
|
[](https://www.npmjs.com/package/@seed-ship/mcp-ui-solid)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
+
## What's New in v6.24.0
|
|
9
|
+
|
|
10
|
+
Explicit missing values in charts and tables, and a `unit` per chart. A `null`
|
|
11
|
+
in a line, bar, radar, scatter or bubble dataset is now accepted and shown as
|
|
12
|
+
missing, never as zero. Lines break, a missing bar gets a dashed outline, and a
|
|
13
|
+
note under the chart says how. Table cells with no value are announced to
|
|
14
|
+
screen readers and explained by a legend. Ten new `MCPUIStrings` keys; requires
|
|
15
|
+
`@seed-ship/mcp-ui-spec` 5.7.0. See
|
|
16
|
+
[Missing values and units in charts](#missing-values-and-units-in-charts-v6240).
|
|
17
|
+
|
|
18
|
+
## What's New in v6.23.0
|
|
19
|
+
|
|
20
|
+
Opt-in LaTeX in markdown text components and table cells, with the same
|
|
21
|
+
currency guards and sanitized MathML output. No change without a provider;
|
|
22
|
+
`MCPUIConfig` is unchanged. See [Math rendering](#math-rendering).
|
|
23
|
+
|
|
24
|
+
## Math rendering
|
|
25
|
+
|
|
26
|
+
Install the optional peer only if the host wants the supplied KaTeX adapter:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm add --save-exact katex@0.18.4
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { MCPUIMathProvider, UIResourceRenderer } from '@seed-ship/mcp-ui-solid'
|
|
34
|
+
import { renderKatexMath } from '@seed-ship/mcp-ui-solid/plugins/katex'
|
|
35
|
+
|
|
36
|
+
<MCPUIMathProvider renderMath={renderKatexMath}>
|
|
37
|
+
<UIResourceRenderer content={resource} />
|
|
38
|
+
</MCPUIMathProvider>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The adapter's optional peer is pinned to 0.18.4 to retain Node 20 installation
|
|
42
|
+
compatibility. KaTeX 0.18.5–0.18.7 pull in Commander 15 (Node >=22.12);
|
|
43
|
+
do not replace the pin with a caret range on Node 20.
|
|
44
|
+
|
|
45
|
+
The provider applies to `text` with `markdown: true` and string-valued table
|
|
46
|
+
cells, including virtualized rows. It recognizes `$...$` inline and `$$...$$`
|
|
47
|
+
display formulas in their own paragraph (not embedded mid-sentence).
|
|
48
|
+
Code spans/fences and link destinations are not formulas;
|
|
49
|
+
currency such as `$5` and `$5-$10` remains text. Malformed/incomplete formulas
|
|
50
|
+
degrade to their source. Copy/export continues to use the original data.
|
|
51
|
+
Dollar syntax can be ambiguous: `$5$` is a formula. Escape a literal dollar
|
|
52
|
+
as `\$` when composing currency and formulas; numeric math such as `$2 + 3$`
|
|
53
|
+
remains supported. Math-enabled cell links keep their existing new-tab behavior.
|
|
54
|
+
|
|
55
|
+
The adapter emits **MathML only**: no KaTeX stylesheet, fonts, CDN requests,
|
|
56
|
+
HTML layout or inline styles. Native MathML rendering varies by browser and
|
|
57
|
+
may differ from the chat's HTML+MathML layout. There is no automatic loading:
|
|
58
|
+
the explicit plugin import is the opt-in dependency boundary; hosts can load
|
|
59
|
+
that module before mounting the provider if they want a separate chunk.
|
|
60
|
+
|
|
61
|
+
Alternatively pass a synchronous `MathRenderer` function returning MathML
|
|
62
|
+
(`(tex, { displayMode }) => string | null`). The library still sanitizes it;
|
|
63
|
+
return `null` or throw to retain literal source. Passing `null` (or omitting
|
|
64
|
+
`renderMath`) on a nested provider disables inherited math. Arbitrary Marked
|
|
65
|
+
extensions and sanitizer overrides are deliberately not public API.
|
|
66
|
+
|
|
67
|
+
On the server, escaped source is emitted without calling the renderer. The
|
|
68
|
+
existing `SafeHtml` client upgrade renders sanitized formulas after hydration.
|
|
69
|
+
Processing is bounded to 100,000 source characters, 4,096 per expression and
|
|
70
|
+
128 expressions per parse; oversized input stays escaped text. The adapter
|
|
71
|
+
also limits macro expansion and dimensions, disables trusted commands, and
|
|
72
|
+
does not share macro definitions across formulas. TeX annotation subtrees are
|
|
73
|
+
removed rather than exposing duplicate source after sanitization.
|
|
74
|
+
|
|
75
|
+
See the [design and integration handoff](./docs/briefs/LATEX-MATHML-2026-09-18.md).
|
|
76
|
+
|
|
8
77
|
## What's New in v6.21.0
|
|
9
78
|
|
|
10
79
|
- **Iframes work under `Cross-Origin-Embedder-Policy: credentialless`.** Both
|
|
@@ -656,6 +725,73 @@ Requires `protomaps-leaflet` peer dependency.
|
|
|
656
725
|
}} />
|
|
657
726
|
```
|
|
658
727
|
|
|
728
|
+
## Missing values and units in charts (v6.24.0)
|
|
729
|
+
|
|
730
|
+
`null` in a chart dataset is an **explicit missing value**: the value belongs
|
|
731
|
+
to the series' grid (its label stays on the axis) but was not observed. Send
|
|
732
|
+
`null` rather than `0`, and rather than a shorter array, whenever a value is
|
|
733
|
+
absent; a series with no value at all is all `null`.
|
|
734
|
+
|
|
735
|
+
```tsx
|
|
736
|
+
<UIResourceRenderer content={{
|
|
737
|
+
id: 'wind',
|
|
738
|
+
type: 'chart',
|
|
739
|
+
position: { colStart: 1, colSpan: 12 },
|
|
740
|
+
params: {
|
|
741
|
+
type: 'line',
|
|
742
|
+
title: 'Wind speed',
|
|
743
|
+
unit: 'km/h',
|
|
744
|
+
data: {
|
|
745
|
+
labels: ['2026-10-04', '2026-10-05', '2026-10-06'],
|
|
746
|
+
datasets: [
|
|
747
|
+
{ label: 'Lyon', data: [18, null, 31] }, // a hole on day 2
|
|
748
|
+
{ label: 'Brest', data: [null, null, null] }, // no value at all
|
|
749
|
+
],
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
}} />
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
| Chart type | A missing value is drawn as | Note under the chart |
|
|
756
|
+
|---|---|---|
|
|
757
|
+
| `line`, `radar` | a break in the line — never joined to its neighbours (`spanGaps: false` is forced) | `chartMissingGaps` |
|
|
758
|
+
| `bar` | a dashed outline at the baseline, so it cannot read as a zero bar | `chartMissingBars` |
|
|
759
|
+
| `scatter`, `bubble` | nothing: the point is not plotted | `chartMissingPoints` |
|
|
760
|
+
| `bar` with `stacked` scales | nothing: the baseline belongs to the series below, so no outline is drawn | `chartMissingPoints` |
|
|
761
|
+
| `pie`, `doughnut`, `polarArea` | refused: Chart.js would draw a missing share as `0` — validation reports `MISSING_VALUE_UNSUPPORTED` | — |
|
|
762
|
+
|
|
763
|
+
A series whose every entry is `null` keeps its legend entry, marked
|
|
764
|
+
`chartLegendNoData`, and is named in a `chartSeriesNoData` note. A chart with
|
|
765
|
+
nothing to plot says `chartNoData` in its plot area. Only an explicit entry is
|
|
766
|
+
a missing value: a dataset with no entry (`data: []`) renders as it always
|
|
767
|
+
did. The notes are linked to
|
|
768
|
+
the canvas through `aria-describedby`, and the **Data** view marks every
|
|
769
|
+
missing cell with the same `-` and screen-reader text as the table component,
|
|
770
|
+
under a `missingValueLegend` line.
|
|
771
|
+
|
|
772
|
+
`unit` (one per chart — split values with different units into separate
|
|
773
|
+
charts) titles the value axis unless `options.scales` already does, follows
|
|
774
|
+
each tooltip value (`chartValueWithUnit`), and joins the data-view column
|
|
775
|
+
headers (`chartLabelWithUnit`).
|
|
776
|
+
|
|
777
|
+
Daily series read best with ISO dates as plain category labels, as above:
|
|
778
|
+
`timeAxis` needs a Chart.js date adapter the host must register itself.
|
|
779
|
+
|
|
780
|
+
Tables follow the same rule: a cell that displays as `-` — `null`,
|
|
781
|
+
`undefined`, an empty or whitespace-only string, `"undefined"`, or a literal
|
|
782
|
+
`-` — shows a muted `-` with a visually-hidden `missingValue`, a
|
|
783
|
+
`missingValueLegend` line follows the table, missing cells sort last, and
|
|
784
|
+
search never matches them.
|
|
785
|
+
|
|
786
|
+
The outlines, notes, legend marks and `unit` belong to the native Chart.js
|
|
787
|
+
renderer. The opt-in QuickChart renderer receives the payload as is.
|
|
788
|
+
|
|
789
|
+
A synthetic, end-to-end example — daily table, one chart per variable,
|
|
790
|
+
comparison, map, thresholds, sources and limits, built with the three
|
|
791
|
+
presentation recipes — lives in
|
|
792
|
+
[`examples/geoai-daily-forecast/`](./examples/geoai-daily-forecast/) (not
|
|
793
|
+
published; its tests run with the package's).
|
|
794
|
+
|
|
659
795
|
## Chat Bus — Agent Interactions (`@experimental`)
|
|
660
796
|
|
|
661
797
|
Bidirectional event/command system for agent-driven chat interactions. Your app keeps full control of its chat UI — the bus adds structured interactivity on top.
|
|
@@ -1029,6 +1165,48 @@ import { MCPUIConfigProvider } from '@seed-ship/mcp-ui-solid'
|
|
|
1029
1165
|
</MCPUIConfigProvider>
|
|
1030
1166
|
```
|
|
1031
1167
|
|
|
1168
|
+
When you keep a partial configuration in a variable, name the authored,
|
|
1169
|
+
all-optional view explicitly:
|
|
1170
|
+
|
|
1171
|
+
```tsx
|
|
1172
|
+
import {
|
|
1173
|
+
MCPUIConfigProvider,
|
|
1174
|
+
type MCPUIConfigInput,
|
|
1175
|
+
} from '@seed-ship/mcp-ui-solid'
|
|
1176
|
+
|
|
1177
|
+
const config: MCPUIConfigInput = {
|
|
1178
|
+
iframeCredentialless: 'always',
|
|
1179
|
+
chartZoom: 'never',
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
<MCPUIConfigProvider config={config}>
|
|
1183
|
+
<App />
|
|
1184
|
+
</MCPUIConfigProvider>
|
|
1185
|
+
```
|
|
1186
|
+
|
|
1187
|
+
Prefer `MCPUIConfigProvider` for partial overrides. The exported raw context is
|
|
1188
|
+
also a public read surface, so its `Provider` requires the complete, resolved
|
|
1189
|
+
`MCPUIConfig` value. If an integration must provide that context directly,
|
|
1190
|
+
spread the defaults first:
|
|
1191
|
+
|
|
1192
|
+
```tsx
|
|
1193
|
+
import {
|
|
1194
|
+
DEFAULT_MCPUI_CONFIG,
|
|
1195
|
+
MCPUIConfigContext,
|
|
1196
|
+
} from '@seed-ship/mcp-ui-solid'
|
|
1197
|
+
|
|
1198
|
+
<MCPUIConfigContext.Provider
|
|
1199
|
+
value={{ ...DEFAULT_MCPUI_CONFIG, iframeCredentialless: 'always' }}
|
|
1200
|
+
>
|
|
1201
|
+
<App />
|
|
1202
|
+
</MCPUIConfigContext.Provider>
|
|
1203
|
+
```
|
|
1204
|
+
|
|
1205
|
+
`MCPUIConfigInput` contains the library's built-in authoring fields.
|
|
1206
|
+
`MCPUIConfig` remains an interface for consumers that extend or augment the
|
|
1207
|
+
resolved contract; `MCPUIConfigProvider` also accepts those augmented fields
|
|
1208
|
+
as partial inline overrides.
|
|
1209
|
+
|
|
1032
1210
|
| Option | Values | Default | What it does |
|
|
1033
1211
|
|--------|--------|---------|--------------|
|
|
1034
1212
|
| `iframeCredentialless` | `'auto'` \| `'always'` \| `'never'` | `'auto'` | `'auto'`: the attribute on the `iframe` component when its host is **not** in `TRUSTED_IFRAME_DOMAINS` (+ `customTrustedIframeDomains`) — those frames already run without cookies. The video embed is excluded, since it has none of that sandboxing. `'always'`: every iframe, video and trusted hosts included — what a COEP host wants. `'never'`: none. |
|
|
@@ -1429,6 +1607,20 @@ formatMCPUIString('Export CSV ({count} rows)', { count: 42 }) // 'Export CSV (42
|
|
|
1429
1607
|
| `sizeBytes` | `{size} B` | `ArtifactRenderer` — file size below 1 KB (template) |
|
|
1430
1608
|
| `sizeKilobytes` | `{size} KB` | `ArtifactRenderer` — file size in kilobytes (template) |
|
|
1431
1609
|
| `sizeMegabytes` | `{size} MB` | `ArtifactRenderer` — file size in megabytes (template) |
|
|
1610
|
+
| `zoomIn` | `Zoom in` | `LightboxOverlay`, `ChartJSRenderer` — zoom-in button `title`/`aria-label` (v6.22.0) |
|
|
1611
|
+
| `zoomOut` | `Zoom out` | `LightboxOverlay`, `ChartJSRenderer` — zoom-out button `title`/`aria-label` (v6.22.0) |
|
|
1612
|
+
| `zoomReset` | `Reset zoom` | `LightboxOverlay`, `ChartJSRenderer` — reset button, shown while zoomed (v6.22.0) |
|
|
1613
|
+
| `zoomLevel` | `Zoom {percent}%` | `LightboxOverlay` — zoom-level readout (template, v6.22.0) |
|
|
1614
|
+
| `missingValue` | `Missing value` | Tables, chart data view, degraded tables — screen-reader text of a missing cell; tooltip value of a missing bar (v6.24.0) |
|
|
1615
|
+
| `missingValueLegend` | `“{marker}” marks a missing value.` | Legend under a table or data view with a missing cell (template, `{marker}` = `-`, v6.24.0) |
|
|
1616
|
+
| `chartMissingGaps` | `Breaks in a line mark missing values.` | `ChartJSRenderer` — note under a line or radar chart with a missing value (v6.24.0) |
|
|
1617
|
+
| `chartMissingBars` | `Dashed outlines mark missing values.` | `ChartJSRenderer` — note under a bar chart with a missing value (v6.24.0) |
|
|
1618
|
+
| `chartMissingPoints` | `Missing values are not plotted.` | `ChartJSRenderer` — note under a scatter, bubble or stacked bar chart with a missing value (v6.24.0) |
|
|
1619
|
+
| `chartSeriesNoData` | `No data for {series}.` | `ChartJSRenderer` — note naming the series with no value at all (template, `{series}` joined as a list in `locale`, v6.24.0) |
|
|
1620
|
+
| `chartLegendNoData` | `{series} (no data)` | `ChartJSRenderer` — legend entry of a series with no value at all (template, v6.24.0) |
|
|
1621
|
+
| `chartValueWithUnit` | `{value} {unit}` | `ChartJSRenderer` — tooltip value followed by the chart `unit` (template, v6.24.0) |
|
|
1622
|
+
| `chartLabelWithUnit` | `{label} ({unit})` | Chart data view and degraded chart tables — column header followed by the chart `unit` (template, v6.24.0) |
|
|
1623
|
+
| `chartMissingUnsupported` | `This chart type cannot show missing values.` | `ChartJSRenderer` — shown instead of a pie, doughnut or polar-area chart that received a missing value (v6.24.0) |
|
|
1432
1624
|
|
|
1433
1625
|
### `locale` — number, date and sort formatting (default change in v6.20.0)
|
|
1434
1626
|
|
|
@@ -1766,6 +1958,20 @@ const fr: MCPUIStrings = {
|
|
|
1766
1958
|
sizeBytes: '{size} o',
|
|
1767
1959
|
sizeKilobytes: '{size} Ko',
|
|
1768
1960
|
sizeMegabytes: '{size} Mo',
|
|
1961
|
+
zoomIn: 'Zoom avant',
|
|
1962
|
+
zoomOut: 'Zoom arrière',
|
|
1963
|
+
zoomReset: 'Réinitialiser le zoom',
|
|
1964
|
+
zoomLevel: 'Zoom {percent} %',
|
|
1965
|
+
missingValue: 'Valeur manquante',
|
|
1966
|
+
missingValueLegend: '« {marker} » signale une valeur manquante.',
|
|
1967
|
+
chartMissingGaps: 'Une interruption de la courbe signale une valeur manquante.',
|
|
1968
|
+
chartMissingBars: 'Un contour en pointillés signale une valeur manquante.',
|
|
1969
|
+
chartMissingPoints: 'Les valeurs manquantes ne sont pas tracées.',
|
|
1970
|
+
chartSeriesNoData: 'Aucune donnée pour {series}.',
|
|
1971
|
+
chartLegendNoData: '{series} (aucune donnée)',
|
|
1972
|
+
chartValueWithUnit: '{value} {unit}',
|
|
1973
|
+
chartLabelWithUnit: '{label} ({unit})',
|
|
1974
|
+
chartMissingUnsupported: 'Ce type de graphique ne peut pas afficher de valeurs manquantes.',
|
|
1769
1975
|
}
|
|
1770
1976
|
|
|
1771
1977
|
<MCPUIStringsProvider strings={fr}><App /></MCPUIStringsProvider>
|
|
@@ -1800,8 +2006,8 @@ exported default table:
|
|
|
1800
2006
|
| `adapters/connector.ts` (`/adapters`) | `connectorResultToUILayout` | `options.messages?: Partial<ConnectorAdapterMessages>` | `DEFAULT_CONNECTOR_MESSAGES` | `degradedNotice`, `degradedVersionSuffix`, `versionWarning` |
|
|
1801
2007
|
| `adapters/macro-run.ts` (`/adapters`) | `macroRunToScratchpadState`, `macroInterrogationToChatPromptConfig` | `options.messages?: Partial<MacroRunAdapterMessages>` | `DEFAULT_MACRO_RUN_MESSAGES` | `agentSectionTitle`, `progressSectionTitle`, `resultSectionTitle`, `runAborted`, `runFailed`, `confirmDefault` |
|
|
1802
2008
|
| `services/validation.ts` (root, `/validation`) | `validateFieldValue`, `validateFormData` | `messages?: Partial<FormValidationMessages>` | `DEFAULT_VALIDATION_MESSAGES` | `required`, `mustBeChecked`, `minLength`, `maxLength`, `invalidPattern`, `invalidEmail`, `invalidNumber`, `minValue`, `maxValue`, `minDate`, `maxDate`, `invalidOption`, `invalidFormat` |
|
|
1803
|
-
| `utils/degraded-projections.ts` (root) | `graphToDegradedTable`, `mapToDegradedTable`, `chartToDegradedTable` | `labels?: Partial<DegradedProjectionLabels>` | `DEGRADED_PROJECTION_LABELS` | `source`, `target`, `label`, `node`, `type`, `lat`, `lng`, `info`, `marker`, `feature`, `series` |
|
|
1804
|
-
| `components/chart-data-table.ts` (root) | `chartToDataTable` | `labels?: Partial<ChartDataTableLabels>` | `CHART_DATA_TABLE_LABELS` | `series`, `point`, `label`, `seriesName`, `x`, `y`, `r` |
|
|
2009
|
+
| `utils/degraded-projections.ts` (root) | `graphToDegradedTable`, `mapToDegradedTable`, `chartToDegradedTable` | `labels?: Partial<DegradedProjectionLabels>` | `DEGRADED_PROJECTION_LABELS` | `source`, `target`, `label`, `node`, `type`, `lat`, `lng`, `info`, `marker`, `feature`, `series`, `withUnit` (optional, v6.24.0: `{label} ({unit})`, chart headers when the chart has a unit) |
|
|
2010
|
+
| `components/chart-data-table.ts` (root) | `chartToDataTable` | `labels?: Partial<ChartDataTableLabels>` | `CHART_DATA_TABLE_LABELS` | `series`, `point`, `label`, `seriesName`, `x`, `y`, `r`, `withUnit` (optional, v6.24.0: `{label} ({unit})`, value headers when the chart has a unit) |
|
|
1805
2011
|
| `hooks/useStreamingUI.ts` (root, `/hooks`) | `useStreamingUI` | `options.messages?: Partial<StreamingUIMessages>` | `DEFAULT_STREAMING_UI_MESSAGES` | `initializing`, `connecting`, `loadingComponent`, `dashboardLoaded`, `errorProgress`, `connectionFailed`, `requestFailed`, `emptyResponse`, `serverSide`, `unknownError` |
|
|
1806
2012
|
|
|
1807
2013
|
Every option is a trailing OPTIONAL parameter, so existing calls keep
|
|
@@ -1966,6 +2172,7 @@ import type {
|
|
|
1966
2172
|
IframePolicy, ValidationOptions,
|
|
1967
2173
|
CitationCtx, CitationEntry, DuplicateMountInfo, DuplicateMountReporter,
|
|
1968
2174
|
MCPUIStrings, MCPUIConfig, // v6.21.0
|
|
2175
|
+
MCPUIConfigInput, // v6.22.1 — the authored, all-optional view
|
|
1969
2176
|
TelemetryEvent, TelemetrySink, TelemetryOptions, TelemetryDispatcher,
|
|
1970
2177
|
DataValidation, HallucinatedNumber, DataValidationOptions,
|
|
1971
2178
|
VerifiedTextContent, DataPreviewContent, MapSectionContent,
|