@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
|
@@ -3,7 +3,7 @@ import { Show, For } from "solid-js";
|
|
|
3
3
|
import { useMCPUIStrings } from "../context/MCPUIStringsContext.js";
|
|
4
4
|
import { MissingValueMark, MissingValueLegend } from "./MissingValue.js";
|
|
5
5
|
import { formatMCPUIString } from "../utils/format-string.js";
|
|
6
|
-
var _tmpl$ = /* @__PURE__ */ template(`<div class="mt-2 max-h-64 overflow-auto rounded border border-amber-200 dark:border-amber-800"><table class="w-full border-collapse text-left text-xs"><thead class="sticky top-0 bg-amber-100 dark:bg-amber-900
|
|
6
|
+
var _tmpl$ = /* @__PURE__ */ template(`<div class="mt-2 max-h-64 overflow-auto rounded border border-[color:var(--mcp-ui-warning-border,var(--color-amber-200))] dark:border-[color:var(--mcp-ui-warning-border,var(--color-amber-800))]"><table class="w-full border-collapse text-left text-xs"><thead class="sticky top-0 bg-[color:var(--mcp-ui-warning-soft,var(--color-amber-100))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-amber-900)_40%,transparent))]"><tr></tr></thead><tbody>`), _tmpl$2 = /* @__PURE__ */ template(`<p class="mt-1 text-[10px] text-[color:var(--mcp-ui-warning,var(--color-amber-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-400))]">`), _tmpl$3 = /* @__PURE__ */ template(`<div class="w-full rounded-lg border border-[color:var(--mcp-ui-warning-border,var(--color-amber-200))] bg-[color:var(--mcp-ui-warning-soft,var(--color-amber-50))] p-3 dark:border-[color:var(--mcp-ui-warning-border,var(--color-amber-800))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-amber-900)_20%,transparent))]"role=alert><p class="text-sm font-medium text-[color:var(--mcp-ui-warning,var(--color-amber-900))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-100))]"></p><p class="mt-0.5 text-xs text-[color:var(--mcp-ui-warning,var(--color-amber-700))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-300))]"></p><!$><!/>`), _tmpl$4 = /* @__PURE__ */ template(`<th class="px-2 py-1 font-medium text-[color:var(--mcp-ui-warning,var(--color-amber-900))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-100))]">`), _tmpl$5 = /* @__PURE__ */ template(`<tr class="border-t border-[color:var(--mcp-ui-warning-border,var(--color-amber-100))] dark:border-[color:var(--mcp-ui-warning-border,color-mix(in_oklab,var(--color-amber-800)_60%,transparent))]">`), _tmpl$6 = /* @__PURE__ */ template(`<td class="px-2 py-1 text-[color:var(--mcp-ui-warning,var(--color-amber-800))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-200))]">`);
|
|
7
7
|
const DegradedFallback = (props) => {
|
|
8
8
|
const strings = useMCPUIStrings();
|
|
9
9
|
const maxRows = () => props.maxRows ?? 50;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DegradedFallback.js","sources":["../../src/components/DegradedFallback.tsx"],"sourcesContent":["/**\n * DegradedFallback — the middle rung of the renderer fallback ladder\n * (audit 2026-05-30, P2.5).\n *\n * Each heavy renderer (graph / map / chart) follows the same contract:\n * 1. native render when its peer lib is available and succeeds;\n * 2. **degraded but useful** view when the native render throws — this\n * component: a visible notice + a plain data table so the user still\n * sees the underlying data instead of a blank space;\n * 3. (the caller also emits a `render:error` telemetry event).\n *\n * Pure / presentational — no peer deps, no side effects — so a render-path\n * failure in a heavy lib can never cascade into the fallback itself, and it\n * is trivially unit-testable. Rows/cells are rendered as text; callers are\n * responsible for stringifying complex cell values.\n */\n\nimport { Component, For, Show } from 'solid-js';\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext';\nimport { MissingValueLegend, MissingValueMark } from './MissingValue';\n\nexport interface DegradedFallbackProps {\n /** Short, human-readable reason the native render was skipped/failed. */\n message: string;\n /**\n * Column headers for the degraded data table. When omitted (or empty),\n * only the notice banner is shown.\n */\n columns?: string[];\n /** Row data — each row is an array of cells aligned to `columns`. */\n rows?: Array<Array<string | number>>;\n /**\n * Caption under the table. Defaults to a generic\n * \"interactive view unavailable\" line.\n */\n caption?: string;\n /** Max rows to render before truncating (default 50). */\n maxRows?: number;\n /**\n * Same shape as `rows`: `true` marks a cell whose value is missing, which\n * renders as `<MissingValueMark/>` instead of its text. A\n * `<MissingValueLegend/>` follows the table when a SHOWN cell is missing.\n * Omitted, the output is unchanged. @since v6.24.0\n */\n missing?: boolean[][];\n}\n\nexport const DegradedFallback: Component<DegradedFallbackProps> = (props) => {\n const strings = useMCPUIStrings();\n const maxRows = () => props.maxRows ?? 50;\n const allRows = () => props.rows ?? [];\n const shownRows = () => allRows().slice(0, maxRows());\n const hiddenCount = () => Math.max(0, allRows().length - shownRows().length);\n const isMissing = (rowIndex: number, colIndex: number) =>\n props.missing?.[rowIndex]?.[colIndex] === true;\n const anyShownMissing = () => {\n const columnCount = props.columns?.length ?? 0;\n return shownRows().some((_row, r) => {\n for (let c = 0; c < columnCount; c += 1) if (isMissing(r, c)) return true;\n return false;\n });\n };\n const hasTable = () => (props.columns?.length ?? 0) > 0 && allRows().length > 0;\n\n return (\n <div\n class=\"w-full rounded-lg border border-amber-200 bg-amber-50 p-3 dark:border-amber-800 dark:bg-amber-900
|
|
1
|
+
{"version":3,"file":"DegradedFallback.js","sources":["../../src/components/DegradedFallback.tsx"],"sourcesContent":["/**\n * DegradedFallback — the middle rung of the renderer fallback ladder\n * (audit 2026-05-30, P2.5).\n *\n * Each heavy renderer (graph / map / chart) follows the same contract:\n * 1. native render when its peer lib is available and succeeds;\n * 2. **degraded but useful** view when the native render throws — this\n * component: a visible notice + a plain data table so the user still\n * sees the underlying data instead of a blank space;\n * 3. (the caller also emits a `render:error` telemetry event).\n *\n * Pure / presentational — no peer deps, no side effects — so a render-path\n * failure in a heavy lib can never cascade into the fallback itself, and it\n * is trivially unit-testable. Rows/cells are rendered as text; callers are\n * responsible for stringifying complex cell values.\n */\n\nimport { Component, For, Show } from 'solid-js';\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext';\nimport { MissingValueLegend, MissingValueMark } from './MissingValue';\n\nexport interface DegradedFallbackProps {\n /** Short, human-readable reason the native render was skipped/failed. */\n message: string;\n /**\n * Column headers for the degraded data table. When omitted (or empty),\n * only the notice banner is shown.\n */\n columns?: string[];\n /** Row data — each row is an array of cells aligned to `columns`. */\n rows?: Array<Array<string | number>>;\n /**\n * Caption under the table. Defaults to a generic\n * \"interactive view unavailable\" line.\n */\n caption?: string;\n /** Max rows to render before truncating (default 50). */\n maxRows?: number;\n /**\n * Same shape as `rows`: `true` marks a cell whose value is missing, which\n * renders as `<MissingValueMark/>` instead of its text. A\n * `<MissingValueLegend/>` follows the table when a SHOWN cell is missing.\n * Omitted, the output is unchanged. @since v6.24.0\n */\n missing?: boolean[][];\n}\n\nexport const DegradedFallback: Component<DegradedFallbackProps> = (props) => {\n const strings = useMCPUIStrings();\n const maxRows = () => props.maxRows ?? 50;\n const allRows = () => props.rows ?? [];\n const shownRows = () => allRows().slice(0, maxRows());\n const hiddenCount = () => Math.max(0, allRows().length - shownRows().length);\n const isMissing = (rowIndex: number, colIndex: number) =>\n props.missing?.[rowIndex]?.[colIndex] === true;\n const anyShownMissing = () => {\n const columnCount = props.columns?.length ?? 0;\n return shownRows().some((_row, r) => {\n for (let c = 0; c < columnCount; c += 1) if (isMissing(r, c)) return true;\n return false;\n });\n };\n const hasTable = () => (props.columns?.length ?? 0) > 0 && allRows().length > 0;\n\n return (\n <div\n class=\"w-full rounded-lg border border-[color:var(--mcp-ui-warning-border,var(--color-amber-200))] bg-[color:var(--mcp-ui-warning-soft,var(--color-amber-50))] p-3 dark:border-[color:var(--mcp-ui-warning-border,var(--color-amber-800))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-amber-900)_20%,transparent))]\"\n role=\"alert\"\n >\n <p class=\"text-sm font-medium text-[color:var(--mcp-ui-warning,var(--color-amber-900))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-100))]\">{props.message}</p>\n <p class=\"mt-0.5 text-xs text-[color:var(--mcp-ui-warning,var(--color-amber-700))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-300))]\">\n {props.caption ?? strings.degradedCaption}\n </p>\n\n <Show when={hasTable()}>\n <div class=\"mt-2 max-h-64 overflow-auto rounded border border-[color:var(--mcp-ui-warning-border,var(--color-amber-200))] dark:border-[color:var(--mcp-ui-warning-border,var(--color-amber-800))]\">\n <table class=\"w-full border-collapse text-left text-xs\">\n <thead class=\"sticky top-0 bg-[color:var(--mcp-ui-warning-soft,var(--color-amber-100))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-amber-900)_40%,transparent))]\">\n <tr>\n <For each={props.columns}>\n {(col) => (\n <th class=\"px-2 py-1 font-medium text-[color:var(--mcp-ui-warning,var(--color-amber-900))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-100))]\">{col}</th>\n )}\n </For>\n </tr>\n </thead>\n <tbody>\n <For each={shownRows()}>\n {(row, rowIndex) => (\n <tr class=\"border-t border-[color:var(--mcp-ui-warning-border,var(--color-amber-100))] dark:border-[color:var(--mcp-ui-warning-border,color-mix(in_oklab,var(--color-amber-800)_60%,transparent))]\">\n <For each={props.columns}>\n {(_col, i) => (\n <td class=\"px-2 py-1 text-[color:var(--mcp-ui-warning,var(--color-amber-800))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-200))]\">\n <Show when={isMissing(rowIndex(), i())} fallback={String(row[i()] ?? '')}>\n <MissingValueMark />\n </Show>\n </td>\n )}\n </For>\n </tr>\n )}\n </For>\n </tbody>\n </table>\n </div>\n <Show when={anyShownMissing()}>\n <MissingValueLegend class=\"mt-2\" />\n </Show>\n <Show when={hiddenCount() > 0}>\n <p class=\"mt-1 text-[10px] text-[color:var(--mcp-ui-warning,var(--color-amber-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-amber-400))]\">\n {formatMCPUIString(strings.degradedMoreRows, { count: hiddenCount() })}\n </p>\n </Show>\n </Show>\n </div>\n );\n};\n"],"names":["DegradedFallback","props","strings","useMCPUIStrings","maxRows","allRows","rows","shownRows","slice","hiddenCount","Math","max","length","isMissing","rowIndex","colIndex","missing","anyShownMissing","columnCount","columns","some","_row","r","c","hasTable","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","nextSibling","_el$0","_el$1","_co$","_$getNextMarker","_$insert","message","caption","degradedCaption","_$createComponent","Show","when","children","_el$4","_tmpl$","_el$5","_el$6","_el$7","_el$8","For","each","col","_el$10","_tmpl$4","row","_el$11","_tmpl$5","_col","i","_el$12","_tmpl$6","fallback","String","MissingValueMark","MissingValueLegend","_el$9","_tmpl$2","formatMCPUIString","degradedMoreRows","count"],"mappings":";;;;;;AA+CO,MAAMA,mBAAsDC,CAAAA,UAAU;AAC3E,QAAMC,UAAUC,gBAAAA;AAChB,QAAMC,UAAUA,MAAMH,MAAMG,WAAW;AACvC,QAAMC,UAAUA,MAAMJ,MAAMK,QAAQ,CAAA;AACpC,QAAMC,YAAYA,MAAMF,QAAAA,EAAUG,MAAM,GAAGJ,SAAS;AACpD,QAAMK,cAAcA,MAAMC,KAAKC,IAAI,GAAGN,UAAUO,SAASL,UAAAA,EAAYK,MAAM;AAC3E,QAAMC,YAAYA,CAACC,UAAkBC,aAAAA;;AACnCd,8BAAMe,YAANf,mBAAgBa,cAAhBb,mBAA4Bc,eAAc;AAAA;AAC5C,QAAME,kBAAkBA,MAAM;;AAC5B,UAAMC,gBAAcjB,WAAMkB,YAANlB,mBAAeW,WAAU;AAC7C,WAAOL,UAAAA,EAAYa,KAAK,CAACC,MAAMC,MAAM;AACnC,eAASC,IAAI,GAAGA,IAAIL,aAAaK,KAAK,EAAG,KAAIV,UAAUS,GAAGC,CAAC,EAAG,QAAO;AACrE,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,QAAMC,WAAWA,MAAAA;;AAAOvB,yBAAMkB,YAANlB,mBAAeW,WAAU,KAAK,KAAKP,UAAUO,SAAS;AAAA;AAE9E,UAAA,MAAA;AAAA,QAAAa,OAAAC,eAAAC,OAAA,GAAAC,QAAAH,KAAAI,YAAAC,QAAAF,MAAAG,aAAAC,QAAAF,MAAAC,aAAA,CAAAE,OAAAC,IAAA,IAAAC,cAAAH,MAAAD,WAAA;AAAAK,WAAAR,OAAA,MAK6J3B,MAAMoC,OAAO;AAAAD,WAAAN,OAAA,MAEnK7B,MAAMqC,WAAWpC,QAAQqC,eAAe;AAAAH,WAAAX,MAAAe,gBAG1CC,MAAI;AAAA,MAAA,IAACC,OAAI;AAAA,eAAElB,SAAAA;AAAAA,MAAU;AAAA,MAAA,IAAAmB,WAAA;AAAA,eAAA,EAAA,MAAA;AAAA,cAAAC,QAAAlB,eAAAmB,MAAA,GAAAC,QAAAF,MAAAf,YAAAkB,QAAAD,MAAAjB,YAAAmB,QAAAD,MAAAlB,YAAAoB,QAAAF,MAAAhB;AAAAK,iBAAAY,OAAAR,gBAKXU,KAAG;AAAA,YAAA,IAACC,OAAI;AAAA,qBAAElD,MAAMkB;AAAAA,YAAO;AAAA,YAAAwB,UACpBS,UAAG,MAAA;AAAA,kBAAAC,SAAA3B,eAAA4B,OAAA;AAAAlB,qBAAAiB,QACyJD,GAAG;AAAA,qBAAAC;AAAAA,YAAA,GAAA;AAAA,UAAA,CAChK,CAAA;AAAAjB,iBAAAa,OAAAT,gBAKJU,KAAG;AAAA,YAAA,IAACC,OAAI;AAAA,qBAAE5C,UAAAA;AAAAA,YAAW;AAAA,YAAAoC,UACnBA,CAACY,KAAKzC,cAAQ,MAAA;AAAA,kBAAA0C,SAAA9B,eAAA+B,OAAA;AAAArB,qBAAAoB,QAAAhB,gBAEVU,KAAG;AAAA,gBAAA,IAACC,OAAI;AAAA,yBAAElD,MAAMkB;AAAAA,gBAAO;AAAA,gBAAAwB,UACrBA,CAACe,MAAMC,OAAC,MAAA;AAAA,sBAAAC,SAAAlC,eAAAmC,OAAA;AAAAzB,yBAAAwB,QAAApB,gBAEJC,MAAI;AAAA,oBAAA,IAACC,OAAI;AAAA,6BAAE7B,UAAUC,YAAY6C,GAAG;AAAA,oBAAC;AAAA,oBAAA,IAAEG,WAAQ;AAAA,6BAAEC,OAAOR,IAAII,EAAAA,CAAG,KAAK,EAAE;AAAA,oBAAC;AAAA,oBAAA,IAAAhB,WAAA;AAAA,6BAAAH,gBACrEwB,kBAAgB,EAAA;AAAA,oBAAA;AAAA,kBAAA,CAAA,CAAA;AAAA,yBAAAJ;AAAAA,gBAAA,GAAA;AAAA,cAAA,CAGtB,CAAA;AAAA,qBAAAJ;AAAAA,YAAA,GAAA;AAAA,UAAA,CAGN,CAAA;AAAA,iBAAAZ;AAAAA,QAAA,GAAA,GAAAJ,gBAKRC,MAAI;AAAA,UAAA,IAACC,OAAI;AAAA,mBAAEzB,gBAAAA;AAAAA,UAAiB;AAAA,UAAA,IAAA0B,WAAA;AAAA,mBAAAH,gBAC1ByB,oBAAkB;AAAA,cAAA,SAAA;AAAA,YAAA,CAAA;AAAA,UAAA;AAAA,QAAA,CAAA,GAAAzB,gBAEpBC,MAAI;AAAA,UAAA,IAACC,OAAI;AAAA,mBAAEjC,gBAAgB;AAAA,UAAC;AAAA,UAAA,IAAAkC,WAAA;AAAA,gBAAAuB,QAAAxC,eAAAyC,OAAA;AAAA/B,mBAAA8B,OAAA,MAExBE,kBAAkBlE,QAAQmE,kBAAkB;AAAA,cAAEC,OAAO7D,YAAAA;AAAAA,YAAY,CAAG,CAAC;AAAA,mBAAAyD;AAAAA,UAAA;AAAA,QAAA,CAAA,CAAA;AAAA,MAAA;AAAA,IAAA,CAAA,GAAAjC,OAAAC,IAAA;AAAA,WAAAT;AAAAA,EAAA,GAAA;AAMlF;"}
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const web = require("solid-js/web");
|
|
4
4
|
const solidJs = require("solid-js");
|
|
5
|
+
const theme = require("../utils/theme.cjs");
|
|
5
6
|
const MCPUIStringsContext = require("../context/MCPUIStringsContext.cjs");
|
|
6
|
-
var _tmpl$ = /* @__PURE__ */ web.template(`<svg class="w-5 h-5"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">`), _tmpl$2 = /* @__PURE__ */ web.template(`<button type=button class="p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"data-mcp-ui-action=copy>`), _tmpl$3 = /* @__PURE__ */ web.template(`<div class="fixed inset-0 z-50 flex flex-col bg-black
|
|
7
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<svg class="w-5 h-5"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">`), _tmpl$2 = /* @__PURE__ */ web.template(`<button type=button class="p-1.5 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] hover:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:hover:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-full 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))] transition-colors"data-mcp-ui-action=copy>`), _tmpl$3 = /* @__PURE__ */ web.template(`<div class="fixed inset-0 z-50 flex flex-col bg-[color:var(--mcp-ui-overlay,color-mix(in_oklab,var(--color-black,#000)_50%,transparent))] backdrop-blur-sm"role=dialog data-mcp-ui-portal=dialog aria-modal=true tabindex=-1 style="animation:expandable-fade-in 0.15s ease-out"><div class="relative flex flex-col m-4 flex-1 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] rounded-lg shadow-[var(--mcp-ui-shadow,var(--shadow-xl))] overflow-hidden"style="animation:expandable-scale-in 0.15s ease-out"><div class="flex items-center justify-between px-4 py-3 border-b border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))] flex-shrink-0"><h2 class="text-lg font-semibold text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] truncate"></h2><div class="flex items-center gap-2"><!$><!/><button type=button class="p-1.5 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] hover:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:hover:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-full 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))] transition-colors"data-mcp-ui-action=close><svg class="w-5 h-5"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M6 18L18 6M6 6l12 12"></path></svg></button></div></div><div class="flex-1 min-h-0 overflow-auto p-4 flex flex-col">`), _tmpl$4 = /* @__PURE__ */ web.template(`<style>
|
|
7
8
|
@keyframes expandable-fade-in {
|
|
8
9
|
from { opacity: 0; }
|
|
9
10
|
to { opacity: 1; }
|
|
@@ -12,7 +13,7 @@ var _tmpl$ = /* @__PURE__ */ web.template(`<svg class="w-5 h-5"fill=none viewBox
|
|
|
12
13
|
from { opacity: 0; transform: scale(0.97); }
|
|
13
14
|
to { opacity: 1; transform: scale(1); }
|
|
14
15
|
}
|
|
15
|
-
`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class="relative group"><div><div></div></div><button type=button data-mcp-ui-action=expand><svg class="w-3.5 h-3.5 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5"></path></svg></button><!$><!/>`), _tmpl$6 = /* @__PURE__ */ web.template(`<svg class="w-5 h-5 text-green-500"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M5 13l4 4L19 7">`);
|
|
16
|
+
`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class="mcp-ui-root relative group"><div><div></div></div><button type=button data-mcp-ui-action=expand><svg class="w-3.5 h-3.5 text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5"></path></svg></button><!$><!/>`), _tmpl$6 = /* @__PURE__ */ web.template(`<svg class="w-5 h-5 text-[color:var(--mcp-ui-success,var(--color-green-500))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M5 13l4 4L19 7">`);
|
|
16
17
|
const ExpandedContext = solidJs.createContext(() => false);
|
|
17
18
|
const useExpanded = () => solidJs.useContext(ExpandedContext);
|
|
18
19
|
const ExpandableWrapper = (props) => {
|
|
@@ -100,8 +101,10 @@ const ExpandableWrapper = (props) => {
|
|
|
100
101
|
get children() {
|
|
101
102
|
return [(() => {
|
|
102
103
|
var _el$5 = web.getNextElement(_tmpl$3), _el$6 = _el$5.firstChild, _el$7 = _el$6.firstChild, _el$8 = _el$7.firstChild, _el$9 = _el$8.nextSibling, _el$11 = _el$9.firstChild, [_el$12, _co$] = web.getNextMarker(_el$11.nextSibling), _el$10 = _el$12.nextSibling, _el$13 = _el$7.nextSibling;
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
web.use((element) => {
|
|
105
|
+
dialogRef = element;
|
|
106
|
+
theme.bindPortalTheme(element, () => inlineSlotRef);
|
|
107
|
+
}, _el$5);
|
|
105
108
|
_el$5.$$pointerdown = handleBackdropPointerDown;
|
|
106
109
|
_el$5.$$click = handleBackdropClick;
|
|
107
110
|
_el$6.$$click = (e) => e.stopPropagation();
|
|
@@ -138,8 +141,8 @@ const ExpandableWrapper = (props) => {
|
|
|
138
141
|
}
|
|
139
142
|
}), _el$12, _co$);
|
|
140
143
|
_el$10.$$click = handleClose;
|
|
141
|
-
var _ref$
|
|
142
|
-
typeof _ref$
|
|
144
|
+
var _ref$3 = modalSlotRef;
|
|
145
|
+
typeof _ref$3 === "function" ? web.use(_ref$3, _el$13) : modalSlotRef = _el$13;
|
|
143
146
|
web.effect((_p$) => {
|
|
144
147
|
var _v$3 = props.title || strings.expandedView, _v$4 = strings.closeExpandedView;
|
|
145
148
|
_v$3 !== _p$.e && web.setAttribute(_el$5, "aria-label", _p$.e = _v$3);
|
|
@@ -157,7 +160,7 @@ const ExpandableWrapper = (props) => {
|
|
|
157
160
|
}
|
|
158
161
|
}), _el$16, _co$2);
|
|
159
162
|
web.effect((_p$) => {
|
|
160
|
-
var _v$5 = `absolute top-2 right-2 z-10 ${props.toolbarVariant === "always-visible" ? "opacity-60 hover:opacity-100" : "opacity-0 group-hover:opacity-70 hover:!opacity-100"} p-1.5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm`, _v$6 = strings.expand, _v$7 = strings.expand;
|
|
163
|
+
var _v$5 = `absolute top-2 right-2 z-10 ${props.toolbarVariant === "always-visible" ? "opacity-60 hover:opacity-100" : "opacity-0 group-hover:opacity-70 hover:!opacity-100"} p-1.5 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] rounded-full 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))] transition-all shadow-[var(--mcp-ui-shadow,var(--shadow-sm))]`, _v$6 = strings.expand, _v$7 = strings.expand;
|
|
161
164
|
_v$5 !== _p$.e && web.className(_el$4, _p$.e = _v$5);
|
|
162
165
|
_v$6 !== _p$.t && web.setAttribute(_el$4, "title", _p$.t = _v$6);
|
|
163
166
|
_v$7 !== _p$.a && web.setAttribute(_el$4, "aria-label", _p$.a = _v$7);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpandableWrapper.cjs","sources":["../../src/components/ExpandableWrapper.tsx"],"sourcesContent":["/**\n * ExpandableWrapper - Generic expand/fullscreen wrapper for components\n * v2.2.0: Reusable wrapper that adds expand button + fullscreen modal\n *\n * Uses DOM reparenting to avoid rendering children twice — critical for\n * imperative components like ChartJS that bind instances to DOM nodes.\n */\n\nimport { Component, Show, createSignal, createEffect, onCleanup, JSX, createContext, useContext, Accessor } from 'solid-js'\nimport { Portal } from 'solid-js/web'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\n/** Context for child components to know if they're in expanded/fullscreen view */\nconst ExpandedContext = createContext<Accessor<boolean>>(() => false)\n\n/** Hook for child components to read expanded state */\nexport const useExpanded = () => useContext(ExpandedContext)\n\nexport interface ExpandableWrapperProps {\n /** Content to render inline (and in expanded view) */\n children: JSX.Element\n /** Title shown in the expanded modal header */\n title?: string\n /** Data string for copy-to-clipboard in expanded view */\n copyData?: string\n /** Label for copy button tooltip */\n copyLabel?: string\n /**\n * Visibility behavior of the inline expand button (v6.3.0 — axe 4 deposium handoff).\n * - `'hover'` (default) : opacity 0, fades to 0.7 on parent group hover.\n * Backwards-compatible — pre-v6.3.0 behavior.\n * - `'always-visible'` : opacity 0.6 permanent, 1 on hover. Use this when\n * the inline button needs to be discoverable without hovering — esp.\n * on touch surfaces and consumer themes where the hover-only pattern\n * hides the affordance.\n */\n toolbarVariant?: 'hover' | 'always-visible'\n /**\n * Called with the expanded state on mount and whenever it changes (v6.19.0).\n * Needed by renderers that render their own `<ExpandableWrapper>`: their\n * `useExpanded()` call sits ABOVE the wrapper's context provider and would\n * only ever see an outer wrapper.\n */\n onExpandedChange?: (expanded: boolean) => void\n}\n\n/**\n * Wraps any component with an expand button (top-right corner).\n * Opens a fullscreen Portal modal. The children's DOM is physically\n * reparented into the modal (not duplicated), so imperative bindings\n * like Chart.js canvas refs stay intact.\n *\n * @example\n * <ExpandableWrapper title=\"Sales Data\" copyData={tsvData}>\n * <TableRenderer ... />\n * </ExpandableWrapper>\n */\nexport const ExpandableWrapper: Component<ExpandableWrapperProps> = (props) => {\n const [isExpanded, setIsExpanded] = createSignal(false)\n const [copied, setCopied] = createSignal(false)\n const strings = useMCPUIStrings()\n let dialogRef: HTMLDivElement | undefined\n let contentRef: HTMLDivElement | undefined\n let inlineSlotRef: HTMLDivElement | undefined\n let modalSlotRef: HTMLDivElement | undefined\n\n const handleOpen = () => setIsExpanded(true)\n const handleClose = () => setIsExpanded(false)\n\n // Report the state to the owner (see `onExpandedChange` docs).\n createEffect(() => {\n props.onExpandedChange?.(isExpanded())\n })\n\n // Reparent content DOM between inline and modal slots\n createEffect(() => {\n if (!contentRef) return\n\n if (isExpanded()) {\n // Move content into modal\n modalSlotRef?.appendChild(contentRef)\n } else {\n // Move content back to inline\n inlineSlotRef?.appendChild(contentRef)\n }\n })\n\n // Keyboard: Escape to close\n createEffect(() => {\n if (!isExpanded()) return\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n handleClose()\n }\n }\n\n document.addEventListener('keydown', onKeyDown)\n onCleanup(() => document.removeEventListener('keydown', onKeyDown))\n })\n\n // Prevent body scroll when expanded\n createEffect(() => {\n if (isExpanded()) {\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n // Focus the dialog\n setTimeout(() => dialogRef?.focus(), 10)\n onCleanup(() => {\n document.body.style.overflow = prev\n })\n }\n })\n\n /**\n * Did the gesture that produced the current click START on the backdrop?\n *\n * `null` means no pointer press was seen — a synthetic or programmatic\n * click, which stays allowed so keyboard and test-driven closes keep working.\n */\n let pressedOnBackdrop: boolean | null = null\n\n const handleBackdropPointerDown = (e: PointerEvent) => {\n pressedOnBackdrop = e.target === e.currentTarget\n }\n\n /**\n * Closing on a backdrop click is only safe when the gesture also BEGAN there.\n *\n * When a press and its release have different targets the browser dispatches\n * `click` on their nearest common ancestor — here the backdrop. So a drag\n * that starts on the content and releases over the 16px margin around the\n * panel (panning a zoomed chart, selecting text in a table) would otherwise\n * land on this handler with `e.target === e.currentTarget` and tear the modal\n * down mid-gesture.\n */\n const handleBackdropClick = (e: MouseEvent) => {\n const startedOnBackdrop = pressedOnBackdrop\n pressedOnBackdrop = null\n if (startedOnBackdrop === false) return\n if (e.target === e.currentTarget) handleClose()\n }\n\n const handleCopy = async () => {\n if (!props.copyData) return\n try {\n await navigator.clipboard.writeText(props.copyData)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error('Failed to copy:', err)\n }\n }\n\n return (\n <div class=\"relative group\">\n {/* Inline slot — content lives here when not expanded */}\n <div ref={inlineSlotRef}>\n <div ref={contentRef}>\n <ExpandedContext.Provider value={isExpanded}>\n {props.children}\n </ExpandedContext.Provider>\n </div>\n </div>\n\n {/* Expand button — visibility per `toolbarVariant` (default 'hover') */}\n <button\n type=\"button\"\n onClick={handleOpen}\n class={`absolute top-2 right-2 z-10 ${\n props.toolbarVariant === 'always-visible'\n ? 'opacity-60 hover:opacity-100'\n : 'opacity-0 group-hover:opacity-70 hover:!opacity-100'\n } p-1.5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm`}\n title={strings.expand}\n aria-label={strings.expand}\n data-mcp-ui-action=\"expand\"\n >\n <svg class=\"w-3.5 h-3.5 text-gray-500 dark:text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5\" />\n </svg>\n </button>\n\n {/* Fullscreen modal via Portal */}\n <Show when={isExpanded()}>\n <Portal>\n <div\n class=\"fixed inset-0 z-50 flex flex-col bg-black/50 backdrop-blur-sm\"\n style={{ animation: 'expandable-fade-in 0.15s ease-out' }}\n onClick={handleBackdropClick}\n onPointerDown={handleBackdropPointerDown}\n role=\"dialog\"\n data-mcp-ui-portal=\"dialog\"\n aria-modal=\"true\"\n aria-label={props.title || strings.expandedView}\n tabIndex={-1}\n ref={dialogRef}\n >\n {/* Modal panel */}\n <div\n class=\"relative flex flex-col m-4 flex-1 bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden\"\n style={{ animation: 'expandable-scale-in 0.15s ease-out' }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div class=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <h2 class=\"text-lg font-semibold text-gray-900 dark:text-white truncate\">\n {props.title || strings.expandedView}\n </h2>\n <div class=\"flex items-center gap-2\">\n {/* Copy button */}\n <Show when={props.copyData}>\n <button\n type=\"button\"\n onClick={handleCopy}\n class=\"p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\n title={props.copyLabel || strings.copyToClipboard}\n aria-label={props.copyLabel || strings.copyToClipboard}\n data-mcp-ui-action=\"copy\"\n >\n <Show\n when={!copied()}\n fallback={\n <svg class=\"w-5 h-5 text-green-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n }\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n </Show>\n </button>\n </Show>\n {/* Close button */}\n <button\n type=\"button\"\n onClick={handleClose}\n class=\"p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\n aria-label={strings.closeExpandedView}\n data-mcp-ui-action=\"close\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Modal slot — content is reparented here when expanded.\n v6.1.0 : `flex flex-col` lets aware children opt into\n `flex-1 min-h-0` to fill the modal vertically (chart,\n table, map, graph). Unaware children keep working\n thanks to `overflow-auto` (their natural height\n scrolls if it overflows the slot). */}\n <div class=\"flex-1 min-h-0 overflow-auto p-4 flex flex-col\" ref={modalSlotRef} />\n </div>\n </div>\n\n <style>{`\n @keyframes expandable-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes expandable-scale-in {\n from { opacity: 0; transform: scale(0.97); }\n to { opacity: 1; transform: scale(1); }\n }\n `}</style>\n </Portal>\n </Show>\n </div>\n )\n}\n"],"names":["ExpandedContext","createContext","useExpanded","useContext","ExpandableWrapper","props","isExpanded","setIsExpanded","createSignal","copied","setCopied","strings","useMCPUIStrings","dialogRef","contentRef","inlineSlotRef","modalSlotRef","handleOpen","handleClose","createEffect","onExpandedChange","appendChild","onKeyDown","e","key","preventDefault","document","addEventListener","onCleanup","removeEventListener","prev","body","style","overflow","setTimeout","focus","pressedOnBackdrop","handleBackdropPointerDown","target","currentTarget","handleBackdropClick","startedOnBackdrop","handleCopy","copyData","navigator","clipboard","writeText","err","console","error","_el$","_$getNextElement","_tmpl$5","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$15","_el$16","_co$2","_$getNextMarker","_ref$","_$use","_ref$2","_$insert","_$createComponent","Provider","value","children","$$click","Show","when","Portal","_el$5","_tmpl$3","_el$6","_el$7","_el$8","_el$9","_el$11","_el$12","_co$","_el$10","_el$13","_ref$3","$$pointerdown","stopPropagation","title","expandedView","_el$0","_tmpl$2","fallback","_tmpl$6","_tmpl$","_$effect","_p$","_v$","copyLabel","copyToClipboard","_v$2","_$setAttribute","t","undefined","_$runHydrationEvents","_ref$4","_v$3","_v$4","closeExpandedView","_tmpl$4","_v$5","toolbarVariant","_v$6","expand","_v$7","_$className","a","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ExpandableWrapper.cjs","sources":["../../src/components/ExpandableWrapper.tsx"],"sourcesContent":["/**\n * ExpandableWrapper - Generic expand/fullscreen wrapper for components\n * v2.2.0: Reusable wrapper that adds expand button + fullscreen modal\n *\n * Uses DOM reparenting to avoid rendering children twice — critical for\n * imperative components like ChartJS that bind instances to DOM nodes.\n */\n\nimport { Component, Show, createSignal, createEffect, onCleanup, JSX, createContext, useContext, Accessor } from 'solid-js'\nimport { Portal } from 'solid-js/web'\nimport { bindPortalTheme } from '../utils/theme'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\n/** Context for child components to know if they're in expanded/fullscreen view */\nconst ExpandedContext = createContext<Accessor<boolean>>(() => false)\n\n/** Hook for child components to read expanded state */\nexport const useExpanded = () => useContext(ExpandedContext)\n\nexport interface ExpandableWrapperProps {\n /** Content to render inline (and in expanded view) */\n children: JSX.Element\n /** Title shown in the expanded modal header */\n title?: string\n /** Data string for copy-to-clipboard in expanded view */\n copyData?: string\n /** Label for copy button tooltip */\n copyLabel?: string\n /**\n * Visibility behavior of the inline expand button (v6.3.0 — axe 4 deposium handoff).\n * - `'hover'` (default) : opacity 0, fades to 0.7 on parent group hover.\n * Backwards-compatible — pre-v6.3.0 behavior.\n * - `'always-visible'` : opacity 0.6 permanent, 1 on hover. Use this when\n * the inline button needs to be discoverable without hovering — esp.\n * on touch surfaces and consumer themes where the hover-only pattern\n * hides the affordance.\n */\n toolbarVariant?: 'hover' | 'always-visible'\n /**\n * Called with the expanded state on mount and whenever it changes (v6.19.0).\n * Needed by renderers that render their own `<ExpandableWrapper>`: their\n * `useExpanded()` call sits ABOVE the wrapper's context provider and would\n * only ever see an outer wrapper.\n */\n onExpandedChange?: (expanded: boolean) => void\n}\n\n/**\n * Wraps any component with an expand button (top-right corner).\n * Opens a fullscreen Portal modal. The children's DOM is physically\n * reparented into the modal (not duplicated), so imperative bindings\n * like Chart.js canvas refs stay intact.\n *\n * @example\n * <ExpandableWrapper title=\"Sales Data\" copyData={tsvData}>\n * <TableRenderer ... />\n * </ExpandableWrapper>\n */\nexport const ExpandableWrapper: Component<ExpandableWrapperProps> = (props) => {\n const [isExpanded, setIsExpanded] = createSignal(false)\n const [copied, setCopied] = createSignal(false)\n const strings = useMCPUIStrings()\n let dialogRef: HTMLDivElement | undefined\n let contentRef: HTMLDivElement | undefined\n let inlineSlotRef: HTMLDivElement | undefined\n let modalSlotRef: HTMLDivElement | undefined\n\n const handleOpen = () => setIsExpanded(true)\n const handleClose = () => setIsExpanded(false)\n\n // Report the state to the owner (see `onExpandedChange` docs).\n createEffect(() => {\n props.onExpandedChange?.(isExpanded())\n })\n\n // Reparent content DOM between inline and modal slots\n createEffect(() => {\n if (!contentRef) return\n\n if (isExpanded()) {\n // Move content into modal\n modalSlotRef?.appendChild(contentRef)\n } else {\n // Move content back to inline\n inlineSlotRef?.appendChild(contentRef)\n }\n })\n\n // Keyboard: Escape to close\n createEffect(() => {\n if (!isExpanded()) return\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n handleClose()\n }\n }\n\n document.addEventListener('keydown', onKeyDown)\n onCleanup(() => document.removeEventListener('keydown', onKeyDown))\n })\n\n // Prevent body scroll when expanded\n createEffect(() => {\n if (isExpanded()) {\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n // Focus the dialog\n setTimeout(() => dialogRef?.focus(), 10)\n onCleanup(() => {\n document.body.style.overflow = prev\n })\n }\n })\n\n /**\n * Did the gesture that produced the current click START on the backdrop?\n *\n * `null` means no pointer press was seen — a synthetic or programmatic\n * click, which stays allowed so keyboard and test-driven closes keep working.\n */\n let pressedOnBackdrop: boolean | null = null\n\n const handleBackdropPointerDown = (e: PointerEvent) => {\n pressedOnBackdrop = e.target === e.currentTarget\n }\n\n /**\n * Closing on a backdrop click is only safe when the gesture also BEGAN there.\n *\n * When a press and its release have different targets the browser dispatches\n * `click` on their nearest common ancestor — here the backdrop. So a drag\n * that starts on the content and releases over the 16px margin around the\n * panel (panning a zoomed chart, selecting text in a table) would otherwise\n * land on this handler with `e.target === e.currentTarget` and tear the modal\n * down mid-gesture.\n */\n const handleBackdropClick = (e: MouseEvent) => {\n const startedOnBackdrop = pressedOnBackdrop\n pressedOnBackdrop = null\n if (startedOnBackdrop === false) return\n if (e.target === e.currentTarget) handleClose()\n }\n\n const handleCopy = async () => {\n if (!props.copyData) return\n try {\n await navigator.clipboard.writeText(props.copyData)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error('Failed to copy:', err)\n }\n }\n\n return (\n <div class=\"mcp-ui-root relative group\">\n {/* Inline slot — content lives here when not expanded */}\n <div ref={inlineSlotRef}>\n <div ref={contentRef}>\n <ExpandedContext.Provider value={isExpanded}>\n {props.children}\n </ExpandedContext.Provider>\n </div>\n </div>\n\n {/* Expand button — visibility per `toolbarVariant` (default 'hover') */}\n <button\n type=\"button\"\n onClick={handleOpen}\n class={`absolute top-2 right-2 z-10 ${\n props.toolbarVariant === 'always-visible'\n ? 'opacity-60 hover:opacity-100'\n : 'opacity-0 group-hover:opacity-70 hover:!opacity-100'\n } p-1.5 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] rounded-full 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))] transition-all shadow-[var(--mcp-ui-shadow,var(--shadow-sm))]`}\n title={strings.expand}\n aria-label={strings.expand}\n data-mcp-ui-action=\"expand\"\n >\n <svg class=\"w-3.5 h-3.5 text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5\" />\n </svg>\n </button>\n\n {/* Fullscreen modal via Portal */}\n <Show when={isExpanded()}>\n <Portal>\n <div\n class=\"fixed inset-0 z-50 flex flex-col bg-[color:var(--mcp-ui-overlay,color-mix(in_oklab,var(--color-black,#000)_50%,transparent))] backdrop-blur-sm\"\n style={{ animation: 'expandable-fade-in 0.15s ease-out' }}\n onClick={handleBackdropClick}\n onPointerDown={handleBackdropPointerDown}\n role=\"dialog\"\n data-mcp-ui-portal=\"dialog\"\n aria-modal=\"true\"\n aria-label={props.title || strings.expandedView}\n tabIndex={-1}\n ref={(element) => {\n dialogRef = element\n bindPortalTheme(element, () => inlineSlotRef)\n }}\n >\n {/* Modal panel */}\n <div\n class=\"relative flex flex-col m-4 flex-1 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] rounded-lg shadow-[var(--mcp-ui-shadow,var(--shadow-xl))] overflow-hidden\"\n style={{ animation: 'expandable-scale-in 0.15s ease-out' }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div class=\"flex items-center justify-between px-4 py-3 border-b border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))] flex-shrink-0\">\n <h2 class=\"text-lg font-semibold text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] truncate\">\n {props.title || strings.expandedView}\n </h2>\n <div class=\"flex items-center gap-2\">\n {/* Copy button */}\n <Show when={props.copyData}>\n <button\n type=\"button\"\n onClick={handleCopy}\n class=\"p-1.5 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] hover:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:hover:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-full 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))] transition-colors\"\n title={props.copyLabel || strings.copyToClipboard}\n aria-label={props.copyLabel || strings.copyToClipboard}\n data-mcp-ui-action=\"copy\"\n >\n <Show\n when={!copied()}\n fallback={\n <svg class=\"w-5 h-5 text-[color:var(--mcp-ui-success,var(--color-green-500))]\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n }\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n </Show>\n </button>\n </Show>\n {/* Close button */}\n <button\n type=\"button\"\n onClick={handleClose}\n class=\"p-1.5 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] hover:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:hover:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-full 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))] transition-colors\"\n aria-label={strings.closeExpandedView}\n data-mcp-ui-action=\"close\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Modal slot — content is reparented here when expanded.\n v6.1.0 : `flex flex-col` lets aware children opt into\n `flex-1 min-h-0` to fill the modal vertically (chart,\n table, map, graph). Unaware children keep working\n thanks to `overflow-auto` (their natural height\n scrolls if it overflows the slot). */}\n <div class=\"flex-1 min-h-0 overflow-auto p-4 flex flex-col\" ref={modalSlotRef} />\n </div>\n </div>\n\n <style>{`\n @keyframes expandable-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes expandable-scale-in {\n from { opacity: 0; transform: scale(0.97); }\n to { opacity: 1; transform: scale(1); }\n }\n `}</style>\n </Portal>\n </Show>\n </div>\n )\n}\n"],"names":["ExpandedContext","createContext","useExpanded","useContext","ExpandableWrapper","props","isExpanded","setIsExpanded","createSignal","copied","setCopied","strings","useMCPUIStrings","dialogRef","contentRef","inlineSlotRef","modalSlotRef","handleOpen","handleClose","createEffect","onExpandedChange","appendChild","onKeyDown","e","key","preventDefault","document","addEventListener","onCleanup","removeEventListener","prev","body","style","overflow","setTimeout","focus","pressedOnBackdrop","handleBackdropPointerDown","target","currentTarget","handleBackdropClick","startedOnBackdrop","handleCopy","copyData","navigator","clipboard","writeText","err","console","error","_el$","_$getNextElement","_tmpl$5","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$15","_el$16","_co$2","_$getNextMarker","_ref$","_$use","_ref$2","_$insert","_$createComponent","Provider","value","children","$$click","Show","when","Portal","_el$5","_tmpl$3","_el$6","_el$7","_el$8","_el$9","_el$11","_el$12","_co$","_el$10","_el$13","element","bindPortalTheme","$$pointerdown","stopPropagation","title","expandedView","_el$0","_tmpl$2","fallback","_tmpl$6","_tmpl$","_$effect","_p$","_v$","copyLabel","copyToClipboard","_v$2","_$setAttribute","t","undefined","_$runHydrationEvents","_ref$3","_v$3","_v$4","closeExpandedView","_tmpl$4","_v$5","toolbarVariant","_v$6","expand","_v$7","_$className","a","_$delegateEvents"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpandableWrapper.d.ts","sourceRoot":"","sources":["../../src/components/ExpandableWrapper.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAA+C,GAAG,EAA6B,QAAQ,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"ExpandableWrapper.d.ts","sourceRoot":"","sources":["../../src/components/ExpandableWrapper.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAA+C,GAAG,EAA6B,QAAQ,EAAE,MAAM,UAAU,CAAA;AAQ3H,uDAAuD;AACvD,eAAO,MAAM,WAAW,yBAAoC,CAAA;AAE5D,MAAM,WAAW,sBAAsB;IACrC,sDAAsD;IACtD,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;IACrB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAA;IAC3C;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;CAC/C;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,sBAAsB,CA4N/D,CAAA"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getNextElement, getNextMarker, insert, createComponent, Portal, use, effect, setAttribute, runHydrationEvents, className, template, delegateEvents } from "solid-js/web";
|
|
2
2
|
import { createSignal, createEffect, onCleanup, Show, useContext, createContext } from "solid-js";
|
|
3
|
+
import { bindPortalTheme } from "../utils/theme.js";
|
|
3
4
|
import { useMCPUIStrings } from "../context/MCPUIStringsContext.js";
|
|
4
|
-
var _tmpl$ = /* @__PURE__ */ template(`<svg class="w-5 h-5"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">`), _tmpl$2 = /* @__PURE__ */ template(`<button type=button class="p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"data-mcp-ui-action=copy>`), _tmpl$3 = /* @__PURE__ */ template(`<div class="fixed inset-0 z-50 flex flex-col bg-black
|
|
5
|
+
var _tmpl$ = /* @__PURE__ */ template(`<svg class="w-5 h-5"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">`), _tmpl$2 = /* @__PURE__ */ template(`<button type=button class="p-1.5 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] hover:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:hover:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-full 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))] transition-colors"data-mcp-ui-action=copy>`), _tmpl$3 = /* @__PURE__ */ template(`<div class="fixed inset-0 z-50 flex flex-col bg-[color:var(--mcp-ui-overlay,color-mix(in_oklab,var(--color-black,#000)_50%,transparent))] backdrop-blur-sm"role=dialog data-mcp-ui-portal=dialog aria-modal=true tabindex=-1 style="animation:expandable-fade-in 0.15s ease-out"><div class="relative flex flex-col m-4 flex-1 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] rounded-lg shadow-[var(--mcp-ui-shadow,var(--shadow-xl))] overflow-hidden"style="animation:expandable-scale-in 0.15s ease-out"><div class="flex items-center justify-between px-4 py-3 border-b border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))] flex-shrink-0"><h2 class="text-lg font-semibold text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] truncate"></h2><div class="flex items-center gap-2"><!$><!/><button type=button class="p-1.5 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] hover:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:hover:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-full 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))] transition-colors"data-mcp-ui-action=close><svg class="w-5 h-5"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M6 18L18 6M6 6l12 12"></path></svg></button></div></div><div class="flex-1 min-h-0 overflow-auto p-4 flex flex-col">`), _tmpl$4 = /* @__PURE__ */ template(`<style>
|
|
5
6
|
@keyframes expandable-fade-in {
|
|
6
7
|
from { opacity: 0; }
|
|
7
8
|
to { opacity: 1; }
|
|
@@ -10,7 +11,7 @@ var _tmpl$ = /* @__PURE__ */ template(`<svg class="w-5 h-5"fill=none viewBox="0
|
|
|
10
11
|
from { opacity: 0; transform: scale(0.97); }
|
|
11
12
|
to { opacity: 1; transform: scale(1); }
|
|
12
13
|
}
|
|
13
|
-
`), _tmpl$5 = /* @__PURE__ */ template(`<div class="relative group"><div><div></div></div><button type=button data-mcp-ui-action=expand><svg class="w-3.5 h-3.5 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5"></path></svg></button><!$><!/>`), _tmpl$6 = /* @__PURE__ */ template(`<svg class="w-5 h-5 text-green-500"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M5 13l4 4L19 7">`);
|
|
14
|
+
`), _tmpl$5 = /* @__PURE__ */ template(`<div class="mcp-ui-root relative group"><div><div></div></div><button type=button data-mcp-ui-action=expand><svg class="w-3.5 h-3.5 text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5"></path></svg></button><!$><!/>`), _tmpl$6 = /* @__PURE__ */ template(`<svg class="w-5 h-5 text-[color:var(--mcp-ui-success,var(--color-green-500))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M5 13l4 4L19 7">`);
|
|
14
15
|
const ExpandedContext = createContext(() => false);
|
|
15
16
|
const useExpanded = () => useContext(ExpandedContext);
|
|
16
17
|
const ExpandableWrapper = (props) => {
|
|
@@ -98,8 +99,10 @@ const ExpandableWrapper = (props) => {
|
|
|
98
99
|
get children() {
|
|
99
100
|
return [(() => {
|
|
100
101
|
var _el$5 = getNextElement(_tmpl$3), _el$6 = _el$5.firstChild, _el$7 = _el$6.firstChild, _el$8 = _el$7.firstChild, _el$9 = _el$8.nextSibling, _el$11 = _el$9.firstChild, [_el$12, _co$] = getNextMarker(_el$11.nextSibling), _el$10 = _el$12.nextSibling, _el$13 = _el$7.nextSibling;
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
use((element) => {
|
|
103
|
+
dialogRef = element;
|
|
104
|
+
bindPortalTheme(element, () => inlineSlotRef);
|
|
105
|
+
}, _el$5);
|
|
103
106
|
_el$5.$$pointerdown = handleBackdropPointerDown;
|
|
104
107
|
_el$5.$$click = handleBackdropClick;
|
|
105
108
|
_el$6.$$click = (e) => e.stopPropagation();
|
|
@@ -136,8 +139,8 @@ const ExpandableWrapper = (props) => {
|
|
|
136
139
|
}
|
|
137
140
|
}), _el$12, _co$);
|
|
138
141
|
_el$10.$$click = handleClose;
|
|
139
|
-
var _ref$
|
|
140
|
-
typeof _ref$
|
|
142
|
+
var _ref$3 = modalSlotRef;
|
|
143
|
+
typeof _ref$3 === "function" ? use(_ref$3, _el$13) : modalSlotRef = _el$13;
|
|
141
144
|
effect((_p$) => {
|
|
142
145
|
var _v$3 = props.title || strings.expandedView, _v$4 = strings.closeExpandedView;
|
|
143
146
|
_v$3 !== _p$.e && setAttribute(_el$5, "aria-label", _p$.e = _v$3);
|
|
@@ -155,7 +158,7 @@ const ExpandableWrapper = (props) => {
|
|
|
155
158
|
}
|
|
156
159
|
}), _el$16, _co$2);
|
|
157
160
|
effect((_p$) => {
|
|
158
|
-
var _v$5 = `absolute top-2 right-2 z-10 ${props.toolbarVariant === "always-visible" ? "opacity-60 hover:opacity-100" : "opacity-0 group-hover:opacity-70 hover:!opacity-100"} p-1.5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm`, _v$6 = strings.expand, _v$7 = strings.expand;
|
|
161
|
+
var _v$5 = `absolute top-2 right-2 z-10 ${props.toolbarVariant === "always-visible" ? "opacity-60 hover:opacity-100" : "opacity-0 group-hover:opacity-70 hover:!opacity-100"} p-1.5 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] rounded-full 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))] transition-all shadow-[var(--mcp-ui-shadow,var(--shadow-sm))]`, _v$6 = strings.expand, _v$7 = strings.expand;
|
|
159
162
|
_v$5 !== _p$.e && className(_el$4, _p$.e = _v$5);
|
|
160
163
|
_v$6 !== _p$.t && setAttribute(_el$4, "title", _p$.t = _v$6);
|
|
161
164
|
_v$7 !== _p$.a && setAttribute(_el$4, "aria-label", _p$.a = _v$7);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpandableWrapper.js","sources":["../../src/components/ExpandableWrapper.tsx"],"sourcesContent":["/**\n * ExpandableWrapper - Generic expand/fullscreen wrapper for components\n * v2.2.0: Reusable wrapper that adds expand button + fullscreen modal\n *\n * Uses DOM reparenting to avoid rendering children twice — critical for\n * imperative components like ChartJS that bind instances to DOM nodes.\n */\n\nimport { Component, Show, createSignal, createEffect, onCleanup, JSX, createContext, useContext, Accessor } from 'solid-js'\nimport { Portal } from 'solid-js/web'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\n/** Context for child components to know if they're in expanded/fullscreen view */\nconst ExpandedContext = createContext<Accessor<boolean>>(() => false)\n\n/** Hook for child components to read expanded state */\nexport const useExpanded = () => useContext(ExpandedContext)\n\nexport interface ExpandableWrapperProps {\n /** Content to render inline (and in expanded view) */\n children: JSX.Element\n /** Title shown in the expanded modal header */\n title?: string\n /** Data string for copy-to-clipboard in expanded view */\n copyData?: string\n /** Label for copy button tooltip */\n copyLabel?: string\n /**\n * Visibility behavior of the inline expand button (v6.3.0 — axe 4 deposium handoff).\n * - `'hover'` (default) : opacity 0, fades to 0.7 on parent group hover.\n * Backwards-compatible — pre-v6.3.0 behavior.\n * - `'always-visible'` : opacity 0.6 permanent, 1 on hover. Use this when\n * the inline button needs to be discoverable without hovering — esp.\n * on touch surfaces and consumer themes where the hover-only pattern\n * hides the affordance.\n */\n toolbarVariant?: 'hover' | 'always-visible'\n /**\n * Called with the expanded state on mount and whenever it changes (v6.19.0).\n * Needed by renderers that render their own `<ExpandableWrapper>`: their\n * `useExpanded()` call sits ABOVE the wrapper's context provider and would\n * only ever see an outer wrapper.\n */\n onExpandedChange?: (expanded: boolean) => void\n}\n\n/**\n * Wraps any component with an expand button (top-right corner).\n * Opens a fullscreen Portal modal. The children's DOM is physically\n * reparented into the modal (not duplicated), so imperative bindings\n * like Chart.js canvas refs stay intact.\n *\n * @example\n * <ExpandableWrapper title=\"Sales Data\" copyData={tsvData}>\n * <TableRenderer ... />\n * </ExpandableWrapper>\n */\nexport const ExpandableWrapper: Component<ExpandableWrapperProps> = (props) => {\n const [isExpanded, setIsExpanded] = createSignal(false)\n const [copied, setCopied] = createSignal(false)\n const strings = useMCPUIStrings()\n let dialogRef: HTMLDivElement | undefined\n let contentRef: HTMLDivElement | undefined\n let inlineSlotRef: HTMLDivElement | undefined\n let modalSlotRef: HTMLDivElement | undefined\n\n const handleOpen = () => setIsExpanded(true)\n const handleClose = () => setIsExpanded(false)\n\n // Report the state to the owner (see `onExpandedChange` docs).\n createEffect(() => {\n props.onExpandedChange?.(isExpanded())\n })\n\n // Reparent content DOM between inline and modal slots\n createEffect(() => {\n if (!contentRef) return\n\n if (isExpanded()) {\n // Move content into modal\n modalSlotRef?.appendChild(contentRef)\n } else {\n // Move content back to inline\n inlineSlotRef?.appendChild(contentRef)\n }\n })\n\n // Keyboard: Escape to close\n createEffect(() => {\n if (!isExpanded()) return\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n handleClose()\n }\n }\n\n document.addEventListener('keydown', onKeyDown)\n onCleanup(() => document.removeEventListener('keydown', onKeyDown))\n })\n\n // Prevent body scroll when expanded\n createEffect(() => {\n if (isExpanded()) {\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n // Focus the dialog\n setTimeout(() => dialogRef?.focus(), 10)\n onCleanup(() => {\n document.body.style.overflow = prev\n })\n }\n })\n\n /**\n * Did the gesture that produced the current click START on the backdrop?\n *\n * `null` means no pointer press was seen — a synthetic or programmatic\n * click, which stays allowed so keyboard and test-driven closes keep working.\n */\n let pressedOnBackdrop: boolean | null = null\n\n const handleBackdropPointerDown = (e: PointerEvent) => {\n pressedOnBackdrop = e.target === e.currentTarget\n }\n\n /**\n * Closing on a backdrop click is only safe when the gesture also BEGAN there.\n *\n * When a press and its release have different targets the browser dispatches\n * `click` on their nearest common ancestor — here the backdrop. So a drag\n * that starts on the content and releases over the 16px margin around the\n * panel (panning a zoomed chart, selecting text in a table) would otherwise\n * land on this handler with `e.target === e.currentTarget` and tear the modal\n * down mid-gesture.\n */\n const handleBackdropClick = (e: MouseEvent) => {\n const startedOnBackdrop = pressedOnBackdrop\n pressedOnBackdrop = null\n if (startedOnBackdrop === false) return\n if (e.target === e.currentTarget) handleClose()\n }\n\n const handleCopy = async () => {\n if (!props.copyData) return\n try {\n await navigator.clipboard.writeText(props.copyData)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error('Failed to copy:', err)\n }\n }\n\n return (\n <div class=\"relative group\">\n {/* Inline slot — content lives here when not expanded */}\n <div ref={inlineSlotRef}>\n <div ref={contentRef}>\n <ExpandedContext.Provider value={isExpanded}>\n {props.children}\n </ExpandedContext.Provider>\n </div>\n </div>\n\n {/* Expand button — visibility per `toolbarVariant` (default 'hover') */}\n <button\n type=\"button\"\n onClick={handleOpen}\n class={`absolute top-2 right-2 z-10 ${\n props.toolbarVariant === 'always-visible'\n ? 'opacity-60 hover:opacity-100'\n : 'opacity-0 group-hover:opacity-70 hover:!opacity-100'\n } p-1.5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm`}\n title={strings.expand}\n aria-label={strings.expand}\n data-mcp-ui-action=\"expand\"\n >\n <svg class=\"w-3.5 h-3.5 text-gray-500 dark:text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5\" />\n </svg>\n </button>\n\n {/* Fullscreen modal via Portal */}\n <Show when={isExpanded()}>\n <Portal>\n <div\n class=\"fixed inset-0 z-50 flex flex-col bg-black/50 backdrop-blur-sm\"\n style={{ animation: 'expandable-fade-in 0.15s ease-out' }}\n onClick={handleBackdropClick}\n onPointerDown={handleBackdropPointerDown}\n role=\"dialog\"\n data-mcp-ui-portal=\"dialog\"\n aria-modal=\"true\"\n aria-label={props.title || strings.expandedView}\n tabIndex={-1}\n ref={dialogRef}\n >\n {/* Modal panel */}\n <div\n class=\"relative flex flex-col m-4 flex-1 bg-white dark:bg-gray-800 rounded-lg shadow-xl overflow-hidden\"\n style={{ animation: 'expandable-scale-in 0.15s ease-out' }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div class=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <h2 class=\"text-lg font-semibold text-gray-900 dark:text-white truncate\">\n {props.title || strings.expandedView}\n </h2>\n <div class=\"flex items-center gap-2\">\n {/* Copy button */}\n <Show when={props.copyData}>\n <button\n type=\"button\"\n onClick={handleCopy}\n class=\"p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\n title={props.copyLabel || strings.copyToClipboard}\n aria-label={props.copyLabel || strings.copyToClipboard}\n data-mcp-ui-action=\"copy\"\n >\n <Show\n when={!copied()}\n fallback={\n <svg class=\"w-5 h-5 text-green-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n }\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n </Show>\n </button>\n </Show>\n {/* Close button */}\n <button\n type=\"button\"\n onClick={handleClose}\n class=\"p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\n aria-label={strings.closeExpandedView}\n data-mcp-ui-action=\"close\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Modal slot — content is reparented here when expanded.\n v6.1.0 : `flex flex-col` lets aware children opt into\n `flex-1 min-h-0` to fill the modal vertically (chart,\n table, map, graph). Unaware children keep working\n thanks to `overflow-auto` (their natural height\n scrolls if it overflows the slot). */}\n <div class=\"flex-1 min-h-0 overflow-auto p-4 flex flex-col\" ref={modalSlotRef} />\n </div>\n </div>\n\n <style>{`\n @keyframes expandable-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes expandable-scale-in {\n from { opacity: 0; transform: scale(0.97); }\n to { opacity: 1; transform: scale(1); }\n }\n `}</style>\n </Portal>\n </Show>\n </div>\n )\n}\n"],"names":["ExpandedContext","createContext","useExpanded","useContext","ExpandableWrapper","props","isExpanded","setIsExpanded","createSignal","copied","setCopied","strings","useMCPUIStrings","dialogRef","contentRef","inlineSlotRef","modalSlotRef","handleOpen","handleClose","createEffect","onExpandedChange","appendChild","onKeyDown","e","key","preventDefault","document","addEventListener","onCleanup","removeEventListener","prev","body","style","overflow","setTimeout","focus","pressedOnBackdrop","handleBackdropPointerDown","target","currentTarget","handleBackdropClick","startedOnBackdrop","handleCopy","copyData","navigator","clipboard","writeText","err","console","error","_el$","_$getNextElement","_tmpl$5","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$15","_el$16","_co$2","_$getNextMarker","_ref$","_$use","_ref$2","_$insert","_$createComponent","Provider","value","children","$$click","Show","when","Portal","_el$5","_tmpl$3","_el$6","_el$7","_el$8","_el$9","_el$11","_el$12","_co$","_el$10","_el$13","_ref$3","$$pointerdown","stopPropagation","title","expandedView","_el$0","_tmpl$2","fallback","_tmpl$6","_tmpl$","_$effect","_p$","_v$","copyLabel","copyToClipboard","_v$2","_$setAttribute","t","undefined","_$runHydrationEvents","_ref$4","_v$3","_v$4","closeExpandedView","_tmpl$4","_v$5","toolbarVariant","_v$6","expand","_v$7","_$className","a","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ExpandableWrapper.js","sources":["../../src/components/ExpandableWrapper.tsx"],"sourcesContent":["/**\n * ExpandableWrapper - Generic expand/fullscreen wrapper for components\n * v2.2.0: Reusable wrapper that adds expand button + fullscreen modal\n *\n * Uses DOM reparenting to avoid rendering children twice — critical for\n * imperative components like ChartJS that bind instances to DOM nodes.\n */\n\nimport { Component, Show, createSignal, createEffect, onCleanup, JSX, createContext, useContext, Accessor } from 'solid-js'\nimport { Portal } from 'solid-js/web'\nimport { bindPortalTheme } from '../utils/theme'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\n/** Context for child components to know if they're in expanded/fullscreen view */\nconst ExpandedContext = createContext<Accessor<boolean>>(() => false)\n\n/** Hook for child components to read expanded state */\nexport const useExpanded = () => useContext(ExpandedContext)\n\nexport interface ExpandableWrapperProps {\n /** Content to render inline (and in expanded view) */\n children: JSX.Element\n /** Title shown in the expanded modal header */\n title?: string\n /** Data string for copy-to-clipboard in expanded view */\n copyData?: string\n /** Label for copy button tooltip */\n copyLabel?: string\n /**\n * Visibility behavior of the inline expand button (v6.3.0 — axe 4 deposium handoff).\n * - `'hover'` (default) : opacity 0, fades to 0.7 on parent group hover.\n * Backwards-compatible — pre-v6.3.0 behavior.\n * - `'always-visible'` : opacity 0.6 permanent, 1 on hover. Use this when\n * the inline button needs to be discoverable without hovering — esp.\n * on touch surfaces and consumer themes where the hover-only pattern\n * hides the affordance.\n */\n toolbarVariant?: 'hover' | 'always-visible'\n /**\n * Called with the expanded state on mount and whenever it changes (v6.19.0).\n * Needed by renderers that render their own `<ExpandableWrapper>`: their\n * `useExpanded()` call sits ABOVE the wrapper's context provider and would\n * only ever see an outer wrapper.\n */\n onExpandedChange?: (expanded: boolean) => void\n}\n\n/**\n * Wraps any component with an expand button (top-right corner).\n * Opens a fullscreen Portal modal. The children's DOM is physically\n * reparented into the modal (not duplicated), so imperative bindings\n * like Chart.js canvas refs stay intact.\n *\n * @example\n * <ExpandableWrapper title=\"Sales Data\" copyData={tsvData}>\n * <TableRenderer ... />\n * </ExpandableWrapper>\n */\nexport const ExpandableWrapper: Component<ExpandableWrapperProps> = (props) => {\n const [isExpanded, setIsExpanded] = createSignal(false)\n const [copied, setCopied] = createSignal(false)\n const strings = useMCPUIStrings()\n let dialogRef: HTMLDivElement | undefined\n let contentRef: HTMLDivElement | undefined\n let inlineSlotRef: HTMLDivElement | undefined\n let modalSlotRef: HTMLDivElement | undefined\n\n const handleOpen = () => setIsExpanded(true)\n const handleClose = () => setIsExpanded(false)\n\n // Report the state to the owner (see `onExpandedChange` docs).\n createEffect(() => {\n props.onExpandedChange?.(isExpanded())\n })\n\n // Reparent content DOM between inline and modal slots\n createEffect(() => {\n if (!contentRef) return\n\n if (isExpanded()) {\n // Move content into modal\n modalSlotRef?.appendChild(contentRef)\n } else {\n // Move content back to inline\n inlineSlotRef?.appendChild(contentRef)\n }\n })\n\n // Keyboard: Escape to close\n createEffect(() => {\n if (!isExpanded()) return\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n handleClose()\n }\n }\n\n document.addEventListener('keydown', onKeyDown)\n onCleanup(() => document.removeEventListener('keydown', onKeyDown))\n })\n\n // Prevent body scroll when expanded\n createEffect(() => {\n if (isExpanded()) {\n const prev = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n // Focus the dialog\n setTimeout(() => dialogRef?.focus(), 10)\n onCleanup(() => {\n document.body.style.overflow = prev\n })\n }\n })\n\n /**\n * Did the gesture that produced the current click START on the backdrop?\n *\n * `null` means no pointer press was seen — a synthetic or programmatic\n * click, which stays allowed so keyboard and test-driven closes keep working.\n */\n let pressedOnBackdrop: boolean | null = null\n\n const handleBackdropPointerDown = (e: PointerEvent) => {\n pressedOnBackdrop = e.target === e.currentTarget\n }\n\n /**\n * Closing on a backdrop click is only safe when the gesture also BEGAN there.\n *\n * When a press and its release have different targets the browser dispatches\n * `click` on their nearest common ancestor — here the backdrop. So a drag\n * that starts on the content and releases over the 16px margin around the\n * panel (panning a zoomed chart, selecting text in a table) would otherwise\n * land on this handler with `e.target === e.currentTarget` and tear the modal\n * down mid-gesture.\n */\n const handleBackdropClick = (e: MouseEvent) => {\n const startedOnBackdrop = pressedOnBackdrop\n pressedOnBackdrop = null\n if (startedOnBackdrop === false) return\n if (e.target === e.currentTarget) handleClose()\n }\n\n const handleCopy = async () => {\n if (!props.copyData) return\n try {\n await navigator.clipboard.writeText(props.copyData)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error('Failed to copy:', err)\n }\n }\n\n return (\n <div class=\"mcp-ui-root relative group\">\n {/* Inline slot — content lives here when not expanded */}\n <div ref={inlineSlotRef}>\n <div ref={contentRef}>\n <ExpandedContext.Provider value={isExpanded}>\n {props.children}\n </ExpandedContext.Provider>\n </div>\n </div>\n\n {/* Expand button — visibility per `toolbarVariant` (default 'hover') */}\n <button\n type=\"button\"\n onClick={handleOpen}\n class={`absolute top-2 right-2 z-10 ${\n props.toolbarVariant === 'always-visible'\n ? 'opacity-60 hover:opacity-100'\n : 'opacity-0 group-hover:opacity-70 hover:!opacity-100'\n } p-1.5 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] rounded-full 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))] transition-all shadow-[var(--mcp-ui-shadow,var(--shadow-sm))]`}\n title={strings.expand}\n aria-label={strings.expand}\n data-mcp-ui-action=\"expand\"\n >\n <svg class=\"w-3.5 h-3.5 text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5\" />\n </svg>\n </button>\n\n {/* Fullscreen modal via Portal */}\n <Show when={isExpanded()}>\n <Portal>\n <div\n class=\"fixed inset-0 z-50 flex flex-col bg-[color:var(--mcp-ui-overlay,color-mix(in_oklab,var(--color-black,#000)_50%,transparent))] backdrop-blur-sm\"\n style={{ animation: 'expandable-fade-in 0.15s ease-out' }}\n onClick={handleBackdropClick}\n onPointerDown={handleBackdropPointerDown}\n role=\"dialog\"\n data-mcp-ui-portal=\"dialog\"\n aria-modal=\"true\"\n aria-label={props.title || strings.expandedView}\n tabIndex={-1}\n ref={(element) => {\n dialogRef = element\n bindPortalTheme(element, () => inlineSlotRef)\n }}\n >\n {/* Modal panel */}\n <div\n class=\"relative flex flex-col m-4 flex-1 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] rounded-lg shadow-[var(--mcp-ui-shadow,var(--shadow-xl))] overflow-hidden\"\n style={{ animation: 'expandable-scale-in 0.15s ease-out' }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div class=\"flex items-center justify-between px-4 py-3 border-b border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))] flex-shrink-0\">\n <h2 class=\"text-lg font-semibold text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] truncate\">\n {props.title || strings.expandedView}\n </h2>\n <div class=\"flex items-center gap-2\">\n {/* Copy button */}\n <Show when={props.copyData}>\n <button\n type=\"button\"\n onClick={handleCopy}\n class=\"p-1.5 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] hover:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:hover:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-full 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))] transition-colors\"\n title={props.copyLabel || strings.copyToClipboard}\n aria-label={props.copyLabel || strings.copyToClipboard}\n data-mcp-ui-action=\"copy\"\n >\n <Show\n when={!copied()}\n fallback={\n <svg class=\"w-5 h-5 text-[color:var(--mcp-ui-success,var(--color-green-500))]\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n }\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n </Show>\n </button>\n </Show>\n {/* Close button */}\n <button\n type=\"button\"\n onClick={handleClose}\n class=\"p-1.5 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] hover:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:hover:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-full 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))] transition-colors\"\n aria-label={strings.closeExpandedView}\n data-mcp-ui-action=\"close\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Modal slot — content is reparented here when expanded.\n v6.1.0 : `flex flex-col` lets aware children opt into\n `flex-1 min-h-0` to fill the modal vertically (chart,\n table, map, graph). Unaware children keep working\n thanks to `overflow-auto` (their natural height\n scrolls if it overflows the slot). */}\n <div class=\"flex-1 min-h-0 overflow-auto p-4 flex flex-col\" ref={modalSlotRef} />\n </div>\n </div>\n\n <style>{`\n @keyframes expandable-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes expandable-scale-in {\n from { opacity: 0; transform: scale(0.97); }\n to { opacity: 1; transform: scale(1); }\n }\n `}</style>\n </Portal>\n </Show>\n </div>\n )\n}\n"],"names":["ExpandedContext","createContext","useExpanded","useContext","ExpandableWrapper","props","isExpanded","setIsExpanded","createSignal","copied","setCopied","strings","useMCPUIStrings","dialogRef","contentRef","inlineSlotRef","modalSlotRef","handleOpen","handleClose","createEffect","onExpandedChange","appendChild","onKeyDown","e","key","preventDefault","document","addEventListener","onCleanup","removeEventListener","prev","body","style","overflow","setTimeout","focus","pressedOnBackdrop","handleBackdropPointerDown","target","currentTarget","handleBackdropClick","startedOnBackdrop","handleCopy","copyData","navigator","clipboard","writeText","err","console","error","_el$","_$getNextElement","_tmpl$5","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$15","_el$16","_co$2","_$getNextMarker","_ref$","_$use","_ref$2","_$insert","_$createComponent","Provider","value","children","$$click","Show","when","Portal","_el$5","_tmpl$3","_el$6","_el$7","_el$8","_el$9","_el$11","_el$12","_co$","_el$10","_el$13","element","bindPortalTheme","$$pointerdown","stopPropagation","title","expandedView","_el$0","_tmpl$2","fallback","_tmpl$6","_tmpl$","_$effect","_p$","_v$","copyLabel","copyToClipboard","_v$2","_$setAttribute","t","undefined","_$runHydrationEvents","_ref$3","_v$3","_v$4","closeExpandedView","_tmpl$4","_v$5","toolbarVariant","_v$6","expand","_v$7","_$className","a","_$delegateEvents"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ const solidJs = require("solid-js");
|
|
|
5
5
|
const useConditionalField = require("../hooks/useConditionalField.cjs");
|
|
6
6
|
const MCPUIStringsContext = require("../context/MCPUIStringsContext.cjs");
|
|
7
7
|
const formatString = require("../utils/format-string.cjs");
|
|
8
|
-
var _tmpl$ = /* @__PURE__ */ web.template(`<span class=mr-1>`), _tmpl$2 = /* @__PURE__ */ web.template(`<span class="text-red-500 ml-1"aria-hidden=true>*`), _tmpl$3 = /* @__PURE__ */ web.template(`<span class="ml-2 text-[10px] font-medium bg-orange-100 dark:bg-orange-900
|
|
8
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<span class=mr-1>`), _tmpl$2 = /* @__PURE__ */ web.template(`<span class="text-[color:var(--mcp-ui-danger,var(--color-red-500))] ml-1"aria-hidden=true>*`), _tmpl$3 = /* @__PURE__ */ web.template(`<span class="ml-2 text-[10px] font-medium bg-[color:var(--mcp-ui-warning-soft,var(--color-orange-100))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-orange-900)_30%,transparent))] text-[color:var(--mcp-ui-warning,var(--color-orange-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-orange-400))] px-1.5 py-0.5 rounded">`), _tmpl$4 = /* @__PURE__ */ web.template(`<span class="ml-2 text-[10px] font-medium bg-[color:var(--mcp-ui-warning-soft,var(--color-yellow-100))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-yellow-900)_30%,transparent))] text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))] px-1.5 py-0.5 rounded">?`), _tmpl$5 = /* @__PURE__ */ web.template(`<label><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$6 = /* @__PURE__ */ web.template(`<input>`), _tmpl$7 = /* @__PURE__ */ web.template(`<input type=number>`), _tmpl$8 = /* @__PURE__ */ web.template(`<input type=date>`), _tmpl$9 = /* @__PURE__ */ web.template(`<textarea>`), _tmpl$0 = /* @__PURE__ */ web.template(`<option value disabled>`), _tmpl$1 = /* @__PURE__ */ web.template(`<select><!$><!/><!$><!/>`), _tmpl$10 = /* @__PURE__ */ web.template(`<label class="flex items-center gap-2 cursor-pointer"><input type=checkbox class="w-4 h-4 rounded border-[color:var(--mcp-ui-border-control,var(--color-gray-300,#d1d5db))] text-[color:var(--mcp-ui-accent,var(--color-blue-600))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))] dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-700,#374151))]"><span class="text-sm text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))]"><!$><!/><!$><!/>`), _tmpl$11 = /* @__PURE__ */ web.template(`<div class=space-y-2 role=radiogroup>`), _tmpl$12 = /* @__PURE__ */ web.template(`<div class="flex items-center gap-3"><input type=range class="flex-1 h-2 bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-200,#e5e7eb))] dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-600,#4b5563))] rounded-lg appearance-none cursor-pointer accent-[color:var(--mcp-ui-accent,var(--color-blue-600))]"><span class="text-sm font-mono text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] min-w-[3rem] text-right">`), _tmpl$13 = /* @__PURE__ */ web.template(`<label class="flex items-center gap-2 cursor-pointer"><button type=button role=switch><span></span></button><span class="text-sm text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))]">`), _tmpl$14 = /* @__PURE__ */ web.template(`<fieldset class="border border-[color:var(--mcp-ui-border-control,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))] rounded-lg p-3"><legend class="text-xs font-medium text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] px-1"></legend><p class="text-xs text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]">`), _tmpl$15 = /* @__PURE__ */ web.template(`<input type=text>`), _tmpl$16 = /* @__PURE__ */ web.template(`<p class="text-xs text-[color:var(--mcp-ui-warning,var(--color-amber-500))] mt-0.5">`), _tmpl$17 = /* @__PURE__ */ web.template(`<p>`), _tmpl$18 = /* @__PURE__ */ web.template(`<p class="text-xs text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]">`), _tmpl$19 = /* @__PURE__ */ web.template(`<p role=alert class="text-xs text-[color:var(--mcp-ui-danger,var(--color-red-600))] dark:text-[color:var(--mcp-ui-danger,var(--color-red-400))]">`), _tmpl$20 = /* @__PURE__ */ web.template(`<div class=space-y-1><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$21 = /* @__PURE__ */ web.template(`<option>`), _tmpl$22 = /* @__PURE__ */ web.template(`<label class="flex items-center gap-2 cursor-pointer"><input type=radio class="w-4 h-4 border-[color:var(--mcp-ui-border-control,var(--color-gray-300,#d1d5db))] text-[color:var(--mcp-ui-accent,var(--color-blue-600))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))]"><span class="text-sm text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))]">`), _tmpl$23 = /* @__PURE__ */ web.template(`<div class="flex flex-wrap gap-1 mb-1">`), _tmpl$24 = /* @__PURE__ */ web.template(`<div class="p-2 border-b border-[color:var(--mcp-ui-border-control,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))] flex-shrink-0"><input type=text class="w-full px-2 py-1 text-sm border border-[color:var(--mcp-ui-border-control,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))] rounded bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-700,#374151))] text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] focus:border-[color:var(--mcp-ui-focus,var(--color-blue-400))] outline-none"autofocus>`), _tmpl$25 = /* @__PURE__ */ web.template(`<p class="px-3 py-2 text-sm text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]">`), _tmpl$26 = /* @__PURE__ */ web.template(`<div class="absolute z-50 mt-1 w-full bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border-control,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))] rounded-md shadow-[var(--mcp-ui-shadow,var(--shadow-lg))]"style=max-height:320px;display:flex;flex-direction:column><!$><!/><div style=overflow-y:auto;flex:1;-webkit-overflow-scrolling:touch><!$><!/><!$><!/>`), _tmpl$27 = /* @__PURE__ */ web.template(`<div class=relative><!$><!/><button type=button><span></span><svg class="w-4 h-4 text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M19 9l-7 7-7-7"></path></svg></button><!$><!/>`), _tmpl$28 = /* @__PURE__ */ web.template(`<span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-[color:var(--mcp-ui-accent-soft,var(--color-blue-100))] dark:bg-[color:var(--mcp-ui-accent-soft,color-mix(in_oklab,var(--color-blue-900)_30%,transparent))] text-[color:var(--mcp-ui-accent,var(--color-blue-700))] dark:text-[color:var(--mcp-ui-accent,var(--color-blue-300))] rounded-full"><!$><!/><button type=button class="hover:text-[color:var(--mcp-ui-accent,var(--color-blue-900))] dark:hover:text-[color:var(--mcp-ui-accent,var(--color-blue-100))]">×`), _tmpl$29 = /* @__PURE__ */ web.template(`<label class="flex items-center gap-2 px-3 py-2 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))] cursor-pointer text-sm"><input type=checkbox class="w-4 h-4 rounded border-[color:var(--mcp-ui-border-control,var(--color-gray-300,#d1d5db))] text-[color:var(--mcp-ui-accent,var(--color-blue-600))] focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))]"><span class="text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))]">`), _tmpl$30 = /* @__PURE__ */ web.template(`<div class="flex items-center gap-1 mb-1 text-xs text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"><span class="animate-spin h-3 w-3 border border-[color:var(--mcp-ui-border-control,var(--color-gray-400,#9ca3af))] border-t-transparent rounded-full"></span><!$><!/>`), _tmpl$31 = /* @__PURE__ */ web.template(`<div class="absolute z-20 mt-1 w-full bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border-control,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))] rounded-md shadow-[var(--mcp-ui-shadow,var(--shadow-lg))] max-h-72 overflow-y-auto">`), _tmpl$32 = /* @__PURE__ */ web.template(`<div class=relative><!$><!/><!$><!/><input type=text autocomplete=off><!$><!/>`), _tmpl$33 = /* @__PURE__ */ web.template(`<span class="ml-2 text-xs">✓`), _tmpl$34 = /* @__PURE__ */ web.template(`<button type=button><!$><!/><!$><!/>`), _tmpl$35 = /* @__PURE__ */ web.template(`<div><!$><!/><input type=text>`);
|
|
9
9
|
const SOURCE_BADGES = {
|
|
10
10
|
detected: {
|
|
11
11
|
icon: "✅",
|
|
@@ -43,12 +43,13 @@ const FormFieldRenderer = (props) => {
|
|
|
43
43
|
};
|
|
44
44
|
const baseInputClass = () => `
|
|
45
45
|
w-full px-3 py-2 border rounded-md
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
${!isMuted() ? "text-[color:var(--mcp-ui-fg,inherit)]" : ""}
|
|
47
|
+
focus:ring-2 focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))] focus:border-[color:var(--mcp-ui-focus,var(--color-blue-500))]
|
|
48
|
+
disabled:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-100,#f3f4f6))] disabled:cursor-not-allowed
|
|
49
|
+
${props.error ? "border-[color:var(--mcp-ui-danger-border,var(--color-red-500))] focus:ring-[color:var(--mcp-ui-focus,var(--color-red-500))]" : "border-[color:var(--mcp-ui-border-control,var(--color-gray-300,#d1d5db))] dark:border-[color:var(--mcp-ui-border-control,var(--color-gray-600,#4b5563))]"}
|
|
50
|
+
dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))]
|
|
50
51
|
${isUnsupported() ? "opacity-50" : ""}
|
|
51
|
-
${isMuted() ? "bg-gray-50 dark:bg-gray-700
|
|
52
|
+
${isMuted() ? "bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-50,#f9fafb))] dark:bg-[color:var(--mcp-ui-surface-muted,color-mix(in_oklab,var(--color-gray-700,#374151)_50%,transparent))] text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]" : ""}
|
|
52
53
|
`;
|
|
53
54
|
const fieldId = () => `field-${props.field.name}`;
|
|
54
55
|
const errorId = () => `${props.field.name}-error`;
|
|
@@ -105,7 +106,7 @@ const FormFieldRenderer = (props) => {
|
|
|
105
106
|
}
|
|
106
107
|
}), _el$14, _co$5);
|
|
107
108
|
web.effect((_p$) => {
|
|
108
|
-
var _v$ = fieldId(), _v$2 = `block text-sm font-medium ${isUnsupported() ? "text-gray-400 dark:text-gray-500" : isMuted() ? "text-gray-400 dark:text-gray-500" : "text-gray-700 dark:text-gray-300"}`;
|
|
109
|
+
var _v$ = fieldId(), _v$2 = `block text-sm font-medium ${isUnsupported() ? "text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] dark:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))]" : isMuted() ? "text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] dark:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))]" : "text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))]"}`;
|
|
109
110
|
_v$ !== _p$.e && web.setAttribute(_el$2, "for", _p$.e = _v$);
|
|
110
111
|
_v$2 !== _p$.t && web.className(_el$2, _p$.t = _v$2);
|
|
111
112
|
return _p$;
|
|
@@ -503,7 +504,7 @@ const FormFieldRenderer = (props) => {
|
|
|
503
504
|
_el$38.$$click = () => props.onChange(!props.value);
|
|
504
505
|
web.insert(_el$40, () => props.field.checkboxLabel || props.field.label);
|
|
505
506
|
web.effect((_p$) => {
|
|
506
|
-
var _v$65 = !!props.value, _v$66 = isFieldDisabled(), _v$67 = `relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${props.value ? "bg-blue-600" : "bg-gray-300 dark:bg-gray-600"} ${isFieldDisabled() ? "opacity-50 cursor-not-allowed" : ""}`, _v$68 = `inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform ${props.value ? "translate-x-4" : "translate-x-0.5"}`;
|
|
507
|
+
var _v$65 = !!props.value, _v$66 = isFieldDisabled(), _v$67 = `relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${props.value ? "bg-[color:var(--mcp-ui-accent,var(--color-blue-600))]" : "bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-300,#d1d5db))] dark:bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-600,#4b5563))]"} ${isFieldDisabled() ? "opacity-50 cursor-not-allowed" : ""}`, _v$68 = `inline-block h-3.5 w-3.5 transform rounded-full bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] transition-transform ${props.value ? "translate-x-4" : "translate-x-0.5"}`;
|
|
507
508
|
_v$65 !== _p$.e && web.setAttribute(_el$38, "aria-checked", _p$.e = _v$65);
|
|
508
509
|
_v$66 !== _p$.t && web.setProperty(_el$38, "disabled", _p$.t = _v$66);
|
|
509
510
|
_v$67 !== _p$.a && web.className(_el$38, _p$.a = _v$67);
|
|
@@ -570,7 +571,7 @@ const FormFieldRenderer = (props) => {
|
|
|
570
571
|
get children() {
|
|
571
572
|
var _el$46 = web.getNextElement(_tmpl$17);
|
|
572
573
|
web.insert(_el$46, () => props.field.statusReason);
|
|
573
|
-
web.effect(() => web.className(_el$46, `text-xs ${isUnsupported() ? "text-orange-500 dark:text-orange-400" : status() === "unknown" ? "text-yellow-500 dark:text-yellow-400" : status() === "required" ? "text-blue-500 dark:text-blue-400" : "text-gray-500 dark:text-gray-400"}`));
|
|
574
|
+
web.effect(() => web.className(_el$46, `text-xs ${isUnsupported() ? "text-[color:var(--mcp-ui-warning,var(--color-orange-500))] dark:text-[color:var(--mcp-ui-warning,var(--color-orange-400))]" : status() === "unknown" ? "text-[color:var(--mcp-ui-warning,var(--color-yellow-500))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))]" : status() === "required" ? "text-[color:var(--mcp-ui-accent,var(--color-blue-500))] dark:text-[color:var(--mcp-ui-accent,var(--color-blue-400))]" : "text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"}`));
|
|
574
575
|
return _el$46;
|
|
575
576
|
}
|
|
576
577
|
}), _el$55, _co$10);
|
|
@@ -581,7 +582,7 @@ const FormFieldRenderer = (props) => {
|
|
|
581
582
|
get children() {
|
|
582
583
|
var _el$47 = web.getNextElement(_tmpl$17);
|
|
583
584
|
web.insert(_el$47, () => props.field.displayHint);
|
|
584
|
-
web.effect(() => web.className(_el$47, `text-xs italic ${isMuted() ? "text-gray-400 dark:text-gray-500" : "text-gray-500 dark:text-gray-400"}`));
|
|
585
|
+
web.effect(() => web.className(_el$47, `text-xs italic ${isMuted() ? "text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] dark:text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))]" : "text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"}`));
|
|
585
586
|
return _el$47;
|
|
586
587
|
}
|
|
587
588
|
}), _el$57, _co$11);
|
|
@@ -717,7 +718,7 @@ const MultiSelectField = (props) => {
|
|
|
717
718
|
}
|
|
718
719
|
}), _el$84, _co$18);
|
|
719
720
|
web.effect((_p$) => {
|
|
720
|
-
var _v$77 = props.disabled, _v$78 = `${props.baseClass} text-left flex items-center justify-between`, _v$79 = props.value.length ? "text-gray-900 dark:text-white" : "text-gray-400";
|
|
721
|
+
var _v$77 = props.disabled, _v$78 = `${props.baseClass} text-left flex items-center justify-between`, _v$79 = props.value.length ? "text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))]" : "text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]";
|
|
721
722
|
_v$77 !== _p$.e && web.setProperty(_el$68, "disabled", _p$.e = _v$77);
|
|
722
723
|
_v$78 !== _p$.t && web.className(_el$68, _p$.t = _v$78);
|
|
723
724
|
_v$79 !== _p$.a && web.className(_el$69, _p$.a = _v$79);
|
|
@@ -953,7 +954,7 @@ const AutocompleteField = (props) => {
|
|
|
953
954
|
}
|
|
954
955
|
}), _el$115, _co$26);
|
|
955
956
|
web.effect((_p$) => {
|
|
956
|
-
var _v$83 = `w-full text-left px-3 py-2 text-sm hover:bg-blue-50 dark:hover:bg-blue-900
|
|
957
|
+
var _v$83 = `w-full text-left px-3 py-2 text-sm hover:bg-[color:var(--mcp-ui-accent-soft,var(--color-blue-50))] dark:hover:bg-[color:var(--mcp-ui-accent-soft,color-mix(in_oklab,var(--color-blue-900)_20%,transparent))] ${isSelected() ? "text-[color:var(--mcp-ui-accent,var(--color-blue-600))] dark:text-[color:var(--mcp-ui-accent,var(--color-blue-400))] bg-[color:var(--mcp-ui-accent-soft,color-mix(in_oklab,var(--color-blue-50)_50%,transparent))] dark:bg-[color:var(--mcp-ui-accent-soft,color-mix(in_oklab,var(--color-blue-900)_10%,transparent))]" : "text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))]"}`, _v$84 = isSelected();
|
|
957
958
|
_v$83 !== _p$.e && web.className(_el$110, _p$.e = _v$83);
|
|
958
959
|
_v$84 !== _p$.t && web.setProperty(_el$110, "disabled", _p$.t = _v$84);
|
|
959
960
|
return _p$;
|