@seed-ship/mcp-ui-solid 6.23.0 → 6.25.1
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 +167 -0
- package/README.md +154 -2
- package/dist/components/ActionGroupRenderer.cjs +6 -6
- package/dist/components/ActionGroupRenderer.cjs.map +1 -1
- package/dist/components/ActionGroupRenderer.js +6 -6
- package/dist/components/ActionGroupRenderer.js.map +1 -1
- package/dist/components/AutocompleteDropdown.cjs +6 -6
- package/dist/components/AutocompleteDropdown.cjs.map +1 -1
- package/dist/components/AutocompleteDropdown.js +6 -6
- package/dist/components/AutocompleteDropdown.js.map +1 -1
- package/dist/components/AutocompleteFormField.cjs +6 -5
- package/dist/components/AutocompleteFormField.cjs.map +1 -1
- package/dist/components/AutocompleteFormField.d.ts.map +1 -1
- package/dist/components/AutocompleteFormField.js +6 -5
- package/dist/components/AutocompleteFormField.js.map +1 -1
- package/dist/components/ChartJSRenderer.cjs +406 -70
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +407 -71
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/ChatPrompt.cjs +5 -5
- package/dist/components/ChatPrompt.cjs.map +1 -1
- package/dist/components/ChatPrompt.js +5 -5
- package/dist/components/ChatPrompt.js.map +1 -1
- package/dist/components/ComponentToolbar.cjs +5 -5
- package/dist/components/ComponentToolbar.cjs.map +1 -1
- package/dist/components/ComponentToolbar.js +5 -5
- package/dist/components/ComponentToolbar.js.map +1 -1
- package/dist/components/DegradedFallback.cjs +35 -3
- 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 +35 -3
- package/dist/components/DegradedFallback.js.map +1 -1
- package/dist/components/ExpandableWrapper.cjs +10 -7
- package/dist/components/ExpandableWrapper.cjs.map +1 -1
- package/dist/components/ExpandableWrapper.d.ts.map +1 -1
- package/dist/components/ExpandableWrapper.js +10 -7
- package/dist/components/ExpandableWrapper.js.map +1 -1
- package/dist/components/FormFieldRenderer.cjs +13 -12
- package/dist/components/FormFieldRenderer.cjs.map +1 -1
- package/dist/components/FormFieldRenderer.d.ts.map +1 -1
- package/dist/components/FormFieldRenderer.js +13 -12
- package/dist/components/FormFieldRenderer.js.map +1 -1
- package/dist/components/FormRenderer.cjs +1 -1
- package/dist/components/FormRenderer.cjs.map +1 -1
- package/dist/components/FormRenderer.js +1 -1
- package/dist/components/FormRenderer.js.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.cjs +1 -1
- package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.js +1 -1
- package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
- package/dist/components/GhostText.cjs +2 -2
- package/dist/components/GhostText.cjs.map +1 -1
- package/dist/components/GhostText.js +2 -2
- package/dist/components/GhostText.js.map +1 -1
- package/dist/components/GraphRenderer.cjs +100 -29
- package/dist/components/GraphRenderer.cjs.map +1 -1
- package/dist/components/GraphRenderer.d.ts +1 -1
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +100 -29
- package/dist/components/GraphRenderer.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/ModalRenderer.cjs +39 -31
- package/dist/components/ModalRenderer.cjs.map +1 -1
- package/dist/components/ModalRenderer.d.ts.map +1 -1
- package/dist/components/ModalRenderer.js +40 -32
- package/dist/components/ModalRenderer.js.map +1 -1
- package/dist/components/PortalDropdownMenu.cjs +6 -3
- package/dist/components/PortalDropdownMenu.cjs.map +1 -1
- package/dist/components/PortalDropdownMenu.d.ts.map +1 -1
- package/dist/components/PortalDropdownMenu.js +7 -4
- package/dist/components/PortalDropdownMenu.js.map +1 -1
- package/dist/components/ScratchpadPanel.cjs +38 -44
- package/dist/components/ScratchpadPanel.cjs.map +1 -1
- package/dist/components/ScratchpadPanel.d.ts.map +1 -1
- package/dist/components/ScratchpadPanel.js +38 -44
- package/dist/components/ScratchpadPanel.js.map +1 -1
- package/dist/components/UIResourceRenderer.cjs +255 -217
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +255 -217
- 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 +129 -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/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/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/math-markdown.cjs +1 -1
- package/dist/utils/math-markdown.cjs.map +1 -1
- package/dist/utils/math-markdown.js +1 -1
- package/dist/utils/math-markdown.js.map +1 -1
- 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/dist/utils/theme.cjs +91 -0
- package/dist/utils/theme.cjs.map +1 -0
- package/dist/utils/theme.d.ts +11 -0
- package/dist/utils/theme.d.ts.map +1 -0
- package/dist/utils/theme.js +91 -0
- package/dist/utils/theme.js.map +1 -0
- package/docs/SECURITY-DEPENDENCIES.md +81 -0
- package/docs/THEMING.md +205 -0
- package/package.json +7 -5
- package/src/components/ActionGroupRenderer.tsx +6 -6
- package/src/components/AutocompleteDropdown.tsx +17 -17
- package/src/components/AutocompleteFormField.tsx +10 -9
- package/src/components/ChartJSRenderer.tsx +609 -212
- package/src/components/ChatPrompt.tsx +16 -16
- package/src/components/ComponentToolbar.tsx +5 -5
- package/src/components/DegradedFallback.tsx +33 -11
- package/src/components/ExpandableWrapper.tsx +15 -11
- package/src/components/FormFieldRenderer.tsx +52 -51
- package/src/components/FormRenderer.tsx +12 -12
- package/src/components/GenerativeUIErrorBoundary.tsx +6 -6
- package/src/components/GhostText.tsx +7 -7
- package/src/components/GraphRenderer.tsx +83 -67
- package/src/components/MissingValue.tsx +61 -0
- package/src/components/ModalRenderer.tsx +11 -5
- package/src/components/PortalDropdownMenu.tsx +6 -2
- package/src/components/ScratchpadPanel.tsx +144 -141
- package/src/components/UIResourceRenderer.tsx +143 -110
- package/src/components/chart-data-table.ts +50 -6
- package/src/components/chart-missing-plugin.ts +336 -0
- package/src/context/MCPUIStringsContext.tsx +76 -0
- package/src/services/component-registry.ts +10 -2
- package/src/services/validation.ts +44 -9
- package/src/styles/autocomplete.css +53 -53
- package/src/types/index.ts +13 -1
- package/src/utils/degraded-projections.ts +44 -4
- package/src/utils/math-markdown.ts +1 -1
- package/src/utils/missing-value.ts +127 -0
- package/src/utils/theme.ts +101 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,173 @@ 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.25.1] - 2026-10-18
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
|
|
12
|
+
- Raise the published DOMPurify floor to `^3.4.17` (lockfile: 3.4.17), covering
|
|
13
|
+
both reported `IN_PLACE` advisories and subsequent upstream hardening. The
|
|
14
|
+
library's existing string-based sanitization profiles remain unchanged.
|
|
15
|
+
- Update workspace Solid to 1.9.17 and Seroval/Seroval plugins to 1.6.11,
|
|
16
|
+
using Solid's supported 1.6.x dependency range instead of the stale 1.5.x
|
|
17
|
+
override. Add real asynchronous SSR and JSON serialization compatibility tests.
|
|
18
|
+
- Update build/test resolutions to `source-map-js` 1.2.2 and `brace-expansion`
|
|
19
|
+
5.0.12. Audit falls from nine advisories to one remaining HIGH advisory in
|
|
20
|
+
the distinct, unpatched development dependency `braces` 3.0.3. No audit ignore
|
|
21
|
+
or advisory dismissal is added; see `docs/SECURITY-DEPENDENCIES.md`.
|
|
22
|
+
- Workspace overrides do not propagate to consuming applications. Hosts must
|
|
23
|
+
separately update their Solid/Seroval lockfiles; the public Solid peer range
|
|
24
|
+
and component APIs are unchanged.
|
|
25
|
+
|
|
26
|
+
## [6.25.0] - 2026-10-18
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Inherited `--mcp-ui-*` CSS theme tokens with per-use original color fallbacks
|
|
31
|
+
for prompts, resource/table chrome, scratchpads, form controls, autocomplete,
|
|
32
|
+
expanded dialogs, export menus and chart/graph chrome. No required provider,
|
|
33
|
+
new dependency, global root defaults or component prop changes.
|
|
34
|
+
- Body portal theme synchronization, including local `.dark`, live ancestor
|
|
35
|
+
token changes and removal; fullscreen content retains its original DOM.
|
|
36
|
+
- Scoped Chart.js/G6 series, grid, axis, label and tooltip tokens with live
|
|
37
|
+
updates and explicit caller color precedence; original engine defaults are
|
|
38
|
+
retained when no host tokens are supplied.
|
|
39
|
+
- Frozen 6.24.0 Chromium computed-style comparisons, host/portal regressions,
|
|
40
|
+
static Tailwind class checks and theming documentation with coverage limits.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- Form input and autocomplete text respects the host foreground without a
|
|
45
|
+
`.dark` class, preserving inherited default colors and muted field states.
|
|
46
|
+
- Explicit point paints no longer block themed line/radar strokes. Live
|
|
47
|
+
Chart.js theme updates also refresh resolved shared point/bar colors without
|
|
48
|
+
replacing their options or changing caller-provided non-color settings.
|
|
49
|
+
|
|
50
|
+
## [6.24.0] - 2026-10-03
|
|
51
|
+
|
|
52
|
+
Explicit missing values in charts and tables, and a unit per chart — lot 1 of
|
|
53
|
+
the GeoAI display brief (`deposium_geoai/docs/handoffs/2026-10-03-mcp-ui-geoai-display-brief.md`).
|
|
54
|
+
Released with `@seed-ship/mcp-ui-spec` 5.7.0, whose chart schema accepts both;
|
|
55
|
+
the dependency floor moves to `^5.7.0`.
|
|
56
|
+
|
|
57
|
+
### The rule
|
|
58
|
+
|
|
59
|
+
Absence is never zero. A `null` keeps its slot — its label stays on the axis,
|
|
60
|
+
its row stays in the table — and every view marks it, visibly and for screen
|
|
61
|
+
readers. Until now `validateComponent` refused any chart carrying a `null`, so
|
|
62
|
+
a host that drops invalid components (Deposium's chat does) showed nothing.
|
|
63
|
+
|
|
64
|
+
Only an explicit entry is a missing value: `null` (or a non-finite number, or a
|
|
65
|
+
point whose `y` is one). A dataset with no entry at all (`data: []`) is not —
|
|
66
|
+
it renders exactly as it did in 6.23.0.
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- **Charts accept `null`** in line, bar, radar, scatter and bubble datasets,
|
|
71
|
+
as a number slot or as a point's `y`:
|
|
72
|
+
- a line or a radar breaks at the missing value: `spanGaps: false` is set on
|
|
73
|
+
every dataset of a chart that has one, so nothing joins the neighbours,
|
|
74
|
+
and the date stays on the axis;
|
|
75
|
+
- a missing bar is drawn as a dashed outline at the baseline, so it cannot
|
|
76
|
+
be read as a zero bar (Chart.js draws nothing for both). Stacked or
|
|
77
|
+
overlaid bars get no outline — their baseline belongs to the series below,
|
|
78
|
+
so an outline there would point at the wrong series — and their note says
|
|
79
|
+
the values are not plotted;
|
|
80
|
+
- scatter and bubble charts leave the point out;
|
|
81
|
+
- a series whose every entry is missing keeps its legend entry, marked
|
|
82
|
+
`chartLegendNoData` ("(no data)"), and a chart with nothing to plot says
|
|
83
|
+
so in its plot area (`chartNoData`);
|
|
84
|
+
- a note under the chart explains how this chart shows a missing value
|
|
85
|
+
(`chartMissingGaps`, `chartMissingBars`, `chartMissingPoints`), shown when
|
|
86
|
+
a reader can actually see the mark, and names the series with no data
|
|
87
|
+
(`chartSeriesNoData`, joined with `Intl.ListFormat` in the strings
|
|
88
|
+
`locale`). The canvas's `aria-describedby` includes it. DOM hooks:
|
|
89
|
+
`[data-mcp-chart-notes]` and
|
|
90
|
+
`[data-mcp-chart-note="gaps|bars|omitted|no-data"]`;
|
|
91
|
+
- a tooltip names a missing bar (`missingValue`) instead of printing `0`.
|
|
92
|
+
|
|
93
|
+
Pie, doughnut and polar-area charts refuse `null`, as a bare value or as a
|
|
94
|
+
point's `y`, because Chart.js parses a missing share as `0` and would draw
|
|
95
|
+
every other share wrong. `validateChartComponent` reports
|
|
96
|
+
`MISSING_VALUE_UNSUPPORTED`. If a host bypasses validation, the renderer
|
|
97
|
+
shows its data table with `chartMissingUnsupported` instead of a misleading
|
|
98
|
+
chart.
|
|
99
|
+
- **`unit`** on chart params: the value-axis title (bar, line, scatter and
|
|
100
|
+
bubble, unless `options.scales` already sets one), the tooltip value
|
|
101
|
+
(`chartValueWithUnit`, except on scatter and bubble, whose value is a pair)
|
|
102
|
+
and the column headers of the data view and of the degraded table
|
|
103
|
+
(`chartLabelWithUnit`). `validateChartComponent` reports `INVALID_UNIT` for
|
|
104
|
+
a non-string unit or one longer than 32 characters; an empty string is
|
|
105
|
+
tolerated and means "no unit".
|
|
106
|
+
- **Tables.** A cell that already displayed as `-` — `null`, `undefined`, an
|
|
107
|
+
empty or whitespace-only string, `"undefined"` (after the backend's
|
|
108
|
+
`"X – undefined"` debris is stripped) or a literal `-` — is now muted,
|
|
109
|
+
hidden from assistive technology and followed by a visually-hidden
|
|
110
|
+
`missingValue`. A legend (`missingValueLegend`, `[data-mcp-missing-legend]`)
|
|
111
|
+
follows any table with such a cell. It is computed on every row, so it does
|
|
112
|
+
not flicker while paging. Missing cells sort last in both directions (an
|
|
113
|
+
empty string no longer sorts as `0`), a numeric column is detected from its
|
|
114
|
+
first present value, and search never matches a missing cell.
|
|
115
|
+
- **The chart data view and the degraded tables** mark missing cells the same
|
|
116
|
+
way, under the same legend. `chartToDataTable` and `chartToDegradedTable`
|
|
117
|
+
return an extra `missing` matrix shaped like `rows`, which still hold `''`.
|
|
118
|
+
One exception: the degraded table prints point data (scatter, bubble,
|
|
119
|
+
`{x, y}` series) as JSON, where `"y":null` reads as such, and does not mark
|
|
120
|
+
it. `DegradedFallback` takes an optional `missing` prop; the graph and map
|
|
121
|
+
degraded tables do not change.
|
|
122
|
+
- Ten `MCPUIStrings` keys (275 → 285), English defaults, French in the README
|
|
123
|
+
dictionary: `missingValue`, `missingValueLegend`, `chartMissingGaps`,
|
|
124
|
+
`chartMissingBars`, `chartMissingPoints`, `chartSeriesNoData`,
|
|
125
|
+
`chartLegendNoData`, `chartValueWithUnit`, `chartLabelWithUnit`,
|
|
126
|
+
`chartMissingUnsupported`.
|
|
127
|
+
- `examples/geoai-daily-forecast/`: a synthetic, clearly labelled GeoAI pilot
|
|
128
|
+
(daily table, one chart per variable, comparison, map, thresholds, sources
|
|
129
|
+
and limits) built with `createComparisonLayout`, `createGeographyLayout` and
|
|
130
|
+
`createEvidenceLayout`, with tests for the brief's validation criteria that a
|
|
131
|
+
library can check. Not published, since it is outside `files`;
|
|
132
|
+
type-checked by `pnpm typecheck` (`tsconfig.examples.json`).
|
|
133
|
+
|
|
134
|
+
### Unchanged on purpose
|
|
135
|
+
|
|
136
|
+
- A chart with no missing entry and no unit builds exactly the 6.23.0
|
|
137
|
+
Chart.js config, and a table with no missing cell renders the 6.23.0 DOM
|
|
138
|
+
(both tested; the table against a capture taken before the change).
|
|
139
|
+
- `renderCellValue` still returns `-` for a missing value; it now shares its
|
|
140
|
+
`"X – undefined"` cleanup with the table marks, so both always agree. CSV
|
|
141
|
+
and TSV exports still write an empty field, JSON still writes `null`.
|
|
142
|
+
- Chart.js's default interaction (`nearest`, `intersect: true`) is kept. A
|
|
143
|
+
missing bar has no height, so its tooltip only appears in `index` mode.
|
|
144
|
+
- No time axis is introduced: daily dates are categorical ISO labels. The
|
|
145
|
+
opt-in QuickChart renderer receives the payload as before; the unit and the
|
|
146
|
+
missing-value outlines, notes and legend belong to the native renderer.
|
|
147
|
+
|
|
148
|
+
### Changed — for code that reads these types
|
|
149
|
+
|
|
150
|
+
- `ChartComponentParams` datasets' `data` is now `Array<number | null>`, or
|
|
151
|
+
points whose `y` is `number | null`. Code that reads chart payloads under
|
|
152
|
+
`strictNullChecks` has to handle the missing value.
|
|
153
|
+
- `chartToDataTable` and `chartToDegradedTable` always return the extra
|
|
154
|
+
`missing` matrix; code asserting their exact shape sees one more key.
|
|
155
|
+
- `ChartDataTableLabels.withUnit` and `DegradedProjectionLabels.withUnit` are
|
|
156
|
+
new **optional** fields, so a complete labels table written for
|
|
157
|
+
6.20.0–6.23.0 as an object literal still type-checks (a
|
|
158
|
+
`Record<keyof …, string>` does not, as with any new key).
|
|
159
|
+
`CHART_DATA_TABLE_LABELS` and `DEGRADED_PROJECTION_LABELS` are now typed
|
|
160
|
+
`Required<…>`.
|
|
161
|
+
- The `INVALID_DATA_TYPE` and `INVALID_POINT_DATA` messages now mention
|
|
162
|
+
`null`; the codes do not change.
|
|
163
|
+
|
|
164
|
+
### For hosts
|
|
165
|
+
|
|
166
|
+
- **Deposium (consumer):** bump to 6.24.0 and add the ten keys to the French
|
|
167
|
+
dictionary; `satisfies Required<MCPUIStrings>` fails until they are there.
|
|
168
|
+
The visually-hidden text uses an inline style, not Tailwind's `sr-only`, so
|
|
169
|
+
the Tailwind configuration needs no change.
|
|
170
|
+
- **Producers:** emit `null` only in line, bar, radar, scatter and bubble
|
|
171
|
+
charts, never `0` for a missing value and never a shortened array. A
|
|
172
|
+
hand-copied schema mirror needs both `null` and `unit` (see the spec 5.7.0
|
|
173
|
+
changelog).
|
|
174
|
+
|
|
8
175
|
## [6.23.0] - 2026-09-18
|
|
9
176
|
|
|
10
177
|
### Added
|
package/README.md
CHANGED
|
@@ -5,6 +5,63 @@ 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.25.1
|
|
9
|
+
|
|
10
|
+
DOMPurify now requires `^3.4.17`. The workspace uses the compatible Solid
|
|
11
|
+
1.9.17 patch with corrected Seroval and build-tool dependency resolutions,
|
|
12
|
+
covered by a real server-rendering/serialization smoke test. These workspace
|
|
13
|
+
overrides do not update an application's own Solid/Seroval lockfile.
|
|
14
|
+
See [security dependency notes](./docs/SECURITY-DEPENDENCIES.md) for host
|
|
15
|
+
upgrade guidance and the remaining unpatched development-tooling advisory.
|
|
16
|
+
|
|
17
|
+
## What's New in v6.25.0
|
|
18
|
+
|
|
19
|
+
Inherited `--mcp-ui-*` CSS tokens theme prompts, resource/table chrome,
|
|
20
|
+
scratchpads, form controls, autocomplete and chart/graph chrome. Body portals
|
|
21
|
+
follow their local host theme; mounted Chart.js/G6 instances update without
|
|
22
|
+
losing their identity. Existing colors remain the defaults.
|
|
23
|
+
|
|
24
|
+
## Theming
|
|
25
|
+
|
|
26
|
+
Set variables on an ancestor; no provider or extra stylesheet is required
|
|
27
|
+
for the Tailwind-based components. Keep scanning this package's `src/**/*.{ts,tsx}`
|
|
28
|
+
with Tailwind v4 and your existing class-based `.dark` variant.
|
|
29
|
+
|
|
30
|
+
```css
|
|
31
|
+
.app-theme {
|
|
32
|
+
--mcp-ui-surface: #ffffff;
|
|
33
|
+
--mcp-ui-surface-muted: #f1f5f9;
|
|
34
|
+
--mcp-ui-fg: #0f172a;
|
|
35
|
+
--mcp-ui-fg-muted: #475569;
|
|
36
|
+
--mcp-ui-border: #cbd5e1;
|
|
37
|
+
--mcp-ui-accent: #1d4ed8;
|
|
38
|
+
}
|
|
39
|
+
.dark .app-theme {
|
|
40
|
+
--mcp-ui-surface: #0f172a;
|
|
41
|
+
--mcp-ui-surface-muted: #1e293b;
|
|
42
|
+
--mcp-ui-fg: #f8fafc;
|
|
43
|
+
--mcp-ui-fg-muted: #cbd5e1;
|
|
44
|
+
--mcp-ui-border: #64748b;
|
|
45
|
+
--mcp-ui-accent: #93c5fd;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The library deliberately does not redeclare public tokens on nested roots:
|
|
50
|
+
an ancestor's tokens keep inheriting. Each use falls back to its original
|
|
51
|
+
color, preserving the existing light/dark distinctions. Optional autocomplete
|
|
52
|
+
CSS is still imported as before. See [the complete token reference, portal
|
|
53
|
+
behavior, contrast limits and migration coverage](./docs/THEMING.md).
|
|
54
|
+
|
|
55
|
+
## What's New in v6.24.0
|
|
56
|
+
|
|
57
|
+
Explicit missing values in charts and tables, and a `unit` per chart. A `null`
|
|
58
|
+
in a line, bar, radar, scatter or bubble dataset is now accepted and shown as
|
|
59
|
+
missing, never as zero. Lines break, a missing bar gets a dashed outline, and a
|
|
60
|
+
note under the chart says how. Table cells with no value are announced to
|
|
61
|
+
screen readers and explained by a legend. Ten new `MCPUIStrings` keys; requires
|
|
62
|
+
`@seed-ship/mcp-ui-spec` 5.7.0. See
|
|
63
|
+
[Missing values and units in charts](#missing-values-and-units-in-charts-v6240).
|
|
64
|
+
|
|
8
65
|
## What's New in v6.23.0
|
|
9
66
|
|
|
10
67
|
Opt-in LaTeX in markdown text components and table cells, with the same
|
|
@@ -715,6 +772,73 @@ Requires `protomaps-leaflet` peer dependency.
|
|
|
715
772
|
}} />
|
|
716
773
|
```
|
|
717
774
|
|
|
775
|
+
## Missing values and units in charts (v6.24.0)
|
|
776
|
+
|
|
777
|
+
`null` in a chart dataset is an **explicit missing value**: the value belongs
|
|
778
|
+
to the series' grid (its label stays on the axis) but was not observed. Send
|
|
779
|
+
`null` rather than `0`, and rather than a shorter array, whenever a value is
|
|
780
|
+
absent; a series with no value at all is all `null`.
|
|
781
|
+
|
|
782
|
+
```tsx
|
|
783
|
+
<UIResourceRenderer content={{
|
|
784
|
+
id: 'wind',
|
|
785
|
+
type: 'chart',
|
|
786
|
+
position: { colStart: 1, colSpan: 12 },
|
|
787
|
+
params: {
|
|
788
|
+
type: 'line',
|
|
789
|
+
title: 'Wind speed',
|
|
790
|
+
unit: 'km/h',
|
|
791
|
+
data: {
|
|
792
|
+
labels: ['2026-10-04', '2026-10-05', '2026-10-06'],
|
|
793
|
+
datasets: [
|
|
794
|
+
{ label: 'Lyon', data: [18, null, 31] }, // a hole on day 2
|
|
795
|
+
{ label: 'Brest', data: [null, null, null] }, // no value at all
|
|
796
|
+
],
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
}} />
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
| Chart type | A missing value is drawn as | Note under the chart |
|
|
803
|
+
|---|---|---|
|
|
804
|
+
| `line`, `radar` | a break in the line — never joined to its neighbours (`spanGaps: false` is forced) | `chartMissingGaps` |
|
|
805
|
+
| `bar` | a dashed outline at the baseline, so it cannot read as a zero bar | `chartMissingBars` |
|
|
806
|
+
| `scatter`, `bubble` | nothing: the point is not plotted | `chartMissingPoints` |
|
|
807
|
+
| `bar` with `stacked` scales | nothing: the baseline belongs to the series below, so no outline is drawn | `chartMissingPoints` |
|
|
808
|
+
| `pie`, `doughnut`, `polarArea` | refused: Chart.js would draw a missing share as `0` — validation reports `MISSING_VALUE_UNSUPPORTED` | — |
|
|
809
|
+
|
|
810
|
+
A series whose every entry is `null` keeps its legend entry, marked
|
|
811
|
+
`chartLegendNoData`, and is named in a `chartSeriesNoData` note. A chart with
|
|
812
|
+
nothing to plot says `chartNoData` in its plot area. Only an explicit entry is
|
|
813
|
+
a missing value: a dataset with no entry (`data: []`) renders as it always
|
|
814
|
+
did. The notes are linked to
|
|
815
|
+
the canvas through `aria-describedby`, and the **Data** view marks every
|
|
816
|
+
missing cell with the same `-` and screen-reader text as the table component,
|
|
817
|
+
under a `missingValueLegend` line.
|
|
818
|
+
|
|
819
|
+
`unit` (one per chart — split values with different units into separate
|
|
820
|
+
charts) titles the value axis unless `options.scales` already does, follows
|
|
821
|
+
each tooltip value (`chartValueWithUnit`), and joins the data-view column
|
|
822
|
+
headers (`chartLabelWithUnit`).
|
|
823
|
+
|
|
824
|
+
Daily series read best with ISO dates as plain category labels, as above:
|
|
825
|
+
`timeAxis` needs a Chart.js date adapter the host must register itself.
|
|
826
|
+
|
|
827
|
+
Tables follow the same rule: a cell that displays as `-` — `null`,
|
|
828
|
+
`undefined`, an empty or whitespace-only string, `"undefined"`, or a literal
|
|
829
|
+
`-` — shows a muted `-` with a visually-hidden `missingValue`, a
|
|
830
|
+
`missingValueLegend` line follows the table, missing cells sort last, and
|
|
831
|
+
search never matches them.
|
|
832
|
+
|
|
833
|
+
The outlines, notes, legend marks and `unit` belong to the native Chart.js
|
|
834
|
+
renderer. The opt-in QuickChart renderer receives the payload as is.
|
|
835
|
+
|
|
836
|
+
A synthetic, end-to-end example — daily table, one chart per variable,
|
|
837
|
+
comparison, map, thresholds, sources and limits, built with the three
|
|
838
|
+
presentation recipes — lives in
|
|
839
|
+
[`examples/geoai-daily-forecast/`](./examples/geoai-daily-forecast/) (not
|
|
840
|
+
published; its tests run with the package's).
|
|
841
|
+
|
|
718
842
|
## Chat Bus — Agent Interactions (`@experimental`)
|
|
719
843
|
|
|
720
844
|
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.
|
|
@@ -1530,6 +1654,20 @@ formatMCPUIString('Export CSV ({count} rows)', { count: 42 }) // 'Export CSV (42
|
|
|
1530
1654
|
| `sizeBytes` | `{size} B` | `ArtifactRenderer` — file size below 1 KB (template) |
|
|
1531
1655
|
| `sizeKilobytes` | `{size} KB` | `ArtifactRenderer` — file size in kilobytes (template) |
|
|
1532
1656
|
| `sizeMegabytes` | `{size} MB` | `ArtifactRenderer` — file size in megabytes (template) |
|
|
1657
|
+
| `zoomIn` | `Zoom in` | `LightboxOverlay`, `ChartJSRenderer` — zoom-in button `title`/`aria-label` (v6.22.0) |
|
|
1658
|
+
| `zoomOut` | `Zoom out` | `LightboxOverlay`, `ChartJSRenderer` — zoom-out button `title`/`aria-label` (v6.22.0) |
|
|
1659
|
+
| `zoomReset` | `Reset zoom` | `LightboxOverlay`, `ChartJSRenderer` — reset button, shown while zoomed (v6.22.0) |
|
|
1660
|
+
| `zoomLevel` | `Zoom {percent}%` | `LightboxOverlay` — zoom-level readout (template, v6.22.0) |
|
|
1661
|
+
| `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) |
|
|
1662
|
+
| `missingValueLegend` | `“{marker}” marks a missing value.` | Legend under a table or data view with a missing cell (template, `{marker}` = `-`, v6.24.0) |
|
|
1663
|
+
| `chartMissingGaps` | `Breaks in a line mark missing values.` | `ChartJSRenderer` — note under a line or radar chart with a missing value (v6.24.0) |
|
|
1664
|
+
| `chartMissingBars` | `Dashed outlines mark missing values.` | `ChartJSRenderer` — note under a bar chart with a missing value (v6.24.0) |
|
|
1665
|
+
| `chartMissingPoints` | `Missing values are not plotted.` | `ChartJSRenderer` — note under a scatter, bubble or stacked bar chart with a missing value (v6.24.0) |
|
|
1666
|
+
| `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) |
|
|
1667
|
+
| `chartLegendNoData` | `{series} (no data)` | `ChartJSRenderer` — legend entry of a series with no value at all (template, v6.24.0) |
|
|
1668
|
+
| `chartValueWithUnit` | `{value} {unit}` | `ChartJSRenderer` — tooltip value followed by the chart `unit` (template, v6.24.0) |
|
|
1669
|
+
| `chartLabelWithUnit` | `{label} ({unit})` | Chart data view and degraded chart tables — column header followed by the chart `unit` (template, v6.24.0) |
|
|
1670
|
+
| `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) |
|
|
1533
1671
|
|
|
1534
1672
|
### `locale` — number, date and sort formatting (default change in v6.20.0)
|
|
1535
1673
|
|
|
@@ -1867,6 +2005,20 @@ const fr: MCPUIStrings = {
|
|
|
1867
2005
|
sizeBytes: '{size} o',
|
|
1868
2006
|
sizeKilobytes: '{size} Ko',
|
|
1869
2007
|
sizeMegabytes: '{size} Mo',
|
|
2008
|
+
zoomIn: 'Zoom avant',
|
|
2009
|
+
zoomOut: 'Zoom arrière',
|
|
2010
|
+
zoomReset: 'Réinitialiser le zoom',
|
|
2011
|
+
zoomLevel: 'Zoom {percent} %',
|
|
2012
|
+
missingValue: 'Valeur manquante',
|
|
2013
|
+
missingValueLegend: '« {marker} » signale une valeur manquante.',
|
|
2014
|
+
chartMissingGaps: 'Une interruption de la courbe signale une valeur manquante.',
|
|
2015
|
+
chartMissingBars: 'Un contour en pointillés signale une valeur manquante.',
|
|
2016
|
+
chartMissingPoints: 'Les valeurs manquantes ne sont pas tracées.',
|
|
2017
|
+
chartSeriesNoData: 'Aucune donnée pour {series}.',
|
|
2018
|
+
chartLegendNoData: '{series} (aucune donnée)',
|
|
2019
|
+
chartValueWithUnit: '{value} {unit}',
|
|
2020
|
+
chartLabelWithUnit: '{label} ({unit})',
|
|
2021
|
+
chartMissingUnsupported: 'Ce type de graphique ne peut pas afficher de valeurs manquantes.',
|
|
1870
2022
|
}
|
|
1871
2023
|
|
|
1872
2024
|
<MCPUIStringsProvider strings={fr}><App /></MCPUIStringsProvider>
|
|
@@ -1901,8 +2053,8 @@ exported default table:
|
|
|
1901
2053
|
| `adapters/connector.ts` (`/adapters`) | `connectorResultToUILayout` | `options.messages?: Partial<ConnectorAdapterMessages>` | `DEFAULT_CONNECTOR_MESSAGES` | `degradedNotice`, `degradedVersionSuffix`, `versionWarning` |
|
|
1902
2054
|
| `adapters/macro-run.ts` (`/adapters`) | `macroRunToScratchpadState`, `macroInterrogationToChatPromptConfig` | `options.messages?: Partial<MacroRunAdapterMessages>` | `DEFAULT_MACRO_RUN_MESSAGES` | `agentSectionTitle`, `progressSectionTitle`, `resultSectionTitle`, `runAborted`, `runFailed`, `confirmDefault` |
|
|
1903
2055
|
| `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` |
|
|
1904
|
-
| `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` |
|
|
1905
|
-
| `components/chart-data-table.ts` (root) | `chartToDataTable` | `labels?: Partial<ChartDataTableLabels>` | `CHART_DATA_TABLE_LABELS` | `series`, `point`, `label`, `seriesName`, `x`, `y`, `r` |
|
|
2056
|
+
| `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) |
|
|
2057
|
+
| `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) |
|
|
1906
2058
|
| `hooks/useStreamingUI.ts` (root, `/hooks`) | `useStreamingUI` | `options.messages?: Partial<StreamingUIMessages>` | `DEFAULT_STREAMING_UI_MESSAGES` | `initializing`, `connecting`, `loadingComponent`, `dashboardLoaded`, `errorProgress`, `connectionFailed`, `requestFailed`, `emptyResponse`, `serverSide`, `unknownError` |
|
|
1907
2059
|
|
|
1908
2060
|
Every option is a trailing OPTIONAL parameter, so existing calls keep
|
|
@@ -33,17 +33,17 @@ const ActionButton = (props) => {
|
|
|
33
33
|
const variantClass = () => {
|
|
34
34
|
switch (props.action.variant) {
|
|
35
35
|
case "primary":
|
|
36
|
-
return "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500";
|
|
36
|
+
return "bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))]";
|
|
37
37
|
case "secondary":
|
|
38
|
-
return "bg-gray-200 text-gray-800 hover:bg-gray-300 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 focus:ring-gray-500";
|
|
38
|
+
return "bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-200,#e5e7eb))] text-[color:var(--mcp-ui-fg,var(--color-gray-800,#1f2937))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-300,#d1d5db))] dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-600,#4b5563))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]";
|
|
39
39
|
case "outline":
|
|
40
|
-
return "border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:ring-gray-500";
|
|
40
|
+
return "border border-[color:var(--mcp-ui-border,var(--color-gray-300,#d1d5db))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-50,#f9fafb))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]";
|
|
41
41
|
case "ghost":
|
|
42
|
-
return "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:ring-gray-500";
|
|
42
|
+
return "text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]";
|
|
43
43
|
case "danger":
|
|
44
|
-
return "bg-red-600 text-white hover:bg-red-700 focus:ring-red-500";
|
|
44
|
+
return "bg-[color:var(--mcp-ui-danger,var(--color-red-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-danger-hover,var(--color-red-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-red-500))]";
|
|
45
45
|
default:
|
|
46
|
-
return "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500";
|
|
46
|
+
return "bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))]";
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
const sizeClass = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionGroupRenderer.cjs","sources":["../../src/components/ActionGroupRenderer.tsx"],"sourcesContent":["/**\n * ActionGroupRenderer - Group of actions with layout options\n * Sprint 3: UX Improvements\n */\n\nimport { Component, For, Show } from 'solid-js'\nimport type { UIComponent, ActionGroupParams, ActionComponentParams } from '../types'\nimport { useAction } from '../hooks/useAction'\nimport { safeUrl } from '../utils/safe-url'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nexport interface ActionGroupRendererProps {\n /**\n * UIComponent with action-group params (for declarative use)\n */\n component?: UIComponent\n\n /**\n * Direct action group params (alternative to component)\n */\n params?: ActionGroupParams\n}\n\n/**\n * Render a single action button with variants and click handling\n */\nconst ActionButton: Component<{\n action: ActionComponentParams\n index: number\n}> = (props) => {\n const { execute, executeAction, isExecuting } = useAction()\n\n // tool-call and submit both go through the host executor — they show a\n // loading state and gate disabled while running. link does neither.\n const isExecutable = () =>\n props.action.action === 'tool-call' || props.action.action === 'submit'\n\n const handleClick = async (e: MouseEvent) => {\n if (props.action.disabled) return\n\n if (props.action.action === 'tool-call' && props.action.toolName) {\n e.preventDefault()\n await execute(props.action.toolName, props.action.params || {})\n } else if (props.action.action === 'submit') {\n // submit is NOT a tool call — route it through the executor with the\n // `action: 'submit'` kind preserved so the host can POST to\n // params.submit_url etc. Works without a surrounding <form>.\n e.preventDefault()\n await executeAction({\n action: 'submit',\n toolName: props.action.toolName || 'submit',\n params: props.action.params || {},\n })\n } else if (props.action.action === 'link' && props.action.url) {\n window.open(props.action.url, '_blank', 'noopener,noreferrer')\n }\n }\n\n const isDisabled = () =>\n props.action.disabled || (isExecutable() && isExecuting())\n\n const variantClass = () => {\n switch (props.action.variant) {\n case 'primary':\n return 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500'\n case 'secondary':\n return 'bg-gray-200 text-gray-800 hover:bg-gray-300 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 focus:ring-gray-500'\n case 'outline':\n return 'border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:ring-gray-500'\n case 'ghost':\n return 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:ring-gray-500'\n case 'danger':\n return 'bg-red-600 text-white hover:bg-red-700 focus:ring-red-500'\n default:\n return 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500'\n }\n }\n\n const sizeClass = () => {\n switch (props.action.size) {\n case 'sm':\n return 'px-2 py-1 text-xs'\n case 'lg':\n return 'px-6 py-3 text-base'\n default:\n return 'px-4 py-2 text-sm'\n }\n }\n\n // Render as link if it's a link action\n if (props.action.type === 'link' || (props.action.action === 'link' && props.action.url)) {\n return (\n <a\n href={safeUrl(props.action.url ?? '') ?? '#'}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class={`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${variantClass()} ${sizeClass()} ${\n isDisabled() ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''\n }`}\n >\n <Show when={props.action.icon}>\n <span class=\"text-current\">{props.action.icon}</span>\n </Show>\n {props.action.label}\n </a>\n )\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isDisabled()}\n class={`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${variantClass()} ${sizeClass()} ${\n isDisabled() ? 'opacity-50 cursor-not-allowed' : ''\n }`}\n >\n <Show when={isExecuting() && isExecutable()}>\n <span class=\"animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full\" />\n </Show>\n <Show when={props.action.icon && !(isExecuting() && isExecutable())}>\n <span class=\"text-current\">{props.action.icon}</span>\n </Show>\n {props.action.label}\n </button>\n )\n}\n\n/**\n * Action group component for rendering multiple actions with consistent layout\n *\n * @example\n * ```tsx\n * const actionGroup: UIComponent = {\n * id: 'form-actions',\n * type: 'action-group',\n * position: { colStart: 1, colSpan: 12 },\n * params: {\n * layout: 'end',\n * gap: 'md',\n * actions: [\n * { label: 'Cancel', variant: 'outline', action: 'link', url: '/back' },\n * { label: 'Save', variant: 'primary', action: 'tool-call', toolName: 'save' },\n * ],\n * },\n * }\n * <ActionGroupRenderer component={actionGroup} />\n * ```\n */\nexport const ActionGroupRenderer: Component<ActionGroupRendererProps> = (props) => {\n const strings = useMCPUIStrings()\n const params = () => props.params || (props.component?.params as ActionGroupParams) || { actions: [] }\n\n const layoutClass = () => {\n switch (params()?.layout) {\n case 'vertical':\n return 'flex flex-col'\n case 'space-between':\n return 'flex justify-between'\n case 'end':\n return 'flex justify-end'\n case 'center':\n return 'flex justify-center'\n default: // horizontal\n return 'flex'\n }\n }\n\n const gapClass = () => {\n switch (params()?.gap) {\n case 'none':\n return 'gap-0'\n case 'sm':\n return 'gap-1'\n case 'lg':\n return 'gap-4'\n default: // md\n return 'gap-2'\n }\n }\n\n return (\n <div\n class={`${layoutClass()} ${gapClass()} ${params()?.fullWidth ? 'w-full' : ''}`}\n role=\"group\"\n aria-label={params()?.label || strings.actionGroupLabel}\n >\n <For each={params()?.actions || []}>\n {(action, index) => <ActionButton action={action} index={index()} />}\n </For>\n </div>\n )\n}\n"],"names":["ActionButton","props","execute","executeAction","isExecuting","useAction","isExecutable","action","handleClick","e","disabled","toolName","preventDefault","params","url","window","open","isDisabled","variantClass","variant","sizeClass","size","type","_el$","_$getNextElement","_tmpl$2","_el$3","firstChild","_el$4","_co$","_$getNextMarker","nextSibling","_el$5","_el$6","_co$2","_$insert","_$createComponent","Show","when","icon","children","_el$2","_tmpl$","label","_$effect","_p$","_v$","safeUrl","_v$2","_$setAttribute","t","_$className","undefined","_el$7","_tmpl$4","_el$0","_el$1","_co$3","_el$10","_el$11","_co$4","_el$12","_el$13","_co$5","$$click","_$memo","_tmpl$3","_el$9","_v$3","_v$4","_$setProperty","_$runHydrationEvents","ActionGroupRenderer","strings","useMCPUIStrings","component","actions","layoutClass","layout","gapClass","gap","_el$14","_tmpl$5","For","each","index","_v$5","fullWidth","_v$6","actionGroupLabel","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ActionGroupRenderer.cjs","sources":["../../src/components/ActionGroupRenderer.tsx"],"sourcesContent":["/**\n * ActionGroupRenderer - Group of actions with layout options\n * Sprint 3: UX Improvements\n */\n\nimport { Component, For, Show } from 'solid-js'\nimport type { UIComponent, ActionGroupParams, ActionComponentParams } from '../types'\nimport { useAction } from '../hooks/useAction'\nimport { safeUrl } from '../utils/safe-url'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nexport interface ActionGroupRendererProps {\n /**\n * UIComponent with action-group params (for declarative use)\n */\n component?: UIComponent\n\n /**\n * Direct action group params (alternative to component)\n */\n params?: ActionGroupParams\n}\n\n/**\n * Render a single action button with variants and click handling\n */\nconst ActionButton: Component<{\n action: ActionComponentParams\n index: number\n}> = (props) => {\n const { execute, executeAction, isExecuting } = useAction()\n\n // tool-call and submit both go through the host executor — they show a\n // loading state and gate disabled while running. link does neither.\n const isExecutable = () =>\n props.action.action === 'tool-call' || props.action.action === 'submit'\n\n const handleClick = async (e: MouseEvent) => {\n if (props.action.disabled) return\n\n if (props.action.action === 'tool-call' && props.action.toolName) {\n e.preventDefault()\n await execute(props.action.toolName, props.action.params || {})\n } else if (props.action.action === 'submit') {\n // submit is NOT a tool call — route it through the executor with the\n // `action: 'submit'` kind preserved so the host can POST to\n // params.submit_url etc. Works without a surrounding <form>.\n e.preventDefault()\n await executeAction({\n action: 'submit',\n toolName: props.action.toolName || 'submit',\n params: props.action.params || {},\n })\n } else if (props.action.action === 'link' && props.action.url) {\n window.open(props.action.url, '_blank', 'noopener,noreferrer')\n }\n }\n\n const isDisabled = () =>\n props.action.disabled || (isExecutable() && isExecuting())\n\n const variantClass = () => {\n switch (props.action.variant) {\n case 'primary':\n return 'bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))]'\n case 'secondary':\n return 'bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-200,#e5e7eb))] text-[color:var(--mcp-ui-fg,var(--color-gray-800,#1f2937))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-300,#d1d5db))] dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-600,#4b5563))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]'\n case 'outline':\n return 'border border-[color:var(--mcp-ui-border,var(--color-gray-300,#d1d5db))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-50,#f9fafb))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]'\n case 'ghost':\n return 'text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]'\n case 'danger':\n return 'bg-[color:var(--mcp-ui-danger,var(--color-red-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-danger-hover,var(--color-red-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-red-500))]'\n default:\n return 'bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))]'\n }\n }\n\n const sizeClass = () => {\n switch (props.action.size) {\n case 'sm':\n return 'px-2 py-1 text-xs'\n case 'lg':\n return 'px-6 py-3 text-base'\n default:\n return 'px-4 py-2 text-sm'\n }\n }\n\n // Render as link if it's a link action\n if (props.action.type === 'link' || (props.action.action === 'link' && props.action.url)) {\n return (\n <a\n href={safeUrl(props.action.url ?? '') ?? '#'}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class={`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${variantClass()} ${sizeClass()} ${\n isDisabled() ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''\n }`}\n >\n <Show when={props.action.icon}>\n <span class=\"text-current\">{props.action.icon}</span>\n </Show>\n {props.action.label}\n </a>\n )\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isDisabled()}\n class={`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${variantClass()} ${sizeClass()} ${\n isDisabled() ? 'opacity-50 cursor-not-allowed' : ''\n }`}\n >\n <Show when={isExecuting() && isExecutable()}>\n <span class=\"animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full\" />\n </Show>\n <Show when={props.action.icon && !(isExecuting() && isExecutable())}>\n <span class=\"text-current\">{props.action.icon}</span>\n </Show>\n {props.action.label}\n </button>\n )\n}\n\n/**\n * Action group component for rendering multiple actions with consistent layout\n *\n * @example\n * ```tsx\n * const actionGroup: UIComponent = {\n * id: 'form-actions',\n * type: 'action-group',\n * position: { colStart: 1, colSpan: 12 },\n * params: {\n * layout: 'end',\n * gap: 'md',\n * actions: [\n * { label: 'Cancel', variant: 'outline', action: 'link', url: '/back' },\n * { label: 'Save', variant: 'primary', action: 'tool-call', toolName: 'save' },\n * ],\n * },\n * }\n * <ActionGroupRenderer component={actionGroup} />\n * ```\n */\nexport const ActionGroupRenderer: Component<ActionGroupRendererProps> = (props) => {\n const strings = useMCPUIStrings()\n const params = () => props.params || (props.component?.params as ActionGroupParams) || { actions: [] }\n\n const layoutClass = () => {\n switch (params()?.layout) {\n case 'vertical':\n return 'flex flex-col'\n case 'space-between':\n return 'flex justify-between'\n case 'end':\n return 'flex justify-end'\n case 'center':\n return 'flex justify-center'\n default: // horizontal\n return 'flex'\n }\n }\n\n const gapClass = () => {\n switch (params()?.gap) {\n case 'none':\n return 'gap-0'\n case 'sm':\n return 'gap-1'\n case 'lg':\n return 'gap-4'\n default: // md\n return 'gap-2'\n }\n }\n\n return (\n <div\n class={`${layoutClass()} ${gapClass()} ${params()?.fullWidth ? 'w-full' : ''}`}\n role=\"group\"\n aria-label={params()?.label || strings.actionGroupLabel}\n >\n <For each={params()?.actions || []}>\n {(action, index) => <ActionButton action={action} index={index()} />}\n </For>\n </div>\n )\n}\n"],"names":["ActionButton","props","execute","executeAction","isExecuting","useAction","isExecutable","action","handleClick","e","disabled","toolName","preventDefault","params","url","window","open","isDisabled","variantClass","variant","sizeClass","size","type","_el$","_$getNextElement","_tmpl$2","_el$3","firstChild","_el$4","_co$","_$getNextMarker","nextSibling","_el$5","_el$6","_co$2","_$insert","_$createComponent","Show","when","icon","children","_el$2","_tmpl$","label","_$effect","_p$","_v$","safeUrl","_v$2","_$setAttribute","t","_$className","undefined","_el$7","_tmpl$4","_el$0","_el$1","_co$3","_el$10","_el$11","_co$4","_el$12","_el$13","_co$5","$$click","_$memo","_tmpl$3","_el$9","_v$3","_v$4","_$setProperty","_$runHydrationEvents","ActionGroupRenderer","strings","useMCPUIStrings","component","actions","layoutClass","layout","gapClass","gap","_el$14","_tmpl$5","For","each","index","_v$5","fullWidth","_v$6","actionGroupLabel","_$delegateEvents"],"mappings":"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"}
|
|
@@ -31,17 +31,17 @@ const ActionButton = (props) => {
|
|
|
31
31
|
const variantClass = () => {
|
|
32
32
|
switch (props.action.variant) {
|
|
33
33
|
case "primary":
|
|
34
|
-
return "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500";
|
|
34
|
+
return "bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))]";
|
|
35
35
|
case "secondary":
|
|
36
|
-
return "bg-gray-200 text-gray-800 hover:bg-gray-300 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 focus:ring-gray-500";
|
|
36
|
+
return "bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-200,#e5e7eb))] text-[color:var(--mcp-ui-fg,var(--color-gray-800,#1f2937))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-300,#d1d5db))] dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-600,#4b5563))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]";
|
|
37
37
|
case "outline":
|
|
38
|
-
return "border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:ring-gray-500";
|
|
38
|
+
return "border border-[color:var(--mcp-ui-border,var(--color-gray-300,#d1d5db))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-50,#f9fafb))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]";
|
|
39
39
|
case "ghost":
|
|
40
|
-
return "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:ring-gray-500";
|
|
40
|
+
return "text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]";
|
|
41
41
|
case "danger":
|
|
42
|
-
return "bg-red-600 text-white hover:bg-red-700 focus:ring-red-500";
|
|
42
|
+
return "bg-[color:var(--mcp-ui-danger,var(--color-red-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-danger-hover,var(--color-red-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-red-500))]";
|
|
43
43
|
default:
|
|
44
|
-
return "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500";
|
|
44
|
+
return "bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))]";
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
const sizeClass = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionGroupRenderer.js","sources":["../../src/components/ActionGroupRenderer.tsx"],"sourcesContent":["/**\n * ActionGroupRenderer - Group of actions with layout options\n * Sprint 3: UX Improvements\n */\n\nimport { Component, For, Show } from 'solid-js'\nimport type { UIComponent, ActionGroupParams, ActionComponentParams } from '../types'\nimport { useAction } from '../hooks/useAction'\nimport { safeUrl } from '../utils/safe-url'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nexport interface ActionGroupRendererProps {\n /**\n * UIComponent with action-group params (for declarative use)\n */\n component?: UIComponent\n\n /**\n * Direct action group params (alternative to component)\n */\n params?: ActionGroupParams\n}\n\n/**\n * Render a single action button with variants and click handling\n */\nconst ActionButton: Component<{\n action: ActionComponentParams\n index: number\n}> = (props) => {\n const { execute, executeAction, isExecuting } = useAction()\n\n // tool-call and submit both go through the host executor — they show a\n // loading state and gate disabled while running. link does neither.\n const isExecutable = () =>\n props.action.action === 'tool-call' || props.action.action === 'submit'\n\n const handleClick = async (e: MouseEvent) => {\n if (props.action.disabled) return\n\n if (props.action.action === 'tool-call' && props.action.toolName) {\n e.preventDefault()\n await execute(props.action.toolName, props.action.params || {})\n } else if (props.action.action === 'submit') {\n // submit is NOT a tool call — route it through the executor with the\n // `action: 'submit'` kind preserved so the host can POST to\n // params.submit_url etc. Works without a surrounding <form>.\n e.preventDefault()\n await executeAction({\n action: 'submit',\n toolName: props.action.toolName || 'submit',\n params: props.action.params || {},\n })\n } else if (props.action.action === 'link' && props.action.url) {\n window.open(props.action.url, '_blank', 'noopener,noreferrer')\n }\n }\n\n const isDisabled = () =>\n props.action.disabled || (isExecutable() && isExecuting())\n\n const variantClass = () => {\n switch (props.action.variant) {\n case 'primary':\n return 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500'\n case 'secondary':\n return 'bg-gray-200 text-gray-800 hover:bg-gray-300 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 focus:ring-gray-500'\n case 'outline':\n return 'border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:ring-gray-500'\n case 'ghost':\n return 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:ring-gray-500'\n case 'danger':\n return 'bg-red-600 text-white hover:bg-red-700 focus:ring-red-500'\n default:\n return 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500'\n }\n }\n\n const sizeClass = () => {\n switch (props.action.size) {\n case 'sm':\n return 'px-2 py-1 text-xs'\n case 'lg':\n return 'px-6 py-3 text-base'\n default:\n return 'px-4 py-2 text-sm'\n }\n }\n\n // Render as link if it's a link action\n if (props.action.type === 'link' || (props.action.action === 'link' && props.action.url)) {\n return (\n <a\n href={safeUrl(props.action.url ?? '') ?? '#'}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class={`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${variantClass()} ${sizeClass()} ${\n isDisabled() ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''\n }`}\n >\n <Show when={props.action.icon}>\n <span class=\"text-current\">{props.action.icon}</span>\n </Show>\n {props.action.label}\n </a>\n )\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isDisabled()}\n class={`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${variantClass()} ${sizeClass()} ${\n isDisabled() ? 'opacity-50 cursor-not-allowed' : ''\n }`}\n >\n <Show when={isExecuting() && isExecutable()}>\n <span class=\"animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full\" />\n </Show>\n <Show when={props.action.icon && !(isExecuting() && isExecutable())}>\n <span class=\"text-current\">{props.action.icon}</span>\n </Show>\n {props.action.label}\n </button>\n )\n}\n\n/**\n * Action group component for rendering multiple actions with consistent layout\n *\n * @example\n * ```tsx\n * const actionGroup: UIComponent = {\n * id: 'form-actions',\n * type: 'action-group',\n * position: { colStart: 1, colSpan: 12 },\n * params: {\n * layout: 'end',\n * gap: 'md',\n * actions: [\n * { label: 'Cancel', variant: 'outline', action: 'link', url: '/back' },\n * { label: 'Save', variant: 'primary', action: 'tool-call', toolName: 'save' },\n * ],\n * },\n * }\n * <ActionGroupRenderer component={actionGroup} />\n * ```\n */\nexport const ActionGroupRenderer: Component<ActionGroupRendererProps> = (props) => {\n const strings = useMCPUIStrings()\n const params = () => props.params || (props.component?.params as ActionGroupParams) || { actions: [] }\n\n const layoutClass = () => {\n switch (params()?.layout) {\n case 'vertical':\n return 'flex flex-col'\n case 'space-between':\n return 'flex justify-between'\n case 'end':\n return 'flex justify-end'\n case 'center':\n return 'flex justify-center'\n default: // horizontal\n return 'flex'\n }\n }\n\n const gapClass = () => {\n switch (params()?.gap) {\n case 'none':\n return 'gap-0'\n case 'sm':\n return 'gap-1'\n case 'lg':\n return 'gap-4'\n default: // md\n return 'gap-2'\n }\n }\n\n return (\n <div\n class={`${layoutClass()} ${gapClass()} ${params()?.fullWidth ? 'w-full' : ''}`}\n role=\"group\"\n aria-label={params()?.label || strings.actionGroupLabel}\n >\n <For each={params()?.actions || []}>\n {(action, index) => <ActionButton action={action} index={index()} />}\n </For>\n </div>\n )\n}\n"],"names":["ActionButton","props","execute","executeAction","isExecuting","useAction","isExecutable","action","handleClick","e","disabled","toolName","preventDefault","params","url","window","open","isDisabled","variantClass","variant","sizeClass","size","type","_el$","_$getNextElement","_tmpl$2","_el$3","firstChild","_el$4","_co$","_$getNextMarker","nextSibling","_el$5","_el$6","_co$2","_$insert","_$createComponent","Show","when","icon","children","_el$2","_tmpl$","label","_$effect","_p$","_v$","safeUrl","_v$2","_$setAttribute","t","_$className","undefined","_el$7","_tmpl$4","_el$0","_el$1","_co$3","_el$10","_el$11","_co$4","_el$12","_el$13","_co$5","$$click","_$memo","_tmpl$3","_el$9","_v$3","_v$4","_$setProperty","_$runHydrationEvents","ActionGroupRenderer","strings","useMCPUIStrings","component","actions","layoutClass","layout","gapClass","gap","_el$14","_tmpl$5","For","each","index","_v$5","fullWidth","_v$6","actionGroupLabel","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ActionGroupRenderer.js","sources":["../../src/components/ActionGroupRenderer.tsx"],"sourcesContent":["/**\n * ActionGroupRenderer - Group of actions with layout options\n * Sprint 3: UX Improvements\n */\n\nimport { Component, For, Show } from 'solid-js'\nimport type { UIComponent, ActionGroupParams, ActionComponentParams } from '../types'\nimport { useAction } from '../hooks/useAction'\nimport { safeUrl } from '../utils/safe-url'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nexport interface ActionGroupRendererProps {\n /**\n * UIComponent with action-group params (for declarative use)\n */\n component?: UIComponent\n\n /**\n * Direct action group params (alternative to component)\n */\n params?: ActionGroupParams\n}\n\n/**\n * Render a single action button with variants and click handling\n */\nconst ActionButton: Component<{\n action: ActionComponentParams\n index: number\n}> = (props) => {\n const { execute, executeAction, isExecuting } = useAction()\n\n // tool-call and submit both go through the host executor — they show a\n // loading state and gate disabled while running. link does neither.\n const isExecutable = () =>\n props.action.action === 'tool-call' || props.action.action === 'submit'\n\n const handleClick = async (e: MouseEvent) => {\n if (props.action.disabled) return\n\n if (props.action.action === 'tool-call' && props.action.toolName) {\n e.preventDefault()\n await execute(props.action.toolName, props.action.params || {})\n } else if (props.action.action === 'submit') {\n // submit is NOT a tool call — route it through the executor with the\n // `action: 'submit'` kind preserved so the host can POST to\n // params.submit_url etc. Works without a surrounding <form>.\n e.preventDefault()\n await executeAction({\n action: 'submit',\n toolName: props.action.toolName || 'submit',\n params: props.action.params || {},\n })\n } else if (props.action.action === 'link' && props.action.url) {\n window.open(props.action.url, '_blank', 'noopener,noreferrer')\n }\n }\n\n const isDisabled = () =>\n props.action.disabled || (isExecutable() && isExecuting())\n\n const variantClass = () => {\n switch (props.action.variant) {\n case 'primary':\n return 'bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))]'\n case 'secondary':\n return 'bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-200,#e5e7eb))] text-[color:var(--mcp-ui-fg,var(--color-gray-800,#1f2937))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-300,#d1d5db))] dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-600,#4b5563))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]'\n case 'outline':\n return 'border border-[color:var(--mcp-ui-border,var(--color-gray-300,#d1d5db))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-50,#f9fafb))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]'\n case 'ghost':\n return 'text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))]'\n case 'danger':\n return 'bg-[color:var(--mcp-ui-danger,var(--color-red-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-danger-hover,var(--color-red-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-red-500))]'\n default:\n return 'bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))]'\n }\n }\n\n const sizeClass = () => {\n switch (props.action.size) {\n case 'sm':\n return 'px-2 py-1 text-xs'\n case 'lg':\n return 'px-6 py-3 text-base'\n default:\n return 'px-4 py-2 text-sm'\n }\n }\n\n // Render as link if it's a link action\n if (props.action.type === 'link' || (props.action.action === 'link' && props.action.url)) {\n return (\n <a\n href={safeUrl(props.action.url ?? '') ?? '#'}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class={`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${variantClass()} ${sizeClass()} ${\n isDisabled() ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''\n }`}\n >\n <Show when={props.action.icon}>\n <span class=\"text-current\">{props.action.icon}</span>\n </Show>\n {props.action.label}\n </a>\n )\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isDisabled()}\n class={`inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${variantClass()} ${sizeClass()} ${\n isDisabled() ? 'opacity-50 cursor-not-allowed' : ''\n }`}\n >\n <Show when={isExecuting() && isExecutable()}>\n <span class=\"animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full\" />\n </Show>\n <Show when={props.action.icon && !(isExecuting() && isExecutable())}>\n <span class=\"text-current\">{props.action.icon}</span>\n </Show>\n {props.action.label}\n </button>\n )\n}\n\n/**\n * Action group component for rendering multiple actions with consistent layout\n *\n * @example\n * ```tsx\n * const actionGroup: UIComponent = {\n * id: 'form-actions',\n * type: 'action-group',\n * position: { colStart: 1, colSpan: 12 },\n * params: {\n * layout: 'end',\n * gap: 'md',\n * actions: [\n * { label: 'Cancel', variant: 'outline', action: 'link', url: '/back' },\n * { label: 'Save', variant: 'primary', action: 'tool-call', toolName: 'save' },\n * ],\n * },\n * }\n * <ActionGroupRenderer component={actionGroup} />\n * ```\n */\nexport const ActionGroupRenderer: Component<ActionGroupRendererProps> = (props) => {\n const strings = useMCPUIStrings()\n const params = () => props.params || (props.component?.params as ActionGroupParams) || { actions: [] }\n\n const layoutClass = () => {\n switch (params()?.layout) {\n case 'vertical':\n return 'flex flex-col'\n case 'space-between':\n return 'flex justify-between'\n case 'end':\n return 'flex justify-end'\n case 'center':\n return 'flex justify-center'\n default: // horizontal\n return 'flex'\n }\n }\n\n const gapClass = () => {\n switch (params()?.gap) {\n case 'none':\n return 'gap-0'\n case 'sm':\n return 'gap-1'\n case 'lg':\n return 'gap-4'\n default: // md\n return 'gap-2'\n }\n }\n\n return (\n <div\n class={`${layoutClass()} ${gapClass()} ${params()?.fullWidth ? 'w-full' : ''}`}\n role=\"group\"\n aria-label={params()?.label || strings.actionGroupLabel}\n >\n <For each={params()?.actions || []}>\n {(action, index) => <ActionButton action={action} index={index()} />}\n </For>\n </div>\n )\n}\n"],"names":["ActionButton","props","execute","executeAction","isExecuting","useAction","isExecutable","action","handleClick","e","disabled","toolName","preventDefault","params","url","window","open","isDisabled","variantClass","variant","sizeClass","size","type","_el$","_$getNextElement","_tmpl$2","_el$3","firstChild","_el$4","_co$","_$getNextMarker","nextSibling","_el$5","_el$6","_co$2","_$insert","_$createComponent","Show","when","icon","children","_el$2","_tmpl$","label","_$effect","_p$","_v$","safeUrl","_v$2","_$setAttribute","t","_$className","undefined","_el$7","_tmpl$4","_el$0","_el$1","_co$3","_el$10","_el$11","_co$4","_el$12","_el$13","_co$5","$$click","_$memo","_tmpl$3","_el$9","_v$3","_v$4","_$setProperty","_$runHydrationEvents","ActionGroupRenderer","strings","useMCPUIStrings","component","actions","layoutClass","layout","gapClass","gap","_el$14","_tmpl$5","For","each","index","_v$5","fullWidth","_v$6","actionGroupLabel","_$delegateEvents"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const web = require("solid-js/web");
|
|
4
4
|
const solidJs = require("solid-js");
|
|
5
5
|
const MCPUIStringsContext = require("../context/MCPUIStringsContext.cjs");
|
|
6
|
-
var _tmpl$ = /* @__PURE__ */ web.template(`<strong class=mcp-autocomplete-highlight>`), _tmpl$2 = /* @__PURE__ */ web.template(`<span class=mcp-autocomplete-option-icon>`), _tmpl$3 = /* @__PURE__ */ web.template(`<span class=mcp-autocomplete-option-description>`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-option-content><!$><!/><div class=mcp-autocomplete-option-text><span class=mcp-autocomplete-option-label></span><!$><!/>`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-loading style="padding:12px 16px;color
|
|
6
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<strong class=mcp-autocomplete-highlight>`), _tmpl$2 = /* @__PURE__ */ web.template(`<span class=mcp-autocomplete-option-icon>`), _tmpl$3 = /* @__PURE__ */ web.template(`<span class=mcp-autocomplete-option-description>`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-option-content><!$><!/><div class=mcp-autocomplete-option-text><span class=mcp-autocomplete-option-label></span><!$><!/>`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-loading style="padding:12px 16px;color:var(--mcp-ui-fg-muted, #6b7280);font-size:0.875rem;display:flex;align-items:center;gap:8px"><span style="display:inline-block;width:14px;height:14px;border:2px solid var(--mcp-ui-border, #e5e7eb);border-top-color:var(--mcp-ui-accent, #3b82f6);border-radius:50%;animation:mcp-spin 0.6s linear infinite"></span><!$><!/>`), _tmpl$6 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-empty style="padding:12px 16px;color:var(--mcp-ui-fg-subtle, #9ca3af);font-size:0.875rem;text-align:center">`), _tmpl$7 = /* @__PURE__ */ web.template(`<ul class=mcp-autocomplete-options style="margin:0;padding:4px 0;list-style:none">`), _tmpl$8 = /* @__PURE__ */ web.template(`<div class=mcp-autocomplete-footer style="padding:6px 12px;border-top:1px solid var(--mcp-ui-border, #e5e7eb);background-color:var(--mcp-ui-surface-muted, #f9fafb);font-size:0.75rem;color:var(--mcp-ui-fg-muted, #6b7280)"><kbd style="background-color:var(--mcp-ui-surface-hover, #e5e7eb);padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">↑</kbd> <kbd style="background-color:var(--mcp-ui-surface-hover, #e5e7eb);padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">↓</kbd><!$><!/><kbd style="background-color:var(--mcp-ui-surface-hover, #e5e7eb);padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">Enter</kbd><!$><!/><kbd style="background-color:var(--mcp-ui-surface-hover, #e5e7eb);padding:1px 4px;border-radius:2px;font-family:inherit;font-size:0.7rem">Esc</kbd><!$><!/>`), _tmpl$9 = /* @__PURE__ */ web.template(`<div role=listbox><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$0 = /* @__PURE__ */ web.template(`<li role=option style="padding:8px 16px;font-size:0.875rem;transition:background-color 150ms ease">`);
|
|
7
7
|
function highlightText(text, match) {
|
|
8
8
|
if (!match || !text) {
|
|
9
9
|
return text;
|
|
@@ -70,10 +70,10 @@ const AutocompleteDropdown = (props) => {
|
|
|
70
70
|
left: "0",
|
|
71
71
|
right: "0",
|
|
72
72
|
"z-index": "50",
|
|
73
|
-
"background-color": "#ffffff",
|
|
74
|
-
border: "1px solid #e5e7eb",
|
|
73
|
+
"background-color": "var(--mcp-ui-surface, #ffffff)",
|
|
74
|
+
border: "1px solid var(--mcp-ui-border, #e5e7eb)",
|
|
75
75
|
"border-radius": "6px",
|
|
76
|
-
"box-shadow": "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
76
|
+
"box-shadow": "var(--mcp-ui-shadow, 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06))",
|
|
77
77
|
"max-height": props.maxHeight || "240px",
|
|
78
78
|
overflow: "auto",
|
|
79
79
|
...positionStyles()
|
|
@@ -150,7 +150,7 @@ const AutocompleteDropdown = (props) => {
|
|
|
150
150
|
}
|
|
151
151
|
}));
|
|
152
152
|
web.effect((_p$) => {
|
|
153
|
-
var _v$4 = isSelected(), _v$5 = isDisabled(), _v$6 = `mcp-autocomplete-option ${isSelected() ? "mcp-autocomplete-option-selected" : ""} ${isDisabled() ? "mcp-autocomplete-option-disabled" : ""}`, _v$7 = isDisabled() ? "not-allowed" : "pointer", _v$8 = isSelected() ? "#eff6ff" : "transparent", _v$9 = isDisabled() ? "#9ca3af" : "#374151";
|
|
153
|
+
var _v$4 = isSelected(), _v$5 = isDisabled(), _v$6 = `mcp-autocomplete-option ${isSelected() ? "mcp-autocomplete-option-selected" : ""} ${isDisabled() ? "mcp-autocomplete-option-disabled" : ""}`, _v$7 = isDisabled() ? "not-allowed" : "pointer", _v$8 = isSelected() ? "var(--mcp-ui-accent-soft, #eff6ff)" : "transparent", _v$9 = isDisabled() ? "var(--mcp-ui-fg-subtle, #9ca3af)" : "var(--mcp-ui-fg, #374151)";
|
|
154
154
|
_v$4 !== _p$.e && web.setAttribute(_el$36, "aria-selected", _p$.e = _v$4);
|
|
155
155
|
_v$5 !== _p$.t && web.setAttribute(_el$36, "aria-disabled", _p$.t = _v$5);
|
|
156
156
|
_v$6 !== _p$.a && web.className(_el$36, _p$.a = _v$6);
|
|
@@ -187,7 +187,7 @@ const AutocompleteDropdown = (props) => {
|
|
|
187
187
|
}
|
|
188
188
|
}), _el$35, _co$0);
|
|
189
189
|
web.effect((_p$) => {
|
|
190
|
-
var _v$ = `mcp-autocomplete-dropdown ${props.class || ""}`, _v$2 = containerStyles(), _v$3 = strings.autocompleteSuggestions;
|
|
190
|
+
var _v$ = `mcp-ui-root mcp-autocomplete-dropdown ${props.class || ""}`, _v$2 = containerStyles(), _v$3 = strings.autocompleteSuggestions;
|
|
191
191
|
_v$ !== _p$.e && web.className(_el$1, _p$.e = _v$);
|
|
192
192
|
_p$.t = web.style(_el$1, _v$2, _p$.t);
|
|
193
193
|
_v$3 !== _p$.a && web.setAttribute(_el$1, "aria-label", _p$.a = _v$3);
|