@seed-ship/mcp-ui-solid 6.24.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 +42 -0
- package/README.md +47 -0
- 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 +216 -6
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +217 -7
- 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 +1 -1
- package/dist/components/DegradedFallback.cjs.map +1 -1
- package/dist/components/DegradedFallback.js +1 -1
- 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 +2 -2
- package/dist/components/MissingValue.cjs.map +1 -1
- package/dist/components/MissingValue.js +2 -2
- package/dist/components/MissingValue.js.map +1 -1
- 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 +20 -20
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.js +20 -20
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/chart-missing-plugin.cjs +4 -4
- package/dist/components/chart-missing-plugin.cjs.map +1 -1
- package/dist/components/chart-missing-plugin.d.ts +3 -1
- package/dist/components/chart-missing-plugin.d.ts.map +1 -1
- package/dist/components/chart-missing-plugin.js +4 -4
- package/dist/components/chart-missing-plugin.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/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 +5 -3
- 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 +483 -239
- package/src/components/ChatPrompt.tsx +16 -16
- package/src/components/ComponentToolbar.tsx +5 -5
- package/src/components/DegradedFallback.tsx +9 -9
- 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 +2 -2
- 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 +101 -101
- package/src/components/chart-missing-plugin.ts +5 -3
- package/src/styles/autocomplete.css +53 -53
- package/src/utils/math-markdown.ts +1 -1
- package/src/utils/theme.ts +101 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,48 @@ 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
|
+
|
|
8
50
|
## [6.24.0] - 2026-10-03
|
|
9
51
|
|
|
10
52
|
Explicit missing values in charts and tables, and a unit per chart — lot 1 of
|
package/README.md
CHANGED
|
@@ -5,6 +5,53 @@ 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
|
+
|
|
8
55
|
## What's New in v6.24.0
|
|
9
56
|
|
|
10
57
|
Explicit missing values in charts and tables, and a `unit` per chart. A `null`
|
|
@@ -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);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteDropdown.cjs","sources":["../../src/components/AutocompleteDropdown.tsx"],"sourcesContent":["/**\n * AutocompleteDropdown Component\n * Displays data-driven dropdown suggestions\n *\n * Sprint Autocomplete Feature\n */\n\nimport { Component, For, Show, createMemo, JSX } from 'solid-js'\nimport type { AutocompleteOption } from '../types'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\n/**\n * Props for AutocompleteDropdown\n */\nexport interface AutocompleteDropdownProps {\n /**\n * Options to display\n */\n options: AutocompleteOption[]\n\n /**\n * Currently selected index\n */\n selectedIndex: number\n\n /**\n * Whether dropdown is visible\n */\n isOpen: boolean\n\n /**\n * Callback when option is selected\n */\n onSelect: (option: AutocompleteOption) => void\n\n /**\n * Callback when option is hovered\n */\n onHover?: (index: number) => void\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n\n /**\n * Custom class\n */\n class?: string\n\n /**\n * Max height\n */\n maxHeight?: string\n\n /**\n * Empty state message\n */\n emptyMessage?: string\n\n /**\n * Loading message\n */\n loadingMessage?: string\n\n /**\n * Highlight matching text in options\n */\n highlightMatch?: string\n\n /**\n * Position (default: 'bottom')\n */\n position?: 'top' | 'bottom'\n\n /**\n * Custom option renderer\n */\n renderOption?: (option: AutocompleteOption, isSelected: boolean) => JSX.Element\n}\n\n/**\n * Highlight matching text\n */\nfunction highlightText(text: string, match?: string): JSX.Element {\n if (!match || !text) {\n return <>{text}</>\n }\n\n const lowerText = text.toLowerCase()\n const lowerMatch = match.toLowerCase()\n const startIndex = lowerText.indexOf(lowerMatch)\n\n if (startIndex === -1) {\n return <>{text}</>\n }\n\n const before = text.slice(0, startIndex)\n const matched = text.slice(startIndex, startIndex + match.length)\n const after = text.slice(startIndex + match.length)\n\n return (\n <>\n {before}\n <strong class=\"mcp-autocomplete-highlight\">{matched}</strong>\n {after}\n </>\n )\n}\n\n/**\n * Default option renderer\n */\nconst DefaultOptionRenderer: Component<{\n option: AutocompleteOption\n isSelected: boolean\n highlightMatch?: string\n}> = (props) => {\n const displayLabel = createMemo(() =>\n props.option.label || props.option.value\n )\n\n return (\n <div class=\"mcp-autocomplete-option-content\">\n <Show when={props.option.icon}>\n <span class=\"mcp-autocomplete-option-icon\">{props.option.icon}</span>\n </Show>\n <div class=\"mcp-autocomplete-option-text\">\n <span class=\"mcp-autocomplete-option-label\">\n {highlightText(displayLabel(), props.highlightMatch)}\n </span>\n <Show when={props.option.description}>\n <span class=\"mcp-autocomplete-option-description\">\n {props.option.description}\n </span>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * AutocompleteDropdown Component\n */\nexport const AutocompleteDropdown: Component<AutocompleteDropdownProps> = (props) => {\n const strings = useMCPUIStrings()\n const positionStyles = createMemo((): JSX.CSSProperties => {\n if (props.position === 'top') {\n return {\n bottom: '100%',\n 'margin-bottom': '4px'\n }\n }\n return {\n top: '100%',\n 'margin-top': '4px'\n }\n })\n\n const containerStyles = createMemo((): JSX.CSSProperties => ({\n position: 'absolute',\n left: '0',\n right: '0',\n 'z-index': '50',\n 'background-color': '#ffffff',\n border: '1px solid #e5e7eb',\n 'border-radius': '6px',\n 'box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n 'max-height': props.maxHeight || '240px',\n overflow: 'auto',\n ...positionStyles()\n }))\n\n return (\n <Show when={props.isOpen}>\n <div\n class={`mcp-autocomplete-dropdown ${props.class || ''}`}\n style={containerStyles()}\n role=\"listbox\"\n aria-label={strings.autocompleteSuggestions}\n >\n {/* Loading state */}\n <Show when={props.isLoading}>\n <div\n class=\"mcp-autocomplete-loading\"\n style={{\n padding: '12px 16px',\n color: '#6b7280',\n 'font-size': '0.875rem',\n display: 'flex',\n 'align-items': 'center',\n gap: '8px'\n }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '14px',\n height: '14px',\n border: '2px solid #e5e7eb',\n 'border-top-color': '#3b82f6',\n 'border-radius': '50%',\n animation: 'mcp-spin 0.6s linear infinite'\n }}\n />\n {props.loadingMessage || strings.autocompleteLoading}\n </div>\n </Show>\n\n {/* Empty state */}\n <Show when={!props.isLoading && props.options.length === 0}>\n <div\n class=\"mcp-autocomplete-empty\"\n style={{\n padding: '12px 16px',\n color: '#9ca3af',\n 'font-size': '0.875rem',\n 'text-align': 'center'\n }}\n >\n {props.emptyMessage || strings.autocompleteEmpty}\n </div>\n </Show>\n\n {/* Options list */}\n <Show when={!props.isLoading && props.options.length > 0}>\n <ul\n class=\"mcp-autocomplete-options\"\n style={{ margin: '0', padding: '4px 0', 'list-style': 'none' }}\n >\n <For each={props.options}>\n {(option, index) => {\n const isSelected = () => index() === props.selectedIndex\n const isDisabled = () => option.disabled\n\n return (\n <li\n role=\"option\"\n aria-selected={isSelected()}\n aria-disabled={isDisabled()}\n class={`mcp-autocomplete-option ${isSelected() ? 'mcp-autocomplete-option-selected' : ''} ${isDisabled() ? 'mcp-autocomplete-option-disabled' : ''}`}\n style={{\n padding: '8px 16px',\n cursor: isDisabled() ? 'not-allowed' : 'pointer',\n 'background-color': isSelected() ? '#eff6ff' : 'transparent',\n color: isDisabled() ? '#9ca3af' : '#374151',\n 'font-size': '0.875rem',\n transition: 'background-color 150ms ease'\n }}\n onClick={() => {\n if (!isDisabled()) {\n props.onSelect(option)\n }\n }}\n onMouseEnter={() => {\n if (!isDisabled()) {\n props.onHover?.(index())\n }\n }}\n >\n <Show\n when={props.renderOption}\n fallback={\n <DefaultOptionRenderer\n option={option}\n isSelected={isSelected()}\n highlightMatch={props.highlightMatch}\n />\n }\n >\n {props.renderOption!(option, isSelected())}\n </Show>\n </li>\n )\n }}\n </For>\n </ul>\n </Show>\n\n {/* Footer hint */}\n <Show when={!props.isLoading && props.options.length > 0}>\n <div\n class=\"mcp-autocomplete-footer\"\n style={{\n padding: '6px 12px',\n 'border-top': '1px solid #e5e7eb',\n 'background-color': '#f9fafb',\n 'font-size': '0.75rem',\n color: '#6b7280'\n }}\n >\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>↑</kbd>\n {' '}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>↓</kbd>\n {strings.autocompleteHintNavigate}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>Enter</kbd>\n {strings.autocompleteHintSelect}\n <kbd style={{\n 'background-color': '#e5e7eb',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>Esc</kbd>\n {strings.autocompleteHintDismiss}\n </div>\n </Show>\n </div>\n </Show>\n )\n}\n\nexport default AutocompleteDropdown\n"],"names":["highlightText","text","match","lowerText","toLowerCase","lowerMatch","startIndex","indexOf","before","slice","matched","length","after","_el$","_$getNextElement","_tmpl$","_$insert","DefaultOptionRenderer","props","displayLabel","createMemo","option","label","value","_el$2","_tmpl$4","_el$9","firstChild","_el$0","_co$2","_$getNextMarker","nextSibling","_el$4","_el$5","_el$7","_el$8","_co$","_$createComponent","Show","when","icon","children","_el$3","_tmpl$2","highlightMatch","description","_el$6","_tmpl$3","AutocompleteDropdown","strings","useMCPUIStrings","positionStyles","position","bottom","top","containerStyles","left","right","border","maxHeight","overflow","isOpen","_el$1","_tmpl$9","_el$28","_el$29","_co$7","_el$30","_el$31","_co$8","_el$32","_el$33","_co$9","_el$34","_el$35","_co$0","isLoading","_el$10","_tmpl$5","_el$11","_el$12","_el$13","_co$3","loadingMessage","autocompleteLoading","_$memo","options","_el$14","_tmpl$6","emptyMessage","autocompleteEmpty","_el$15","_tmpl$7","For","each","index","isSelected","selectedIndex","isDisabled","disabled","_el$36","_tmpl$0","addEventListener","onHover","$$click","onSelect","renderOption","fallback","_$effect","_p$","_v$4","_v$5","_v$6","_v$7","_v$8","_v$9","e","_$setAttribute","t","a","_$className","o","_$setStyleProperty","i","n","undefined","_$runHydrationEvents","_el$16","_tmpl$8","_el$17","_el$18","_el$19","_el$22","_el$23","_co$4","_el$20","_el$24","_el$25","_co$5","_el$21","_el$26","_el$27","_co$6","autocompleteHintNavigate","autocompleteHintSelect","autocompleteHintDismiss","_v$","class","_v$2","_v$3","autocompleteSuggestions","_$style","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AutocompleteDropdown.cjs","sources":["../../src/components/AutocompleteDropdown.tsx"],"sourcesContent":["/**\n * AutocompleteDropdown Component\n * Displays data-driven dropdown suggestions\n *\n * Sprint Autocomplete Feature\n */\n\nimport { Component, For, Show, createMemo, JSX } from 'solid-js'\nimport type { AutocompleteOption } from '../types'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\n/**\n * Props for AutocompleteDropdown\n */\nexport interface AutocompleteDropdownProps {\n /**\n * Options to display\n */\n options: AutocompleteOption[]\n\n /**\n * Currently selected index\n */\n selectedIndex: number\n\n /**\n * Whether dropdown is visible\n */\n isOpen: boolean\n\n /**\n * Callback when option is selected\n */\n onSelect: (option: AutocompleteOption) => void\n\n /**\n * Callback when option is hovered\n */\n onHover?: (index: number) => void\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n\n /**\n * Custom class\n */\n class?: string\n\n /**\n * Max height\n */\n maxHeight?: string\n\n /**\n * Empty state message\n */\n emptyMessage?: string\n\n /**\n * Loading message\n */\n loadingMessage?: string\n\n /**\n * Highlight matching text in options\n */\n highlightMatch?: string\n\n /**\n * Position (default: 'bottom')\n */\n position?: 'top' | 'bottom'\n\n /**\n * Custom option renderer\n */\n renderOption?: (option: AutocompleteOption, isSelected: boolean) => JSX.Element\n}\n\n/**\n * Highlight matching text\n */\nfunction highlightText(text: string, match?: string): JSX.Element {\n if (!match || !text) {\n return <>{text}</>\n }\n\n const lowerText = text.toLowerCase()\n const lowerMatch = match.toLowerCase()\n const startIndex = lowerText.indexOf(lowerMatch)\n\n if (startIndex === -1) {\n return <>{text}</>\n }\n\n const before = text.slice(0, startIndex)\n const matched = text.slice(startIndex, startIndex + match.length)\n const after = text.slice(startIndex + match.length)\n\n return (\n <>\n {before}\n <strong class=\"mcp-autocomplete-highlight\">{matched}</strong>\n {after}\n </>\n )\n}\n\n/**\n * Default option renderer\n */\nconst DefaultOptionRenderer: Component<{\n option: AutocompleteOption\n isSelected: boolean\n highlightMatch?: string\n}> = (props) => {\n const displayLabel = createMemo(() =>\n props.option.label || props.option.value\n )\n\n return (\n <div class=\"mcp-autocomplete-option-content\">\n <Show when={props.option.icon}>\n <span class=\"mcp-autocomplete-option-icon\">{props.option.icon}</span>\n </Show>\n <div class=\"mcp-autocomplete-option-text\">\n <span class=\"mcp-autocomplete-option-label\">\n {highlightText(displayLabel(), props.highlightMatch)}\n </span>\n <Show when={props.option.description}>\n <span class=\"mcp-autocomplete-option-description\">\n {props.option.description}\n </span>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * AutocompleteDropdown Component\n */\nexport const AutocompleteDropdown: Component<AutocompleteDropdownProps> = (props) => {\n const strings = useMCPUIStrings()\n const positionStyles = createMemo((): JSX.CSSProperties => {\n if (props.position === 'top') {\n return {\n bottom: '100%',\n 'margin-bottom': '4px'\n }\n }\n return {\n top: '100%',\n 'margin-top': '4px'\n }\n })\n\n const containerStyles = createMemo((): JSX.CSSProperties => ({\n position: 'absolute',\n left: '0',\n right: '0',\n 'z-index': '50',\n 'background-color': 'var(--mcp-ui-surface, #ffffff)',\n border: '1px solid var(--mcp-ui-border, #e5e7eb)',\n 'border-radius': '6px',\n '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))',\n 'max-height': props.maxHeight || '240px',\n overflow: 'auto',\n ...positionStyles()\n }))\n\n return (\n <Show when={props.isOpen}>\n <div\n class={`mcp-ui-root mcp-autocomplete-dropdown ${props.class || ''}`}\n style={containerStyles()}\n role=\"listbox\"\n aria-label={strings.autocompleteSuggestions}\n >\n {/* Loading state */}\n <Show when={props.isLoading}>\n <div\n class=\"mcp-autocomplete-loading\"\n style={{\n padding: '12px 16px',\n color: 'var(--mcp-ui-fg-muted, #6b7280)',\n 'font-size': '0.875rem',\n display: 'flex',\n 'align-items': 'center',\n gap: '8px'\n }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '14px',\n height: '14px',\n border: '2px solid var(--mcp-ui-border, #e5e7eb)',\n 'border-top-color': 'var(--mcp-ui-accent, #3b82f6)',\n 'border-radius': '50%',\n animation: 'mcp-spin 0.6s linear infinite'\n }}\n />\n {props.loadingMessage || strings.autocompleteLoading}\n </div>\n </Show>\n\n {/* Empty state */}\n <Show when={!props.isLoading && props.options.length === 0}>\n <div\n class=\"mcp-autocomplete-empty\"\n style={{\n padding: '12px 16px',\n color: 'var(--mcp-ui-fg-subtle, #9ca3af)',\n 'font-size': '0.875rem',\n 'text-align': 'center'\n }}\n >\n {props.emptyMessage || strings.autocompleteEmpty}\n </div>\n </Show>\n\n {/* Options list */}\n <Show when={!props.isLoading && props.options.length > 0}>\n <ul\n class=\"mcp-autocomplete-options\"\n style={{ margin: '0', padding: '4px 0', 'list-style': 'none' }}\n >\n <For each={props.options}>\n {(option, index) => {\n const isSelected = () => index() === props.selectedIndex\n const isDisabled = () => option.disabled\n\n return (\n <li\n role=\"option\"\n aria-selected={isSelected()}\n aria-disabled={isDisabled()}\n class={`mcp-autocomplete-option ${isSelected() ? 'mcp-autocomplete-option-selected' : ''} ${isDisabled() ? 'mcp-autocomplete-option-disabled' : ''}`}\n style={{\n padding: '8px 16px',\n cursor: isDisabled() ? 'not-allowed' : 'pointer',\n 'background-color': isSelected() ? 'var(--mcp-ui-accent-soft, #eff6ff)' : 'transparent',\n color: isDisabled() ? 'var(--mcp-ui-fg-subtle, #9ca3af)' : 'var(--mcp-ui-fg, #374151)',\n 'font-size': '0.875rem',\n transition: 'background-color 150ms ease'\n }}\n onClick={() => {\n if (!isDisabled()) {\n props.onSelect(option)\n }\n }}\n onMouseEnter={() => {\n if (!isDisabled()) {\n props.onHover?.(index())\n }\n }}\n >\n <Show\n when={props.renderOption}\n fallback={\n <DefaultOptionRenderer\n option={option}\n isSelected={isSelected()}\n highlightMatch={props.highlightMatch}\n />\n }\n >\n {props.renderOption!(option, isSelected())}\n </Show>\n </li>\n )\n }}\n </For>\n </ul>\n </Show>\n\n {/* Footer hint */}\n <Show when={!props.isLoading && props.options.length > 0}>\n <div\n class=\"mcp-autocomplete-footer\"\n style={{\n padding: '6px 12px',\n 'border-top': '1px solid var(--mcp-ui-border, #e5e7eb)',\n 'background-color': 'var(--mcp-ui-surface-muted, #f9fafb)',\n 'font-size': '0.75rem',\n color: 'var(--mcp-ui-fg-muted, #6b7280)'\n }}\n >\n <kbd style={{\n 'background-color': 'var(--mcp-ui-surface-hover, #e5e7eb)',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>↑</kbd>\n {' '}\n <kbd style={{\n 'background-color': 'var(--mcp-ui-surface-hover, #e5e7eb)',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>↓</kbd>\n {strings.autocompleteHintNavigate}\n <kbd style={{\n 'background-color': 'var(--mcp-ui-surface-hover, #e5e7eb)',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>Enter</kbd>\n {strings.autocompleteHintSelect}\n <kbd style={{\n 'background-color': 'var(--mcp-ui-surface-hover, #e5e7eb)',\n padding: '1px 4px',\n 'border-radius': '2px',\n 'font-family': 'inherit',\n 'font-size': '0.7rem'\n }}>Esc</kbd>\n {strings.autocompleteHintDismiss}\n </div>\n </Show>\n </div>\n </Show>\n )\n}\n\nexport default AutocompleteDropdown\n"],"names":["highlightText","text","match","lowerText","toLowerCase","lowerMatch","startIndex","indexOf","before","slice","matched","length","after","_el$","_$getNextElement","_tmpl$","_$insert","DefaultOptionRenderer","props","displayLabel","createMemo","option","label","value","_el$2","_tmpl$4","_el$9","firstChild","_el$0","_co$2","_$getNextMarker","nextSibling","_el$4","_el$5","_el$7","_el$8","_co$","_$createComponent","Show","when","icon","children","_el$3","_tmpl$2","highlightMatch","description","_el$6","_tmpl$3","AutocompleteDropdown","strings","useMCPUIStrings","positionStyles","position","bottom","top","containerStyles","left","right","border","maxHeight","overflow","isOpen","_el$1","_tmpl$9","_el$28","_el$29","_co$7","_el$30","_el$31","_co$8","_el$32","_el$33","_co$9","_el$34","_el$35","_co$0","isLoading","_el$10","_tmpl$5","_el$11","_el$12","_el$13","_co$3","loadingMessage","autocompleteLoading","_$memo","options","_el$14","_tmpl$6","emptyMessage","autocompleteEmpty","_el$15","_tmpl$7","For","each","index","isSelected","selectedIndex","isDisabled","disabled","_el$36","_tmpl$0","addEventListener","onHover","$$click","onSelect","renderOption","fallback","_$effect","_p$","_v$4","_v$5","_v$6","_v$7","_v$8","_v$9","e","_$setAttribute","t","a","_$className","o","_$setStyleProperty","i","n","undefined","_$runHydrationEvents","_el$16","_tmpl$8","_el$17","_el$18","_el$19","_el$22","_el$23","_co$4","_el$20","_el$24","_el$25","_co$5","_el$21","_el$26","_el$27","_co$6","autocompleteHintNavigate","autocompleteHintSelect","autocompleteHintDismiss","_v$","class","_v$2","_v$3","autocompleteSuggestions","_$style","_$delegateEvents"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createComponent, getNextElement, getNextMarker, insert, memo, effect, setAttribute, className, setStyleProperty, runHydrationEvents, style, template, delegateEvents } from "solid-js/web";
|
|
2
2
|
import { createMemo, Show, For } from "solid-js";
|
|
3
3
|
import { useMCPUIStrings } from "../context/MCPUIStringsContext.js";
|
|
4
|
-
var _tmpl$ = /* @__PURE__ */ template(`<strong class=mcp-autocomplete-highlight>`), _tmpl$2 = /* @__PURE__ */ template(`<span class=mcp-autocomplete-option-icon>`), _tmpl$3 = /* @__PURE__ */ template(`<span class=mcp-autocomplete-option-description>`), _tmpl$4 = /* @__PURE__ */ template(`<div class=mcp-autocomplete-option-content><!$><!/><div class=mcp-autocomplete-option-text><span class=mcp-autocomplete-option-label></span><!$><!/>`), _tmpl$5 = /* @__PURE__ */ template(`<div class=mcp-autocomplete-loading style="padding:12px 16px;color
|
|
4
|
+
var _tmpl$ = /* @__PURE__ */ template(`<strong class=mcp-autocomplete-highlight>`), _tmpl$2 = /* @__PURE__ */ template(`<span class=mcp-autocomplete-option-icon>`), _tmpl$3 = /* @__PURE__ */ template(`<span class=mcp-autocomplete-option-description>`), _tmpl$4 = /* @__PURE__ */ template(`<div class=mcp-autocomplete-option-content><!$><!/><div class=mcp-autocomplete-option-text><span class=mcp-autocomplete-option-label></span><!$><!/>`), _tmpl$5 = /* @__PURE__ */ 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__ */ 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__ */ template(`<ul class=mcp-autocomplete-options style="margin:0;padding:4px 0;list-style:none">`), _tmpl$8 = /* @__PURE__ */ 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__ */ template(`<div role=listbox><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$0 = /* @__PURE__ */ template(`<li role=option style="padding:8px 16px;font-size:0.875rem;transition:background-color 150ms ease">`);
|
|
5
5
|
function highlightText(text, match) {
|
|
6
6
|
if (!match || !text) {
|
|
7
7
|
return text;
|
|
@@ -68,10 +68,10 @@ const AutocompleteDropdown = (props) => {
|
|
|
68
68
|
left: "0",
|
|
69
69
|
right: "0",
|
|
70
70
|
"z-index": "50",
|
|
71
|
-
"background-color": "#ffffff",
|
|
72
|
-
border: "1px solid #e5e7eb",
|
|
71
|
+
"background-color": "var(--mcp-ui-surface, #ffffff)",
|
|
72
|
+
border: "1px solid var(--mcp-ui-border, #e5e7eb)",
|
|
73
73
|
"border-radius": "6px",
|
|
74
|
-
"box-shadow": "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
74
|
+
"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))",
|
|
75
75
|
"max-height": props.maxHeight || "240px",
|
|
76
76
|
overflow: "auto",
|
|
77
77
|
...positionStyles()
|
|
@@ -148,7 +148,7 @@ const AutocompleteDropdown = (props) => {
|
|
|
148
148
|
}
|
|
149
149
|
}));
|
|
150
150
|
effect((_p$) => {
|
|
151
|
-
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";
|
|
151
|
+
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)";
|
|
152
152
|
_v$4 !== _p$.e && setAttribute(_el$36, "aria-selected", _p$.e = _v$4);
|
|
153
153
|
_v$5 !== _p$.t && setAttribute(_el$36, "aria-disabled", _p$.t = _v$5);
|
|
154
154
|
_v$6 !== _p$.a && className(_el$36, _p$.a = _v$6);
|
|
@@ -185,7 +185,7 @@ const AutocompleteDropdown = (props) => {
|
|
|
185
185
|
}
|
|
186
186
|
}), _el$35, _co$0);
|
|
187
187
|
effect((_p$) => {
|
|
188
|
-
var _v$ = `mcp-autocomplete-dropdown ${props.class || ""}`, _v$2 = containerStyles(), _v$3 = strings.autocompleteSuggestions;
|
|
188
|
+
var _v$ = `mcp-ui-root mcp-autocomplete-dropdown ${props.class || ""}`, _v$2 = containerStyles(), _v$3 = strings.autocompleteSuggestions;
|
|
189
189
|
_v$ !== _p$.e && className(_el$1, _p$.e = _v$);
|
|
190
190
|
_p$.t = style(_el$1, _v$2, _p$.t);
|
|
191
191
|
_v$3 !== _p$.a && setAttribute(_el$1, "aria-label", _p$.a = _v$3);
|