@seed-ship/mcp-ui-solid 6.17.0 → 6.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +50 -3
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/presentation.cjs +141 -0
- package/dist/adapters/presentation.cjs.map +1 -0
- package/dist/adapters/presentation.d.ts +68 -0
- package/dist/adapters/presentation.d.ts.map +1 -0
- package/dist/adapters/presentation.js +141 -0
- package/dist/adapters/presentation.js.map +1 -0
- package/dist/adapters.cjs +4 -0
- package/dist/adapters.cjs.map +1 -1
- package/dist/adapters.d.cts +2 -0
- package/dist/adapters.d.ts +2 -0
- package/dist/adapters.js +4 -0
- package/dist/adapters.js.map +1 -1
- package/dist/components/ChartJSRenderer.cjs +165 -65
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +168 -68
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/ComponentToolbar.cjs.map +1 -1
- package/dist/components/ComponentToolbar.d.ts.map +1 -1
- package/dist/components/ComponentToolbar.js.map +1 -1
- package/dist/components/EditableLayoutContext.cjs +17 -0
- package/dist/components/EditableLayoutContext.cjs.map +1 -0
- package/dist/components/EditableLayoutContext.d.ts +5 -0
- package/dist/components/EditableLayoutContext.d.ts.map +1 -0
- package/dist/components/EditableLayoutContext.js +17 -0
- package/dist/components/EditableLayoutContext.js.map +1 -0
- package/dist/components/EditableUIResourceRenderer.cjs +87 -84
- package/dist/components/EditableUIResourceRenderer.cjs.map +1 -1
- package/dist/components/EditableUIResourceRenderer.d.ts.map +1 -1
- package/dist/components/EditableUIResourceRenderer.js +87 -84
- package/dist/components/EditableUIResourceRenderer.js.map +1 -1
- package/dist/components/ElicitationForm.cjs.map +1 -1
- package/dist/components/ElicitationForm.js.map +1 -1
- package/dist/components/FeedbackInline.cjs +0 -1
- package/dist/components/FeedbackInline.cjs.map +1 -1
- package/dist/components/FeedbackInline.js +0 -1
- package/dist/components/FeedbackInline.js.map +1 -1
- package/dist/components/GraphRenderer.cjs.map +1 -1
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/components/GridRenderer.cjs +12 -6
- package/dist/components/GridRenderer.cjs.map +1 -1
- package/dist/components/GridRenderer.d.ts.map +1 -1
- package/dist/components/GridRenderer.js +13 -7
- package/dist/components/GridRenderer.js.map +1 -1
- package/dist/components/MapRenderer.cjs.map +1 -1
- package/dist/components/MapRenderer.d.ts.map +1 -1
- package/dist/components/MapRenderer.js.map +1 -1
- package/dist/components/PresentationFeedback.cjs +0 -1
- package/dist/components/PresentationFeedback.cjs.map +1 -1
- package/dist/components/PresentationFeedback.js +0 -1
- package/dist/components/PresentationFeedback.js.map +1 -1
- package/dist/components/UIResourceRenderer.cjs +37 -22
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +38 -23
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/VerifiedText.cjs +0 -4
- package/dist/components/VerifiedText.cjs.map +1 -1
- package/dist/components/VerifiedText.d.ts.map +1 -1
- package/dist/components/VerifiedText.js +0 -4
- package/dist/components/VerifiedText.js.map +1 -1
- package/dist/components/chart-data-table.cjs +73 -0
- package/dist/components/chart-data-table.cjs.map +1 -0
- package/dist/components/chart-data-table.d.ts +23 -0
- package/dist/components/chart-data-table.d.ts.map +1 -0
- package/dist/components/chart-data-table.js +73 -0
- package/dist/components/chart-data-table.js.map +1 -0
- package/dist/context/MCPUIStringsContext.cjs +10 -9
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +17 -5
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +11 -10
- package/dist/context/MCPUIStringsContext.js.map +1 -1
- package/dist/hooks/createResponsiveGrid.cjs +37 -0
- package/dist/hooks/createResponsiveGrid.cjs.map +1 -0
- package/dist/hooks/createResponsiveGrid.d.ts +6 -0
- package/dist/hooks/createResponsiveGrid.d.ts.map +1 -0
- package/dist/hooks/createResponsiveGrid.js +37 -0
- package/dist/hooks/createResponsiveGrid.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-ui-spec/dist/schemas.cjs +13 -1
- package/dist/mcp-ui-spec/dist/schemas.cjs.map +1 -1
- package/dist/mcp-ui-spec/dist/schemas.js +13 -1
- package/dist/mcp-ui-spec/dist/schemas.js.map +1 -1
- package/dist/services/chat-bus.cjs.map +1 -1
- package/dist/services/chat-bus.d.ts.map +1 -1
- package/dist/services/chat-bus.js.map +1 -1
- package/dist/services/chat-prompt-controller.cjs.map +1 -1
- package/dist/services/chat-prompt-controller.d.ts.map +1 -1
- package/dist/services/chat-prompt-controller.js.map +1 -1
- package/dist/services/component-registry.cjs +162 -22
- package/dist/services/component-registry.cjs.map +1 -1
- package/dist/services/component-registry.d.ts +6 -3
- package/dist/services/component-registry.d.ts.map +1 -1
- package/dist/services/component-registry.js +162 -22
- package/dist/services/component-registry.js.map +1 -1
- package/dist/services/telemetry.cjs +0 -1
- package/dist/services/telemetry.cjs.map +1 -1
- package/dist/services/telemetry.js +0 -1
- package/dist/services/telemetry.js.map +1 -1
- package/dist/services/validation.cjs +21 -7
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +21 -7
- package/dist/services/validation.js.map +1 -1
- package/dist/types/index.d.ts +43 -8
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types.d.cts +43 -8
- package/dist/types.d.ts +43 -8
- package/docs/briefs/VISUALIZATION-FOUNDATION-2026-09-14.md +105 -0
- package/package.json +4 -4
- package/src/adapters/index.ts +18 -0
- package/src/adapters/presentation.test.ts +114 -0
- package/src/adapters/presentation.ts +229 -0
- package/src/components/ChartJSRenderer.test.tsx +325 -0
- package/src/components/ChartJSRenderer.tsx +162 -27
- package/src/components/ChatPrompt.test.tsx +1 -1
- package/src/components/ComponentToolbar.tsx +1 -1
- package/src/components/EditableLayoutContext.tsx +12 -0
- package/src/components/EditableUIResourceRenderer.tsx +11 -8
- package/src/components/ElicitationForm.tsx +1 -1
- package/src/components/FeedbackInline.tsx +1 -1
- package/src/components/GraphRenderer.test.tsx +1 -2
- package/src/components/GraphRenderer.tsx +0 -2
- package/src/components/GridRenderer.tsx +6 -4
- package/src/components/MapRenderer.tsx +0 -3
- package/src/components/PresentationFeedback.tsx +1 -1
- package/src/components/ResponsiveGrid.test.tsx +166 -0
- package/src/components/TableRenderer.pagination.test.tsx +31 -0
- package/src/components/UIResourceRenderer.tsx +14 -9
- package/src/components/VerifiedText.tsx +0 -5
- package/src/components/chart-data-table.ts +97 -0
- package/src/context/MCPUIStringsContext.test.tsx +60 -0
- package/src/context/MCPUIStringsContext.tsx +31 -12
- package/src/hooks/createResponsiveGrid.ts +41 -0
- package/src/services/chat-bus.test.ts +1 -1
- package/src/services/chat-bus.ts +0 -2
- package/src/services/chat-prompt-controller.ts +0 -8
- package/src/services/component-registry.test.ts +81 -2
- package/src/services/component-registry.ts +167 -23
- package/src/services/telemetry.ts +1 -1
- package/src/services/validation.test.ts +1 -14
- package/src/services/validation.ts +23 -6
- package/src/services/visualization-validation.test.ts +42 -0
- package/src/types/index.ts +50 -9
- package/src/types/visualization-contracts.test.ts +66 -0
- package/src/utils/perf.test.ts +3 -3
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PresentationFeedback.cjs","sources":["../../src/components/PresentationFeedback.tsx"],"sourcesContent":["/**\n * PresentationFeedback — feedback on how a connector result was *presented*.\n *\n * @experimental\n * @since v6.6.0 (R3 / D9 of ROADMAP-opendata-macro-mcpui)\n *\n * ## A separate axis from `FeedbackInline`\n *\n * MCP-UI has two distinct feedback widgets, kept separate on purpose\n * (cf. R3) :\n *\n * - **`FeedbackInline`** — was the *answer* good? (response quality)\n * - **`PresentationFeedback`** (this) — was the answer *shown well*?\n * (layout / readability)\n *\n * They are separate components, separate exports, separate payloads — so\n * the two axes never collapse into one in the UX or in the logs.\n *\n * ## Stateless — host owns persistence and re-render\n *\n * On submit the component calls `onSubmit(feedback)` with a\n * `ConnectorRenderFeedback` payload and flips to its acknowledgement state.\n * It does NOT persist anything and does NOT re-render the result itself\n * (cf. D1 : adapter pure + host-owned state). The host persists the\n * feedback and, if it wants to \"close the loop\", re-runs its adapter with\n * the corrected `preferredLayout`.\n *\n * Submission is best-effort : a rejected `onSubmit` promise is swallowed,\n * the UI still flips.\n *\n * ## Localization\n *\n * All labels ship in English and are overridable via the `labels` prop\n * (partial). This component carries its own label bag rather than routing\n * through `MCPUIStringsProvider` — its label set is large and specific to\n * this one widget.\n *\n * @example\n * ```tsx\n * <PresentationFeedback\n * connectorId=\"datagouv\"\n * toolName=\"datagouv.search\"\n * queryHash={result.queryHash}\n * layoutType=\"table\"\n * preferredLayoutOptions={['table', 'bar', 'map']}\n * onSubmit={(fb) => fetch('/api/render-feedback', {\n * method: 'POST', body: JSON.stringify(fb),\n * })}\n * />\n * ```\n */\n\nimport { Component, Show, For, createSignal } from 'solid-js'\nimport type {\n ConnectorRenderFeedback,\n ConnectorRenderProblem,\n ConnectorPreferredLayout,\n} from '@seed-ship/mcp-ui-spec'\n\n/** The full set of problem tags, in display order. */\nconst PROBLEM_ORDER: ConnectorRenderProblem[] = [\n 'too_raw',\n 'wrong_columns',\n 'wrong_chart',\n 'missing_context',\n 'wrong_unit',\n 'bad_grouping',\n 'missing_dataset_context',\n]\n\nexport interface PresentationFeedbackLabels {\n /** Resting-state question. */\n prompt: string\n /** Positive verdict button. */\n readable: string\n /** Negative verdict button — opens the detail step. */\n notReadable: string\n /** Heading of the detail step. */\n problemsPrompt: string\n /** Per-problem chip labels. */\n problemTooRaw: string\n problemWrongColumns: string\n problemWrongChart: string\n problemMissingContext: string\n problemWrongUnit: string\n problemBadGrouping: string\n problemMissingDatasetContext: string\n /** Heading of the optional layout picker. */\n preferLayoutPrompt: string\n /** Free-text comment placeholder. */\n commentPlaceholder: string\n /** Submit button of the detail step. */\n submit: string\n /** Acknowledgement shown after submission. */\n ack: string\n}\n\n/** English defaults. Override via the `labels` prop for other locales. */\nexport const DEFAULT_PRESENTATION_FEEDBACK_LABELS: PresentationFeedbackLabels = {\n prompt: 'Is this shown clearly?',\n readable: 'Clear',\n notReadable: 'Not clear',\n problemsPrompt: \"What's off?\",\n problemTooRaw: 'Too raw',\n problemWrongColumns: 'Wrong columns',\n problemWrongChart: 'Wrong chart',\n problemMissingContext: 'Missing context',\n problemWrongUnit: 'Wrong unit',\n problemBadGrouping: 'Bad grouping',\n problemMissingDatasetContext: 'Missing dataset context',\n preferLayoutPrompt: 'Better shown as',\n commentPlaceholder: 'Anything else? (optional)',\n submit: 'Send feedback',\n ack: 'Thanks — noted.',\n}\n\nconst PROBLEM_LABEL_KEY: Record<ConnectorRenderProblem, keyof PresentationFeedbackLabels> = {\n too_raw: 'problemTooRaw',\n wrong_columns: 'problemWrongColumns',\n wrong_chart: 'problemWrongChart',\n missing_context: 'problemMissingContext',\n wrong_unit: 'problemWrongUnit',\n bad_grouping: 'problemBadGrouping',\n missing_dataset_context: 'problemMissingDatasetContext',\n}\n\nexport interface PresentationFeedbackProps {\n /** Connector whose result is being rated. */\n connectorId: string\n /** Tool that produced the result. */\n toolName: string\n /** Stable key tying feedback to a `ConnectorDynamicResultV1.queryHash`. */\n queryHash?: string\n /** What is being rated (e.g. `'primary'`). Passed through to the payload. */\n renderKind?: string\n /** The layout type currently shown (e.g. `'table'`). Passed through. */\n layoutType?: string\n /**\n * Called once on submit with the assembled `ConnectorRenderFeedback`.\n * Persistence + any re-render are the host's responsibility.\n */\n onSubmit: (feedback: ConnectorRenderFeedback) => void | Promise<void>\n /**\n * Layout alternatives offered in the detail step. Omit (or pass an empty\n * array) to hide the layout picker entirely.\n */\n preferredLayoutOptions?: ConnectorPreferredLayout[]\n /** Partial label override (English defaults otherwise). */\n labels?: Partial<PresentationFeedbackLabels>\n /** Extra Tailwind classes on the container. */\n class?: string\n}\n\n/**\n * @experimental\n * Presentation-quality feedback widget (readable / not-readable + detail).\n */\nexport const PresentationFeedback: Component<PresentationFeedbackProps> = (props) => {\n const [step, setStep] = createSignal<'idle' | 'detail' | 'done'>('idle')\n const [problems, setProblems] = createSignal<Set<ConnectorRenderProblem>>(new Set())\n const [preferred, setPreferred] = createSignal<ConnectorPreferredLayout | undefined>(undefined)\n const [comment, setComment] = createSignal('')\n\n const label = (key: keyof PresentationFeedbackLabels): string =>\n props.labels?.[key] ?? DEFAULT_PRESENTATION_FEEDBACK_LABELS[key]\n\n const emit = (feedback: ConnectorRenderFeedback) => {\n try {\n // Fire-and-forget — feedback is best-effort, a rejection must not\n // break the UI (mirrors FeedbackInline).\n const result = props.onSubmit(feedback)\n if (result && typeof (result as Promise<void>).catch === 'function') {\n ;(result as Promise<void>).catch(() => {\n /* non-blocking */\n })\n }\n } catch {\n /* non-blocking */\n }\n setStep('done')\n }\n\n const base = (): Pick<\n ConnectorRenderFeedback,\n 'connectorId' | 'toolName' | 'queryHash' | 'renderKind' | 'layoutType'\n > => ({\n connectorId: props.connectorId,\n toolName: props.toolName,\n ...(props.queryHash ? { queryHash: props.queryHash } : {}),\n ...(props.renderKind ? { renderKind: props.renderKind } : {}),\n ...(props.layoutType ? { layoutType: props.layoutType } : {}),\n })\n\n const submitReadable = () => emit({ ...base(), verdict: 'readable' })\n\n const submitNotReadable = () => {\n const picked = [...problems()]\n const text = comment().trim()\n emit({\n ...base(),\n verdict: 'not_readable',\n ...(picked.length > 0 ? { problems: picked } : {}),\n ...(preferred() ? { preferredLayout: preferred() } : {}),\n ...(text ? { comment: text } : {}),\n })\n }\n\n const toggleProblem = (p: ConnectorRenderProblem) => {\n setProblems((prev) => {\n const next = new Set(prev)\n if (next.has(p)) next.delete(p)\n else next.add(p)\n return next\n })\n }\n\n return (\n <div\n class={`text-xs ${props.class ?? ''}`.trim()}\n data-presentation-feedback-step={step()}\n >\n {/* ── Step 1 : verdict ─────────────────────────────── */}\n <Show when={step() === 'idle'}>\n <div class=\"flex items-center gap-2\">\n <span class=\"text-deposium-slate-500\">{label('prompt')}</span>\n <button\n type=\"button\"\n onClick={submitReadable}\n class=\"px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-green-500 hover:text-green-600 transition-colors\"\n data-presentation-feedback-verdict=\"readable\"\n >\n {label('readable')}\n </button>\n <button\n type=\"button\"\n onClick={() => setStep('detail')}\n class=\"px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-amber-500 hover:text-amber-600 transition-colors\"\n data-presentation-feedback-verdict=\"not_readable\"\n >\n {label('notReadable')}\n </button>\n </div>\n </Show>\n\n {/* ── Step 2 : detail ──────────────────────────────── */}\n <Show when={step() === 'detail'}>\n <div class=\"flex flex-col gap-2 p-2 rounded-lg border border-gray-200 dark:border-gray-700\">\n <span class=\"font-medium text-deposium-slate-600 dark:text-gray-300\">\n {label('problemsPrompt')}\n </span>\n\n {/* Problem chips */}\n <div class=\"flex flex-wrap gap-1\">\n <For each={PROBLEM_ORDER}>\n {(p) => (\n <button\n type=\"button\"\n onClick={() => toggleProblem(p)}\n aria-pressed={problems().has(p)}\n data-presentation-feedback-problem={p}\n class={`px-2 py-0.5 rounded-full border transition-colors ${\n problems().has(p)\n ? 'border-amber-500 bg-amber-50 dark:bg-amber-900/30 text-amber-700 dark:text-amber-200'\n : 'border-gray-200 dark:border-gray-600 text-deposium-slate-500 hover:border-amber-400'\n }`}\n >\n {label(PROBLEM_LABEL_KEY[p])}\n </button>\n )}\n </For>\n </div>\n\n {/* Optional layout picker */}\n <Show when={(props.preferredLayoutOptions?.length ?? 0) > 0}>\n <div class=\"flex flex-wrap items-center gap-1\">\n <span class=\"text-deposium-slate-500\">{label('preferLayoutPrompt')}</span>\n <For each={props.preferredLayoutOptions}>\n {(opt) => (\n <button\n type=\"button\"\n onClick={() => setPreferred((cur) => (cur === opt ? undefined : opt))}\n aria-pressed={preferred() === opt}\n data-presentation-feedback-layout={opt}\n class={`px-2 py-0.5 rounded border transition-colors ${\n preferred() === opt\n ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-200'\n : 'border-gray-200 dark:border-gray-600 text-deposium-slate-500 hover:border-blue-400'\n }`}\n >\n {opt}\n </button>\n )}\n </For>\n </div>\n </Show>\n\n {/* Free-text comment */}\n <textarea\n value={comment()}\n onInput={(e) => setComment(e.currentTarget.value)}\n placeholder={label('commentPlaceholder')}\n rows={2}\n class=\"w-full rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 p-1.5 text-xs resize-y\"\n data-presentation-feedback-comment\n />\n\n <button\n type=\"button\"\n onClick={submitNotReadable}\n class=\"self-end px-3 py-1 rounded bg-amber-500 text-white font-medium hover:bg-amber-600 transition-colors\"\n data-presentation-feedback-submit\n >\n {label('submit')}\n </button>\n </div>\n </Show>\n\n {/* ── Step 3 : acknowledgement ─────────────────────── */}\n <Show when={step() === 'done'}>\n <span class=\"text-deposium-slate-500\" data-presentation-feedback-ack>\n {label('ack')}\n </span>\n </Show>\n </div>\n )\n}\n"],"names":["PROBLEM_ORDER","DEFAULT_PRESENTATION_FEEDBACK_LABELS","prompt","readable","notReadable","problemsPrompt","problemTooRaw","problemWrongColumns","problemWrongChart","problemMissingContext","problemWrongUnit","problemBadGrouping","problemMissingDatasetContext","preferLayoutPrompt","commentPlaceholder","submit","ack","PROBLEM_LABEL_KEY","too_raw","wrong_columns","wrong_chart","missing_context","wrong_unit","bad_grouping","missing_dataset_context","PresentationFeedback","props","step","setStep","createSignal","problems","setProblems","Set","preferred","setPreferred","undefined","comment","setComment","label","key","labels","emit","feedback","result","onSubmit","catch","base","connectorId","toolName","queryHash","renderKind","layoutType","submitReadable","verdict","submitNotReadable","picked","text","trim","length","preferredLayout","toggleProblem","p","prev","next","has","delete","add","_el$","_$getNextElement","_tmpl$5","_el$16","firstChild","_el$17","_co$3","_$getNextMarker","nextSibling","_el$18","_el$19","_co$4","_el$20","_el$21","_co$5","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","_el$4","_el$5","$$click","_$runHydrationEvents","_el$6","_tmpl$3","_el$7","_el$8","_el$13","_el$14","_co$2","_el$11","_el$12","For","each","_el$22","_tmpl$6","_$setAttribute","_$effect","_p$","_v$3","_v$4","e","t","_$className","preferredLayoutOptions","_el$9","_tmpl$2","_el$0","_el$1","_el$10","_co$","opt","_el$23","cur","_v$5","_v$6","$$input","currentTarget","value","_$setProperty","_el$15","_tmpl$4","_v$","class","_v$2","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PresentationFeedback.cjs","sources":["../../src/components/PresentationFeedback.tsx"],"sourcesContent":["/**\n * PresentationFeedback — feedback on how a connector result was *presented*.\n *\n * @experimental\n * @since v6.6.0 (R3 / D9 of ROADMAP-opendata-macro-mcpui)\n *\n * ## A separate axis from `FeedbackInline`\n *\n * MCP-UI has two distinct feedback widgets, kept separate on purpose\n * (cf. R3) :\n *\n * - **`FeedbackInline`** — was the *answer* good? (response quality)\n * - **`PresentationFeedback`** (this) — was the answer *shown well*?\n * (layout / readability)\n *\n * They are separate components, separate exports, separate payloads — so\n * the two axes never collapse into one in the UX or in the logs.\n *\n * ## Stateless — host owns persistence and re-render\n *\n * On submit the component calls `onSubmit(feedback)` with a\n * `ConnectorRenderFeedback` payload and flips to its acknowledgement state.\n * It does NOT persist anything and does NOT re-render the result itself\n * (cf. D1 : adapter pure + host-owned state). The host persists the\n * feedback and, if it wants to \"close the loop\", re-runs its adapter with\n * the corrected `preferredLayout`.\n *\n * Submission is best-effort : a rejected `onSubmit` promise is swallowed,\n * the UI still flips.\n *\n * ## Localization\n *\n * All labels ship in English and are overridable via the `labels` prop\n * (partial). This component carries its own label bag rather than routing\n * through `MCPUIStringsProvider` — its label set is large and specific to\n * this one widget.\n *\n * @example\n * ```tsx\n * <PresentationFeedback\n * connectorId=\"datagouv\"\n * toolName=\"datagouv.search\"\n * queryHash={result.queryHash}\n * layoutType=\"table\"\n * preferredLayoutOptions={['table', 'bar', 'map']}\n * onSubmit={(fb) => fetch('/api/render-feedback', {\n * method: 'POST', body: JSON.stringify(fb),\n * })}\n * />\n * ```\n */\n\nimport { Component, Show, For, createSignal } from 'solid-js'\nimport type {\n ConnectorRenderFeedback,\n ConnectorRenderProblem,\n ConnectorPreferredLayout,\n} from '@seed-ship/mcp-ui-spec'\n\n/** The full set of problem tags, in display order. */\nconst PROBLEM_ORDER: ConnectorRenderProblem[] = [\n 'too_raw',\n 'wrong_columns',\n 'wrong_chart',\n 'missing_context',\n 'wrong_unit',\n 'bad_grouping',\n 'missing_dataset_context',\n]\n\nexport interface PresentationFeedbackLabels {\n /** Resting-state question. */\n prompt: string\n /** Positive verdict button. */\n readable: string\n /** Negative verdict button — opens the detail step. */\n notReadable: string\n /** Heading of the detail step. */\n problemsPrompt: string\n /** Per-problem chip labels. */\n problemTooRaw: string\n problemWrongColumns: string\n problemWrongChart: string\n problemMissingContext: string\n problemWrongUnit: string\n problemBadGrouping: string\n problemMissingDatasetContext: string\n /** Heading of the optional layout picker. */\n preferLayoutPrompt: string\n /** Free-text comment placeholder. */\n commentPlaceholder: string\n /** Submit button of the detail step. */\n submit: string\n /** Acknowledgement shown after submission. */\n ack: string\n}\n\n/** English defaults. Override via the `labels` prop for other locales. */\nexport const DEFAULT_PRESENTATION_FEEDBACK_LABELS: PresentationFeedbackLabels = {\n prompt: 'Is this shown clearly?',\n readable: 'Clear',\n notReadable: 'Not clear',\n problemsPrompt: \"What's off?\",\n problemTooRaw: 'Too raw',\n problemWrongColumns: 'Wrong columns',\n problemWrongChart: 'Wrong chart',\n problemMissingContext: 'Missing context',\n problemWrongUnit: 'Wrong unit',\n problemBadGrouping: 'Bad grouping',\n problemMissingDatasetContext: 'Missing dataset context',\n preferLayoutPrompt: 'Better shown as',\n commentPlaceholder: 'Anything else? (optional)',\n submit: 'Send feedback',\n ack: 'Thanks — noted.',\n}\n\nconst PROBLEM_LABEL_KEY: Record<ConnectorRenderProblem, keyof PresentationFeedbackLabels> = {\n too_raw: 'problemTooRaw',\n wrong_columns: 'problemWrongColumns',\n wrong_chart: 'problemWrongChart',\n missing_context: 'problemMissingContext',\n wrong_unit: 'problemWrongUnit',\n bad_grouping: 'problemBadGrouping',\n missing_dataset_context: 'problemMissingDatasetContext',\n}\n\nexport interface PresentationFeedbackProps {\n /** Connector whose result is being rated. */\n connectorId: string\n /** Tool that produced the result. */\n toolName: string\n /** Stable key tying feedback to a `ConnectorDynamicResultV1.queryHash`. */\n queryHash?: string\n /** What is being rated (e.g. `'primary'`). Passed through to the payload. */\n renderKind?: string\n /** The layout type currently shown (e.g. `'table'`). Passed through. */\n layoutType?: string\n /**\n * Called once on submit with the assembled `ConnectorRenderFeedback`.\n * Persistence + any re-render are the host's responsibility.\n */\n onSubmit: (feedback: ConnectorRenderFeedback) => void | Promise<void>\n /**\n * Layout alternatives offered in the detail step. Omit (or pass an empty\n * array) to hide the layout picker entirely.\n */\n preferredLayoutOptions?: ConnectorPreferredLayout[]\n /** Partial label override (English defaults otherwise). */\n labels?: Partial<PresentationFeedbackLabels>\n /** Extra Tailwind classes on the container. */\n class?: string\n}\n\n/**\n * @experimental\n * Presentation-quality feedback widget (readable / not-readable + detail).\n */\nexport const PresentationFeedback: Component<PresentationFeedbackProps> = (props) => {\n const [step, setStep] = createSignal<'idle' | 'detail' | 'done'>('idle')\n const [problems, setProblems] = createSignal<Set<ConnectorRenderProblem>>(new Set())\n const [preferred, setPreferred] = createSignal<ConnectorPreferredLayout | undefined>(undefined)\n const [comment, setComment] = createSignal('')\n\n const label = (key: keyof PresentationFeedbackLabels): string =>\n props.labels?.[key] ?? DEFAULT_PRESENTATION_FEEDBACK_LABELS[key]\n\n const emit = (feedback: ConnectorRenderFeedback) => {\n try {\n // Fire-and-forget — feedback is best-effort, a rejection must not\n // break the UI (mirrors FeedbackInline).\n const result = props.onSubmit(feedback)\n if (result && typeof (result as Promise<void>).catch === 'function') {\n (result as Promise<void>).catch(() => {\n /* non-blocking */\n })\n }\n } catch {\n /* non-blocking */\n }\n setStep('done')\n }\n\n const base = (): Pick<\n ConnectorRenderFeedback,\n 'connectorId' | 'toolName' | 'queryHash' | 'renderKind' | 'layoutType'\n > => ({\n connectorId: props.connectorId,\n toolName: props.toolName,\n ...(props.queryHash ? { queryHash: props.queryHash } : {}),\n ...(props.renderKind ? { renderKind: props.renderKind } : {}),\n ...(props.layoutType ? { layoutType: props.layoutType } : {}),\n })\n\n const submitReadable = () => emit({ ...base(), verdict: 'readable' })\n\n const submitNotReadable = () => {\n const picked = [...problems()]\n const text = comment().trim()\n emit({\n ...base(),\n verdict: 'not_readable',\n ...(picked.length > 0 ? { problems: picked } : {}),\n ...(preferred() ? { preferredLayout: preferred() } : {}),\n ...(text ? { comment: text } : {}),\n })\n }\n\n const toggleProblem = (p: ConnectorRenderProblem) => {\n setProblems((prev) => {\n const next = new Set(prev)\n if (next.has(p)) next.delete(p)\n else next.add(p)\n return next\n })\n }\n\n return (\n <div\n class={`text-xs ${props.class ?? ''}`.trim()}\n data-presentation-feedback-step={step()}\n >\n {/* ── Step 1 : verdict ─────────────────────────────── */}\n <Show when={step() === 'idle'}>\n <div class=\"flex items-center gap-2\">\n <span class=\"text-deposium-slate-500\">{label('prompt')}</span>\n <button\n type=\"button\"\n onClick={submitReadable}\n class=\"px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-green-500 hover:text-green-600 transition-colors\"\n data-presentation-feedback-verdict=\"readable\"\n >\n {label('readable')}\n </button>\n <button\n type=\"button\"\n onClick={() => setStep('detail')}\n class=\"px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-amber-500 hover:text-amber-600 transition-colors\"\n data-presentation-feedback-verdict=\"not_readable\"\n >\n {label('notReadable')}\n </button>\n </div>\n </Show>\n\n {/* ── Step 2 : detail ──────────────────────────────── */}\n <Show when={step() === 'detail'}>\n <div class=\"flex flex-col gap-2 p-2 rounded-lg border border-gray-200 dark:border-gray-700\">\n <span class=\"font-medium text-deposium-slate-600 dark:text-gray-300\">\n {label('problemsPrompt')}\n </span>\n\n {/* Problem chips */}\n <div class=\"flex flex-wrap gap-1\">\n <For each={PROBLEM_ORDER}>\n {(p) => (\n <button\n type=\"button\"\n onClick={() => toggleProblem(p)}\n aria-pressed={problems().has(p)}\n data-presentation-feedback-problem={p}\n class={`px-2 py-0.5 rounded-full border transition-colors ${\n problems().has(p)\n ? 'border-amber-500 bg-amber-50 dark:bg-amber-900/30 text-amber-700 dark:text-amber-200'\n : 'border-gray-200 dark:border-gray-600 text-deposium-slate-500 hover:border-amber-400'\n }`}\n >\n {label(PROBLEM_LABEL_KEY[p])}\n </button>\n )}\n </For>\n </div>\n\n {/* Optional layout picker */}\n <Show when={(props.preferredLayoutOptions?.length ?? 0) > 0}>\n <div class=\"flex flex-wrap items-center gap-1\">\n <span class=\"text-deposium-slate-500\">{label('preferLayoutPrompt')}</span>\n <For each={props.preferredLayoutOptions}>\n {(opt) => (\n <button\n type=\"button\"\n onClick={() => setPreferred((cur) => (cur === opt ? undefined : opt))}\n aria-pressed={preferred() === opt}\n data-presentation-feedback-layout={opt}\n class={`px-2 py-0.5 rounded border transition-colors ${\n preferred() === opt\n ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-200'\n : 'border-gray-200 dark:border-gray-600 text-deposium-slate-500 hover:border-blue-400'\n }`}\n >\n {opt}\n </button>\n )}\n </For>\n </div>\n </Show>\n\n {/* Free-text comment */}\n <textarea\n value={comment()}\n onInput={(e) => setComment(e.currentTarget.value)}\n placeholder={label('commentPlaceholder')}\n rows={2}\n class=\"w-full rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 p-1.5 text-xs resize-y\"\n data-presentation-feedback-comment\n />\n\n <button\n type=\"button\"\n onClick={submitNotReadable}\n class=\"self-end px-3 py-1 rounded bg-amber-500 text-white font-medium hover:bg-amber-600 transition-colors\"\n data-presentation-feedback-submit\n >\n {label('submit')}\n </button>\n </div>\n </Show>\n\n {/* ── Step 3 : acknowledgement ─────────────────────── */}\n <Show when={step() === 'done'}>\n <span class=\"text-deposium-slate-500\" data-presentation-feedback-ack>\n {label('ack')}\n </span>\n </Show>\n </div>\n )\n}\n"],"names":["PROBLEM_ORDER","DEFAULT_PRESENTATION_FEEDBACK_LABELS","prompt","readable","notReadable","problemsPrompt","problemTooRaw","problemWrongColumns","problemWrongChart","problemMissingContext","problemWrongUnit","problemBadGrouping","problemMissingDatasetContext","preferLayoutPrompt","commentPlaceholder","submit","ack","PROBLEM_LABEL_KEY","too_raw","wrong_columns","wrong_chart","missing_context","wrong_unit","bad_grouping","missing_dataset_context","PresentationFeedback","props","step","setStep","createSignal","problems","setProblems","Set","preferred","setPreferred","undefined","comment","setComment","label","key","labels","emit","feedback","result","onSubmit","catch","base","connectorId","toolName","queryHash","renderKind","layoutType","submitReadable","verdict","submitNotReadable","picked","text","trim","length","preferredLayout","toggleProblem","p","prev","next","has","delete","add","_el$","_$getNextElement","_tmpl$5","_el$16","firstChild","_el$17","_co$3","_$getNextMarker","nextSibling","_el$18","_el$19","_co$4","_el$20","_el$21","_co$5","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","_el$4","_el$5","$$click","_$runHydrationEvents","_el$6","_tmpl$3","_el$7","_el$8","_el$13","_el$14","_co$2","_el$11","_el$12","For","each","_el$22","_tmpl$6","_$setAttribute","_$effect","_p$","_v$3","_v$4","e","t","_$className","preferredLayoutOptions","_el$9","_tmpl$2","_el$0","_el$1","_el$10","_co$","opt","_el$23","cur","_v$5","_v$6","$$input","currentTarget","value","_$setProperty","_el$15","_tmpl$4","_v$","class","_v$2","_$delegateEvents"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PresentationFeedback.js","sources":["../../src/components/PresentationFeedback.tsx"],"sourcesContent":["/**\n * PresentationFeedback — feedback on how a connector result was *presented*.\n *\n * @experimental\n * @since v6.6.0 (R3 / D9 of ROADMAP-opendata-macro-mcpui)\n *\n * ## A separate axis from `FeedbackInline`\n *\n * MCP-UI has two distinct feedback widgets, kept separate on purpose\n * (cf. R3) :\n *\n * - **`FeedbackInline`** — was the *answer* good? (response quality)\n * - **`PresentationFeedback`** (this) — was the answer *shown well*?\n * (layout / readability)\n *\n * They are separate components, separate exports, separate payloads — so\n * the two axes never collapse into one in the UX or in the logs.\n *\n * ## Stateless — host owns persistence and re-render\n *\n * On submit the component calls `onSubmit(feedback)` with a\n * `ConnectorRenderFeedback` payload and flips to its acknowledgement state.\n * It does NOT persist anything and does NOT re-render the result itself\n * (cf. D1 : adapter pure + host-owned state). The host persists the\n * feedback and, if it wants to \"close the loop\", re-runs its adapter with\n * the corrected `preferredLayout`.\n *\n * Submission is best-effort : a rejected `onSubmit` promise is swallowed,\n * the UI still flips.\n *\n * ## Localization\n *\n * All labels ship in English and are overridable via the `labels` prop\n * (partial). This component carries its own label bag rather than routing\n * through `MCPUIStringsProvider` — its label set is large and specific to\n * this one widget.\n *\n * @example\n * ```tsx\n * <PresentationFeedback\n * connectorId=\"datagouv\"\n * toolName=\"datagouv.search\"\n * queryHash={result.queryHash}\n * layoutType=\"table\"\n * preferredLayoutOptions={['table', 'bar', 'map']}\n * onSubmit={(fb) => fetch('/api/render-feedback', {\n * method: 'POST', body: JSON.stringify(fb),\n * })}\n * />\n * ```\n */\n\nimport { Component, Show, For, createSignal } from 'solid-js'\nimport type {\n ConnectorRenderFeedback,\n ConnectorRenderProblem,\n ConnectorPreferredLayout,\n} from '@seed-ship/mcp-ui-spec'\n\n/** The full set of problem tags, in display order. */\nconst PROBLEM_ORDER: ConnectorRenderProblem[] = [\n 'too_raw',\n 'wrong_columns',\n 'wrong_chart',\n 'missing_context',\n 'wrong_unit',\n 'bad_grouping',\n 'missing_dataset_context',\n]\n\nexport interface PresentationFeedbackLabels {\n /** Resting-state question. */\n prompt: string\n /** Positive verdict button. */\n readable: string\n /** Negative verdict button — opens the detail step. */\n notReadable: string\n /** Heading of the detail step. */\n problemsPrompt: string\n /** Per-problem chip labels. */\n problemTooRaw: string\n problemWrongColumns: string\n problemWrongChart: string\n problemMissingContext: string\n problemWrongUnit: string\n problemBadGrouping: string\n problemMissingDatasetContext: string\n /** Heading of the optional layout picker. */\n preferLayoutPrompt: string\n /** Free-text comment placeholder. */\n commentPlaceholder: string\n /** Submit button of the detail step. */\n submit: string\n /** Acknowledgement shown after submission. */\n ack: string\n}\n\n/** English defaults. Override via the `labels` prop for other locales. */\nexport const DEFAULT_PRESENTATION_FEEDBACK_LABELS: PresentationFeedbackLabels = {\n prompt: 'Is this shown clearly?',\n readable: 'Clear',\n notReadable: 'Not clear',\n problemsPrompt: \"What's off?\",\n problemTooRaw: 'Too raw',\n problemWrongColumns: 'Wrong columns',\n problemWrongChart: 'Wrong chart',\n problemMissingContext: 'Missing context',\n problemWrongUnit: 'Wrong unit',\n problemBadGrouping: 'Bad grouping',\n problemMissingDatasetContext: 'Missing dataset context',\n preferLayoutPrompt: 'Better shown as',\n commentPlaceholder: 'Anything else? (optional)',\n submit: 'Send feedback',\n ack: 'Thanks — noted.',\n}\n\nconst PROBLEM_LABEL_KEY: Record<ConnectorRenderProblem, keyof PresentationFeedbackLabels> = {\n too_raw: 'problemTooRaw',\n wrong_columns: 'problemWrongColumns',\n wrong_chart: 'problemWrongChart',\n missing_context: 'problemMissingContext',\n wrong_unit: 'problemWrongUnit',\n bad_grouping: 'problemBadGrouping',\n missing_dataset_context: 'problemMissingDatasetContext',\n}\n\nexport interface PresentationFeedbackProps {\n /** Connector whose result is being rated. */\n connectorId: string\n /** Tool that produced the result. */\n toolName: string\n /** Stable key tying feedback to a `ConnectorDynamicResultV1.queryHash`. */\n queryHash?: string\n /** What is being rated (e.g. `'primary'`). Passed through to the payload. */\n renderKind?: string\n /** The layout type currently shown (e.g. `'table'`). Passed through. */\n layoutType?: string\n /**\n * Called once on submit with the assembled `ConnectorRenderFeedback`.\n * Persistence + any re-render are the host's responsibility.\n */\n onSubmit: (feedback: ConnectorRenderFeedback) => void | Promise<void>\n /**\n * Layout alternatives offered in the detail step. Omit (or pass an empty\n * array) to hide the layout picker entirely.\n */\n preferredLayoutOptions?: ConnectorPreferredLayout[]\n /** Partial label override (English defaults otherwise). */\n labels?: Partial<PresentationFeedbackLabels>\n /** Extra Tailwind classes on the container. */\n class?: string\n}\n\n/**\n * @experimental\n * Presentation-quality feedback widget (readable / not-readable + detail).\n */\nexport const PresentationFeedback: Component<PresentationFeedbackProps> = (props) => {\n const [step, setStep] = createSignal<'idle' | 'detail' | 'done'>('idle')\n const [problems, setProblems] = createSignal<Set<ConnectorRenderProblem>>(new Set())\n const [preferred, setPreferred] = createSignal<ConnectorPreferredLayout | undefined>(undefined)\n const [comment, setComment] = createSignal('')\n\n const label = (key: keyof PresentationFeedbackLabels): string =>\n props.labels?.[key] ?? DEFAULT_PRESENTATION_FEEDBACK_LABELS[key]\n\n const emit = (feedback: ConnectorRenderFeedback) => {\n try {\n // Fire-and-forget — feedback is best-effort, a rejection must not\n // break the UI (mirrors FeedbackInline).\n const result = props.onSubmit(feedback)\n if (result && typeof (result as Promise<void>).catch === 'function') {\n ;(result as Promise<void>).catch(() => {\n /* non-blocking */\n })\n }\n } catch {\n /* non-blocking */\n }\n setStep('done')\n }\n\n const base = (): Pick<\n ConnectorRenderFeedback,\n 'connectorId' | 'toolName' | 'queryHash' | 'renderKind' | 'layoutType'\n > => ({\n connectorId: props.connectorId,\n toolName: props.toolName,\n ...(props.queryHash ? { queryHash: props.queryHash } : {}),\n ...(props.renderKind ? { renderKind: props.renderKind } : {}),\n ...(props.layoutType ? { layoutType: props.layoutType } : {}),\n })\n\n const submitReadable = () => emit({ ...base(), verdict: 'readable' })\n\n const submitNotReadable = () => {\n const picked = [...problems()]\n const text = comment().trim()\n emit({\n ...base(),\n verdict: 'not_readable',\n ...(picked.length > 0 ? { problems: picked } : {}),\n ...(preferred() ? { preferredLayout: preferred() } : {}),\n ...(text ? { comment: text } : {}),\n })\n }\n\n const toggleProblem = (p: ConnectorRenderProblem) => {\n setProblems((prev) => {\n const next = new Set(prev)\n if (next.has(p)) next.delete(p)\n else next.add(p)\n return next\n })\n }\n\n return (\n <div\n class={`text-xs ${props.class ?? ''}`.trim()}\n data-presentation-feedback-step={step()}\n >\n {/* ── Step 1 : verdict ─────────────────────────────── */}\n <Show when={step() === 'idle'}>\n <div class=\"flex items-center gap-2\">\n <span class=\"text-deposium-slate-500\">{label('prompt')}</span>\n <button\n type=\"button\"\n onClick={submitReadable}\n class=\"px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-green-500 hover:text-green-600 transition-colors\"\n data-presentation-feedback-verdict=\"readable\"\n >\n {label('readable')}\n </button>\n <button\n type=\"button\"\n onClick={() => setStep('detail')}\n class=\"px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-amber-500 hover:text-amber-600 transition-colors\"\n data-presentation-feedback-verdict=\"not_readable\"\n >\n {label('notReadable')}\n </button>\n </div>\n </Show>\n\n {/* ── Step 2 : detail ──────────────────────────────── */}\n <Show when={step() === 'detail'}>\n <div class=\"flex flex-col gap-2 p-2 rounded-lg border border-gray-200 dark:border-gray-700\">\n <span class=\"font-medium text-deposium-slate-600 dark:text-gray-300\">\n {label('problemsPrompt')}\n </span>\n\n {/* Problem chips */}\n <div class=\"flex flex-wrap gap-1\">\n <For each={PROBLEM_ORDER}>\n {(p) => (\n <button\n type=\"button\"\n onClick={() => toggleProblem(p)}\n aria-pressed={problems().has(p)}\n data-presentation-feedback-problem={p}\n class={`px-2 py-0.5 rounded-full border transition-colors ${\n problems().has(p)\n ? 'border-amber-500 bg-amber-50 dark:bg-amber-900/30 text-amber-700 dark:text-amber-200'\n : 'border-gray-200 dark:border-gray-600 text-deposium-slate-500 hover:border-amber-400'\n }`}\n >\n {label(PROBLEM_LABEL_KEY[p])}\n </button>\n )}\n </For>\n </div>\n\n {/* Optional layout picker */}\n <Show when={(props.preferredLayoutOptions?.length ?? 0) > 0}>\n <div class=\"flex flex-wrap items-center gap-1\">\n <span class=\"text-deposium-slate-500\">{label('preferLayoutPrompt')}</span>\n <For each={props.preferredLayoutOptions}>\n {(opt) => (\n <button\n type=\"button\"\n onClick={() => setPreferred((cur) => (cur === opt ? undefined : opt))}\n aria-pressed={preferred() === opt}\n data-presentation-feedback-layout={opt}\n class={`px-2 py-0.5 rounded border transition-colors ${\n preferred() === opt\n ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-200'\n : 'border-gray-200 dark:border-gray-600 text-deposium-slate-500 hover:border-blue-400'\n }`}\n >\n {opt}\n </button>\n )}\n </For>\n </div>\n </Show>\n\n {/* Free-text comment */}\n <textarea\n value={comment()}\n onInput={(e) => setComment(e.currentTarget.value)}\n placeholder={label('commentPlaceholder')}\n rows={2}\n class=\"w-full rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 p-1.5 text-xs resize-y\"\n data-presentation-feedback-comment\n />\n\n <button\n type=\"button\"\n onClick={submitNotReadable}\n class=\"self-end px-3 py-1 rounded bg-amber-500 text-white font-medium hover:bg-amber-600 transition-colors\"\n data-presentation-feedback-submit\n >\n {label('submit')}\n </button>\n </div>\n </Show>\n\n {/* ── Step 3 : acknowledgement ─────────────────────── */}\n <Show when={step() === 'done'}>\n <span class=\"text-deposium-slate-500\" data-presentation-feedback-ack>\n {label('ack')}\n </span>\n </Show>\n </div>\n )\n}\n"],"names":["PROBLEM_ORDER","DEFAULT_PRESENTATION_FEEDBACK_LABELS","prompt","readable","notReadable","problemsPrompt","problemTooRaw","problemWrongColumns","problemWrongChart","problemMissingContext","problemWrongUnit","problemBadGrouping","problemMissingDatasetContext","preferLayoutPrompt","commentPlaceholder","submit","ack","PROBLEM_LABEL_KEY","too_raw","wrong_columns","wrong_chart","missing_context","wrong_unit","bad_grouping","missing_dataset_context","PresentationFeedback","props","step","setStep","createSignal","problems","setProblems","Set","preferred","setPreferred","undefined","comment","setComment","label","key","labels","emit","feedback","result","onSubmit","catch","base","connectorId","toolName","queryHash","renderKind","layoutType","submitReadable","verdict","submitNotReadable","picked","text","trim","length","preferredLayout","toggleProblem","p","prev","next","has","delete","add","_el$","_$getNextElement","_tmpl$5","_el$16","firstChild","_el$17","_co$3","_$getNextMarker","nextSibling","_el$18","_el$19","_co$4","_el$20","_el$21","_co$5","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","_el$4","_el$5","$$click","_$runHydrationEvents","_el$6","_tmpl$3","_el$7","_el$8","_el$13","_el$14","_co$2","_el$11","_el$12","For","each","_el$22","_tmpl$6","_$setAttribute","_$effect","_p$","_v$3","_v$4","e","t","_$className","preferredLayoutOptions","_el$9","_tmpl$2","_el$0","_el$1","_el$10","_co$","opt","_el$23","cur","_v$5","_v$6","$$input","currentTarget","value","_$setProperty","_el$15","_tmpl$4","_v$","class","_v$2","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PresentationFeedback.js","sources":["../../src/components/PresentationFeedback.tsx"],"sourcesContent":["/**\n * PresentationFeedback — feedback on how a connector result was *presented*.\n *\n * @experimental\n * @since v6.6.0 (R3 / D9 of ROADMAP-opendata-macro-mcpui)\n *\n * ## A separate axis from `FeedbackInline`\n *\n * MCP-UI has two distinct feedback widgets, kept separate on purpose\n * (cf. R3) :\n *\n * - **`FeedbackInline`** — was the *answer* good? (response quality)\n * - **`PresentationFeedback`** (this) — was the answer *shown well*?\n * (layout / readability)\n *\n * They are separate components, separate exports, separate payloads — so\n * the two axes never collapse into one in the UX or in the logs.\n *\n * ## Stateless — host owns persistence and re-render\n *\n * On submit the component calls `onSubmit(feedback)` with a\n * `ConnectorRenderFeedback` payload and flips to its acknowledgement state.\n * It does NOT persist anything and does NOT re-render the result itself\n * (cf. D1 : adapter pure + host-owned state). The host persists the\n * feedback and, if it wants to \"close the loop\", re-runs its adapter with\n * the corrected `preferredLayout`.\n *\n * Submission is best-effort : a rejected `onSubmit` promise is swallowed,\n * the UI still flips.\n *\n * ## Localization\n *\n * All labels ship in English and are overridable via the `labels` prop\n * (partial). This component carries its own label bag rather than routing\n * through `MCPUIStringsProvider` — its label set is large and specific to\n * this one widget.\n *\n * @example\n * ```tsx\n * <PresentationFeedback\n * connectorId=\"datagouv\"\n * toolName=\"datagouv.search\"\n * queryHash={result.queryHash}\n * layoutType=\"table\"\n * preferredLayoutOptions={['table', 'bar', 'map']}\n * onSubmit={(fb) => fetch('/api/render-feedback', {\n * method: 'POST', body: JSON.stringify(fb),\n * })}\n * />\n * ```\n */\n\nimport { Component, Show, For, createSignal } from 'solid-js'\nimport type {\n ConnectorRenderFeedback,\n ConnectorRenderProblem,\n ConnectorPreferredLayout,\n} from '@seed-ship/mcp-ui-spec'\n\n/** The full set of problem tags, in display order. */\nconst PROBLEM_ORDER: ConnectorRenderProblem[] = [\n 'too_raw',\n 'wrong_columns',\n 'wrong_chart',\n 'missing_context',\n 'wrong_unit',\n 'bad_grouping',\n 'missing_dataset_context',\n]\n\nexport interface PresentationFeedbackLabels {\n /** Resting-state question. */\n prompt: string\n /** Positive verdict button. */\n readable: string\n /** Negative verdict button — opens the detail step. */\n notReadable: string\n /** Heading of the detail step. */\n problemsPrompt: string\n /** Per-problem chip labels. */\n problemTooRaw: string\n problemWrongColumns: string\n problemWrongChart: string\n problemMissingContext: string\n problemWrongUnit: string\n problemBadGrouping: string\n problemMissingDatasetContext: string\n /** Heading of the optional layout picker. */\n preferLayoutPrompt: string\n /** Free-text comment placeholder. */\n commentPlaceholder: string\n /** Submit button of the detail step. */\n submit: string\n /** Acknowledgement shown after submission. */\n ack: string\n}\n\n/** English defaults. Override via the `labels` prop for other locales. */\nexport const DEFAULT_PRESENTATION_FEEDBACK_LABELS: PresentationFeedbackLabels = {\n prompt: 'Is this shown clearly?',\n readable: 'Clear',\n notReadable: 'Not clear',\n problemsPrompt: \"What's off?\",\n problemTooRaw: 'Too raw',\n problemWrongColumns: 'Wrong columns',\n problemWrongChart: 'Wrong chart',\n problemMissingContext: 'Missing context',\n problemWrongUnit: 'Wrong unit',\n problemBadGrouping: 'Bad grouping',\n problemMissingDatasetContext: 'Missing dataset context',\n preferLayoutPrompt: 'Better shown as',\n commentPlaceholder: 'Anything else? (optional)',\n submit: 'Send feedback',\n ack: 'Thanks — noted.',\n}\n\nconst PROBLEM_LABEL_KEY: Record<ConnectorRenderProblem, keyof PresentationFeedbackLabels> = {\n too_raw: 'problemTooRaw',\n wrong_columns: 'problemWrongColumns',\n wrong_chart: 'problemWrongChart',\n missing_context: 'problemMissingContext',\n wrong_unit: 'problemWrongUnit',\n bad_grouping: 'problemBadGrouping',\n missing_dataset_context: 'problemMissingDatasetContext',\n}\n\nexport interface PresentationFeedbackProps {\n /** Connector whose result is being rated. */\n connectorId: string\n /** Tool that produced the result. */\n toolName: string\n /** Stable key tying feedback to a `ConnectorDynamicResultV1.queryHash`. */\n queryHash?: string\n /** What is being rated (e.g. `'primary'`). Passed through to the payload. */\n renderKind?: string\n /** The layout type currently shown (e.g. `'table'`). Passed through. */\n layoutType?: string\n /**\n * Called once on submit with the assembled `ConnectorRenderFeedback`.\n * Persistence + any re-render are the host's responsibility.\n */\n onSubmit: (feedback: ConnectorRenderFeedback) => void | Promise<void>\n /**\n * Layout alternatives offered in the detail step. Omit (or pass an empty\n * array) to hide the layout picker entirely.\n */\n preferredLayoutOptions?: ConnectorPreferredLayout[]\n /** Partial label override (English defaults otherwise). */\n labels?: Partial<PresentationFeedbackLabels>\n /** Extra Tailwind classes on the container. */\n class?: string\n}\n\n/**\n * @experimental\n * Presentation-quality feedback widget (readable / not-readable + detail).\n */\nexport const PresentationFeedback: Component<PresentationFeedbackProps> = (props) => {\n const [step, setStep] = createSignal<'idle' | 'detail' | 'done'>('idle')\n const [problems, setProblems] = createSignal<Set<ConnectorRenderProblem>>(new Set())\n const [preferred, setPreferred] = createSignal<ConnectorPreferredLayout | undefined>(undefined)\n const [comment, setComment] = createSignal('')\n\n const label = (key: keyof PresentationFeedbackLabels): string =>\n props.labels?.[key] ?? DEFAULT_PRESENTATION_FEEDBACK_LABELS[key]\n\n const emit = (feedback: ConnectorRenderFeedback) => {\n try {\n // Fire-and-forget — feedback is best-effort, a rejection must not\n // break the UI (mirrors FeedbackInline).\n const result = props.onSubmit(feedback)\n if (result && typeof (result as Promise<void>).catch === 'function') {\n (result as Promise<void>).catch(() => {\n /* non-blocking */\n })\n }\n } catch {\n /* non-blocking */\n }\n setStep('done')\n }\n\n const base = (): Pick<\n ConnectorRenderFeedback,\n 'connectorId' | 'toolName' | 'queryHash' | 'renderKind' | 'layoutType'\n > => ({\n connectorId: props.connectorId,\n toolName: props.toolName,\n ...(props.queryHash ? { queryHash: props.queryHash } : {}),\n ...(props.renderKind ? { renderKind: props.renderKind } : {}),\n ...(props.layoutType ? { layoutType: props.layoutType } : {}),\n })\n\n const submitReadable = () => emit({ ...base(), verdict: 'readable' })\n\n const submitNotReadable = () => {\n const picked = [...problems()]\n const text = comment().trim()\n emit({\n ...base(),\n verdict: 'not_readable',\n ...(picked.length > 0 ? { problems: picked } : {}),\n ...(preferred() ? { preferredLayout: preferred() } : {}),\n ...(text ? { comment: text } : {}),\n })\n }\n\n const toggleProblem = (p: ConnectorRenderProblem) => {\n setProblems((prev) => {\n const next = new Set(prev)\n if (next.has(p)) next.delete(p)\n else next.add(p)\n return next\n })\n }\n\n return (\n <div\n class={`text-xs ${props.class ?? ''}`.trim()}\n data-presentation-feedback-step={step()}\n >\n {/* ── Step 1 : verdict ─────────────────────────────── */}\n <Show when={step() === 'idle'}>\n <div class=\"flex items-center gap-2\">\n <span class=\"text-deposium-slate-500\">{label('prompt')}</span>\n <button\n type=\"button\"\n onClick={submitReadable}\n class=\"px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-green-500 hover:text-green-600 transition-colors\"\n data-presentation-feedback-verdict=\"readable\"\n >\n {label('readable')}\n </button>\n <button\n type=\"button\"\n onClick={() => setStep('detail')}\n class=\"px-2 py-0.5 rounded border border-gray-200 dark:border-gray-600 text-deposium-slate-600 dark:text-gray-300 hover:border-amber-500 hover:text-amber-600 transition-colors\"\n data-presentation-feedback-verdict=\"not_readable\"\n >\n {label('notReadable')}\n </button>\n </div>\n </Show>\n\n {/* ── Step 2 : detail ──────────────────────────────── */}\n <Show when={step() === 'detail'}>\n <div class=\"flex flex-col gap-2 p-2 rounded-lg border border-gray-200 dark:border-gray-700\">\n <span class=\"font-medium text-deposium-slate-600 dark:text-gray-300\">\n {label('problemsPrompt')}\n </span>\n\n {/* Problem chips */}\n <div class=\"flex flex-wrap gap-1\">\n <For each={PROBLEM_ORDER}>\n {(p) => (\n <button\n type=\"button\"\n onClick={() => toggleProblem(p)}\n aria-pressed={problems().has(p)}\n data-presentation-feedback-problem={p}\n class={`px-2 py-0.5 rounded-full border transition-colors ${\n problems().has(p)\n ? 'border-amber-500 bg-amber-50 dark:bg-amber-900/30 text-amber-700 dark:text-amber-200'\n : 'border-gray-200 dark:border-gray-600 text-deposium-slate-500 hover:border-amber-400'\n }`}\n >\n {label(PROBLEM_LABEL_KEY[p])}\n </button>\n )}\n </For>\n </div>\n\n {/* Optional layout picker */}\n <Show when={(props.preferredLayoutOptions?.length ?? 0) > 0}>\n <div class=\"flex flex-wrap items-center gap-1\">\n <span class=\"text-deposium-slate-500\">{label('preferLayoutPrompt')}</span>\n <For each={props.preferredLayoutOptions}>\n {(opt) => (\n <button\n type=\"button\"\n onClick={() => setPreferred((cur) => (cur === opt ? undefined : opt))}\n aria-pressed={preferred() === opt}\n data-presentation-feedback-layout={opt}\n class={`px-2 py-0.5 rounded border transition-colors ${\n preferred() === opt\n ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-200'\n : 'border-gray-200 dark:border-gray-600 text-deposium-slate-500 hover:border-blue-400'\n }`}\n >\n {opt}\n </button>\n )}\n </For>\n </div>\n </Show>\n\n {/* Free-text comment */}\n <textarea\n value={comment()}\n onInput={(e) => setComment(e.currentTarget.value)}\n placeholder={label('commentPlaceholder')}\n rows={2}\n class=\"w-full rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 p-1.5 text-xs resize-y\"\n data-presentation-feedback-comment\n />\n\n <button\n type=\"button\"\n onClick={submitNotReadable}\n class=\"self-end px-3 py-1 rounded bg-amber-500 text-white font-medium hover:bg-amber-600 transition-colors\"\n data-presentation-feedback-submit\n >\n {label('submit')}\n </button>\n </div>\n </Show>\n\n {/* ── Step 3 : acknowledgement ─────────────────────── */}\n <Show when={step() === 'done'}>\n <span class=\"text-deposium-slate-500\" data-presentation-feedback-ack>\n {label('ack')}\n </span>\n </Show>\n </div>\n )\n}\n"],"names":["PROBLEM_ORDER","DEFAULT_PRESENTATION_FEEDBACK_LABELS","prompt","readable","notReadable","problemsPrompt","problemTooRaw","problemWrongColumns","problemWrongChart","problemMissingContext","problemWrongUnit","problemBadGrouping","problemMissingDatasetContext","preferLayoutPrompt","commentPlaceholder","submit","ack","PROBLEM_LABEL_KEY","too_raw","wrong_columns","wrong_chart","missing_context","wrong_unit","bad_grouping","missing_dataset_context","PresentationFeedback","props","step","setStep","createSignal","problems","setProblems","Set","preferred","setPreferred","undefined","comment","setComment","label","key","labels","emit","feedback","result","onSubmit","catch","base","connectorId","toolName","queryHash","renderKind","layoutType","submitReadable","verdict","submitNotReadable","picked","text","trim","length","preferredLayout","toggleProblem","p","prev","next","has","delete","add","_el$","_$getNextElement","_tmpl$5","_el$16","firstChild","_el$17","_co$3","_$getNextMarker","nextSibling","_el$18","_el$19","_co$4","_el$20","_el$21","_co$5","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","_el$4","_el$5","$$click","_$runHydrationEvents","_el$6","_tmpl$3","_el$7","_el$8","_el$13","_el$14","_co$2","_el$11","_el$12","For","each","_el$22","_tmpl$6","_$setAttribute","_$effect","_p$","_v$3","_v$4","e","t","_$className","preferredLayoutOptions","_el$9","_tmpl$2","_el$0","_el$1","_el$10","_co$","opt","_el$23","cur","_v$5","_v$6","$$input","currentTarget","value","_$setProperty","_el$15","_tmpl$4","_v$","class","_v$2","_$delegateEvents"],"mappings":"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"}
|
|
@@ -29,8 +29,9 @@ const ExpandableWrapper = require("./ExpandableWrapper.cjs");
|
|
|
29
29
|
const PortalDropdownMenu = require("./PortalDropdownMenu.cjs");
|
|
30
30
|
const RenderContext = require("./RenderContext.cjs");
|
|
31
31
|
const useAction = require("../hooks/useAction.cjs");
|
|
32
|
+
const createResponsiveGrid = require("../hooks/createResponsiveGrid.cjs");
|
|
32
33
|
const marked_esm = require("../node_modules/.pnpm/marked@16.4.2/node_modules/marked/lib/marked.esm.cjs");
|
|
33
|
-
var _tmpl$ = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 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="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>`), _tmpl$3 = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 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">`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class="p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><p class="text-red-500 dark:text-red-400 text-sm">Invalid chart data: missing data.datasets`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class=p-3>`), _tmpl$6 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600">`), _tmpl$7 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center p-4"><div class=text-center><p class="text-red-600 dark:text-red-400 text-sm font-medium">Chart Error</p><p class="text-gray-600 dark:text-gray-400 text-xs mt-1">`), _tmpl$8 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3">`), _tmpl$9 = /* @__PURE__ */ web.template(`<div class="w-full h-full p-4"><!$><!/><div class="w-full h-full"role=img><img class="w-full h-auto max-h-[300px] object-contain">`), _tmpl$0 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full min-h-[300px] bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$1 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">`), _tmpl$10 = /* @__PURE__ */ web.template(`<tr>`), _tmpl$11 = /* @__PURE__ */ web.template(`<td class="px-6 py-4 text-sm text-gray-700 dark:text-gray-200 whitespace-normal break-words leading-relaxed first:pl-6 last:pr-6"><div>`), _tmpl$12 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 relative">`), _tmpl$13 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Copy TSV`), _tmpl$14 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Download CSV`), _tmpl$15 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Download JSON`), _tmpl$16 = /* @__PURE__ */ web.template(`<div class="absolute right-10 top-2 z-10"><button class="opacity-60 hover:opacity-100 px-2 py-1 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"title="Export table"aria-label="Export table"aria-haspopup=menu><svg class="w-3 h-3 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="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path></svg></button><!$><!/>`), _tmpl$17 = /* @__PURE__ */ web.template(`<span class="ml-2 text-xs font-normal text-gray-400">(virtualized: <!$><!/> rows)`), _tmpl$18 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3 flex-shrink-0"><!$><!/><!$><!/>`), _tmpl$19 = /* @__PURE__ */ web.template(`<button type=button class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-sm"aria-label="Clear search">×`), _tmpl$20 = /* @__PURE__ */ web.template(`<div class="relative mb-3"><span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none text-sm">🔍</span><input type=text class="w-full max-w-xs min-w-[200px] pl-8 pr-8 py-1.5 text-sm border border-gray-200 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:border-blue-400 focus:ring-1 focus:ring-blue-400 outline-none"><!$><!/>`), _tmpl$21 = /* @__PURE__ */ web.template(`<p class="text-xs text-gray-500 dark:text-gray-400 mb-2"><!$><!/> result<!$><!/> on <!$><!/>`), _tmpl$22 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!$><!/> - <!$><!/> of <!$><!/>`), _tmpl$23 = /* @__PURE__ */ web.template(`<select class="ml-2 px-1 py-0.5 text-xs border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300">`), _tmpl$24 = /* @__PURE__ */ web.template(`<span class=text-gray-400>/ page`), _tmpl$25 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span><!$><!/>–<!$><!/> / <!$><!/></span><div class="flex items-center gap-2"><button class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors">◀</button><span><!$><!/> / <!$><!/></span><button class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors">▶</button><!$><!/>`), _tmpl$26 = /* @__PURE__ */ web.template(`<div><!$><!/><div><!$><!/><!$><!/><div role=region tabindex=0><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border-separate border-spacing-0"><thead class="bg-gray-100 dark:bg-gray-900 sticky top-0 z-10"><tr></tr></thead><!$><!/></table></div><!$><!/><!$><!/>`), _tmpl$27 = /* @__PURE__ */ web.template(`<th scope=col class="px-6 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700 first:pl-6 last:pr-6 bg-gray-100 dark:bg-gray-900 cursor-pointer select-none hover:bg-gray-200 dark:hover:bg-gray-800 transition-colors"><span class="inline-flex items-center gap-1"><!$><!/><span class="text-[10px] leading-none">`), _tmpl$28 = /* @__PURE__ */ web.template(`<option>`), _tmpl$29 = /* @__PURE__ */ web.template(`<span class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">`), _tmpl$30 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center"><span><!$><!/> <!$><!/>%`), _tmpl$31 = /* @__PURE__ */ web.template(`<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">`), _tmpl$32 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div class="flex flex-col h-full justify-between"><div><p class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide"></p><div class="mt-2 flex items-baseline"><p class="text-2xl font-semibold text-gray-900 dark:text-white"></p><!$><!/></div></div><!$><!/><!$><!/>`), _tmpl$33 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div>`), _tmpl$34 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class=cursor-zoom-in><img class="max-w-full max-h-[400px] object-contain rounded shadow-sm hover:opacity-90 transition-opacity"loading=lazy></a></div><div class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center italic">`, true, false, false), _tmpl$35 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$36 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><!$><!/><iframe class="w-full border-0 flex-1"loading=lazy>`, true, false, false), _tmpl$37 = /* @__PURE__ */ web.template(`<figcaption class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center">`), _tmpl$38 = /* @__PURE__ */ web.template(`<figure><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class="cursor-zoom-in focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded"><img class="max-w-full max-h-[500px] object-contain rounded shadow-sm hover:opacity-95 transition-opacity"loading=lazy></a></div><!$><!/>`, true, false, false), _tmpl$39 = /* @__PURE__ */ web.template(`<p class="text-xs text-gray-500 dark:text-gray-400 truncate">`), _tmpl$40 = /* @__PURE__ */ web.template(`<a target=_blank rel="noopener noreferrer"><div class="p-2 bg-blue-50 dark:bg-blue-900/30 rounded-full text-blue-600 dark:text-blue-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/50 shrink-0 transition-colors"aria-hidden=true><svg xmlns=http://www.w3.org/2000/svg class="w-5 h-5"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-medium text-gray-900 dark:text-white truncate group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"></h4><!$><!/></div><svg xmlns=http://www.w3.org/2000/svg class="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 shrink-0 transition-colors"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1=10 y1=14 x2=21 y2=3>`), _tmpl$41 = /* @__PURE__ */ web.template(`<div class="inline-flex items-center gap-1.5 px-2 py-1 rounded-md bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 text-xs text-yellow-800 dark:text-yellow-200"role=alert aria-label="Component validation warning"><svg xmlns=http://www.w3.org/2000/svg class="w-3.5 h-3.5"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1=12 y1=9 x2=12 y2=13></line><line x1=12 y1=17 x2=12.01 y2=17></line></svg><span>Invalid <!$><!/>`), _tmpl$42 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4"><p class="text-sm font-medium text-red-900 dark:text-red-100">Validation Error</p><p class="text-xs text-red-700 dark:text-red-300 mt-1">`), _tmpl$43 = /* @__PURE__ */ web.template(`<div role=alert class="w-full rounded-lg border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200">Unsupported component type: <code class=font-mono>`), _tmpl$44 = /* @__PURE__ */ web.template(`<span aria-hidden=true>`), _tmpl$45 = /* @__PURE__ */ web.template(`<a rel="noopener noreferrer"><!$><!/><!$><!/>`), _tmpl$46 = /* @__PURE__ */ web.template(`<span class="animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full"aria-hidden=true>`), _tmpl$47 = /* @__PURE__ */ web.template(`<button type=button><!$><!/><!$><!/><!$><!/>`), _tmpl$48 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-600 dark:text-red-400 mt-1">Type: <!$><!/>`), _tmpl$49 = /* @__PURE__ */ web.template(`<div class=mt-3><p class="text-xs font-medium text-red-700 dark:text-red-300">Suggestions:</p><ul class="mt-1 text-xs text-red-600 dark:text-red-400 list-disc list-inside">`), _tmpl$50 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-500 dark:text-red-500 mt-2">`), _tmpl$51 = /* @__PURE__ */ web.template(`<div class="relative w-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 group"><!$><!/><div class="flex items-start gap-3"><div class="p-2 bg-red-100 dark:bg-red-900/40 rounded-full shrink-0"><svg class="w-5 h-5 text-red-600 dark:text-red-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-semibold text-red-800 dark:text-red-200">Tool Error: <!$><!/></h4><p class="text-sm text-red-700 dark:text-red-300 mt-1"></p><!$><!/><!$><!/><!$><!/>`), _tmpl$52 = /* @__PURE__ */ web.template(`<li>`), _tmpl$53 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white capitalize">`), _tmpl$54 = /* @__PURE__ */ web.template(`<div class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><div class="p-4 prose prose-sm dark:prose-invert max-w-none">`), _tmpl$55 = /* @__PURE__ */ web.template(`<div><div class="grid gap-4"></div><!$><!/>`), _tmpl$56 = /* @__PURE__ */ web.template(`<div>`);
|
|
34
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 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="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>`), _tmpl$3 = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 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">`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class="p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><p class="text-red-500 dark:text-red-400 text-sm">Invalid chart data: missing data.datasets`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class=p-3>`), _tmpl$6 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600">`), _tmpl$7 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center p-4"><div class=text-center><p class="text-red-600 dark:text-red-400 text-sm font-medium">Chart Error</p><p class="text-gray-600 dark:text-gray-400 text-xs mt-1">`), _tmpl$8 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3">`), _tmpl$9 = /* @__PURE__ */ web.template(`<div class="w-full h-full p-4"><!$><!/><div class="w-full h-full"role=img><img class="w-full h-auto max-h-[300px] object-contain">`), _tmpl$0 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full min-h-[300px] bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$1 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">`), _tmpl$10 = /* @__PURE__ */ web.template(`<tr>`), _tmpl$11 = /* @__PURE__ */ web.template(`<td class="px-6 py-4 text-sm text-gray-700 dark:text-gray-200 whitespace-normal break-words leading-relaxed first:pl-6 last:pr-6"><div>`), _tmpl$12 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 relative">`), _tmpl$13 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Copy TSV`), _tmpl$14 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Download CSV`), _tmpl$15 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Download JSON`), _tmpl$16 = /* @__PURE__ */ web.template(`<div class="absolute right-10 top-2 z-10"><button class="opacity-60 hover:opacity-100 px-2 py-1 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"title="Export table"aria-label="Export table"aria-haspopup=menu><svg class="w-3 h-3 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="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path></svg></button><!$><!/>`), _tmpl$17 = /* @__PURE__ */ web.template(`<span class="ml-2 text-xs font-normal text-gray-400">(virtualized: <!$><!/> rows)`), _tmpl$18 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3 flex-shrink-0"><!$><!/><!$><!/>`), _tmpl$19 = /* @__PURE__ */ web.template(`<button type=button class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-sm"aria-label="Clear search">×`), _tmpl$20 = /* @__PURE__ */ web.template(`<div class="relative mb-3"><span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none text-sm">🔍</span><input type=text class="w-full max-w-xs min-w-[200px] pl-8 pr-8 py-1.5 text-sm border border-gray-200 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:border-blue-400 focus:ring-1 focus:ring-blue-400 outline-none"><!$><!/>`), _tmpl$21 = /* @__PURE__ */ web.template(`<p class="text-xs text-gray-500 dark:text-gray-400 mb-2"><!$><!/> result<!$><!/> on <!$><!/>`), _tmpl$22 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!$><!/> - <!$><!/> of <!$><!/>`), _tmpl$23 = /* @__PURE__ */ web.template(`<select class="ml-2 px-1 py-0.5 text-xs border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300">`), _tmpl$24 = /* @__PURE__ */ web.template(`<span class=text-gray-400>/ page`), _tmpl$25 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span><!$><!/>–<!$><!/> / <!$><!/></span><div class="flex items-center gap-2"><button class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors">◀</button><span><!$><!/> / <!$><!/></span><button class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors">▶</button><!$><!/>`), _tmpl$26 = /* @__PURE__ */ web.template(`<div><!$><!/><div><!$><!/><!$><!/><div role=region tabindex=0><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border-separate border-spacing-0"><thead class="bg-gray-100 dark:bg-gray-900 sticky top-0 z-10"><tr></tr></thead><!$><!/></table></div><!$><!/><!$><!/>`), _tmpl$27 = /* @__PURE__ */ web.template(`<th scope=col class="px-6 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700 first:pl-6 last:pr-6 bg-gray-100 dark:bg-gray-900 cursor-pointer select-none hover:bg-gray-200 dark:hover:bg-gray-800 transition-colors"><span class="inline-flex items-center gap-1"><!$><!/><span class="text-[10px] leading-none">`), _tmpl$28 = /* @__PURE__ */ web.template(`<option>`), _tmpl$29 = /* @__PURE__ */ web.template(`<span class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">`), _tmpl$30 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center"><span><!$><!/> <!$><!/>%`), _tmpl$31 = /* @__PURE__ */ web.template(`<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">`), _tmpl$32 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div class="flex flex-col h-full justify-between"><div><p class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide"></p><div class="mt-2 flex items-baseline"><p class="text-2xl font-semibold text-gray-900 dark:text-white"></p><!$><!/></div></div><!$><!/><!$><!/>`), _tmpl$33 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div>`), _tmpl$34 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class=cursor-zoom-in><img class="max-w-full max-h-[400px] object-contain rounded shadow-sm hover:opacity-90 transition-opacity"loading=lazy></a></div><div class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center italic">`, true, false, false), _tmpl$35 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$36 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><!$><!/><iframe class="w-full border-0 flex-1"loading=lazy>`, true, false, false), _tmpl$37 = /* @__PURE__ */ web.template(`<figcaption class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center">`), _tmpl$38 = /* @__PURE__ */ web.template(`<figure><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class="cursor-zoom-in focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded"><img class="max-w-full max-h-[500px] object-contain rounded shadow-sm hover:opacity-95 transition-opacity"loading=lazy></a></div><!$><!/>`, true, false, false), _tmpl$39 = /* @__PURE__ */ web.template(`<p class="text-xs text-gray-500 dark:text-gray-400 truncate">`), _tmpl$40 = /* @__PURE__ */ web.template(`<a target=_blank rel="noopener noreferrer"><div class="p-2 bg-blue-50 dark:bg-blue-900/30 rounded-full text-blue-600 dark:text-blue-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/50 shrink-0 transition-colors"aria-hidden=true><svg xmlns=http://www.w3.org/2000/svg class="w-5 h-5"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-medium text-gray-900 dark:text-white truncate group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"></h4><!$><!/></div><svg xmlns=http://www.w3.org/2000/svg class="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 shrink-0 transition-colors"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1=10 y1=14 x2=21 y2=3>`), _tmpl$41 = /* @__PURE__ */ web.template(`<div class="inline-flex items-center gap-1.5 px-2 py-1 rounded-md bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 text-xs text-yellow-800 dark:text-yellow-200"role=alert aria-label="Component validation warning"><svg xmlns=http://www.w3.org/2000/svg class="w-3.5 h-3.5"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1=12 y1=9 x2=12 y2=13></line><line x1=12 y1=17 x2=12.01 y2=17></line></svg><span>Invalid <!$><!/>`), _tmpl$42 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4"><p class="text-sm font-medium text-red-900 dark:text-red-100">Validation Error</p><p class="text-xs text-red-700 dark:text-red-300 mt-1">`), _tmpl$43 = /* @__PURE__ */ web.template(`<div role=alert class="w-full rounded-lg border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200">Unsupported component type: <code class=font-mono>`), _tmpl$44 = /* @__PURE__ */ web.template(`<span aria-hidden=true>`), _tmpl$45 = /* @__PURE__ */ web.template(`<a rel="noopener noreferrer"><!$><!/><!$><!/>`), _tmpl$46 = /* @__PURE__ */ web.template(`<span class="animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full"aria-hidden=true>`), _tmpl$47 = /* @__PURE__ */ web.template(`<button type=button><!$><!/><!$><!/><!$><!/>`), _tmpl$48 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-600 dark:text-red-400 mt-1">Type: <!$><!/>`), _tmpl$49 = /* @__PURE__ */ web.template(`<div class=mt-3><p class="text-xs font-medium text-red-700 dark:text-red-300">Suggestions:</p><ul class="mt-1 text-xs text-red-600 dark:text-red-400 list-disc list-inside">`), _tmpl$50 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-500 dark:text-red-500 mt-2">`), _tmpl$51 = /* @__PURE__ */ web.template(`<div class="relative w-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 group"><!$><!/><div class="flex items-start gap-3"><div class="p-2 bg-red-100 dark:bg-red-900/40 rounded-full shrink-0"><svg class="w-5 h-5 text-red-600 dark:text-red-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-semibold text-red-800 dark:text-red-200">Tool Error: <!$><!/></h4><p class="text-sm text-red-700 dark:text-red-300 mt-1"></p><!$><!/><!$><!/><!$><!/>`), _tmpl$52 = /* @__PURE__ */ web.template(`<li>`), _tmpl$53 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white capitalize">`), _tmpl$54 = /* @__PURE__ */ web.template(`<div class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><div class="p-4 prose prose-sm dark:prose-invert max-w-none">`), _tmpl$55 = /* @__PURE__ */ web.template(`<div><div class="grid gap-4"data-mcp-ui-grid></div><!$><!/>`), _tmpl$56 = /* @__PURE__ */ web.template(`<div class=min-w-0>`);
|
|
34
35
|
function CopyButton(props) {
|
|
35
36
|
const [copied, setCopied] = solidJs.createSignal(false);
|
|
36
37
|
const handleCopy = async () => {
|
|
@@ -434,8 +435,12 @@ function TableRenderer(props) {
|
|
|
434
435
|
const showAll = () => userPageSize() === 0;
|
|
435
436
|
const hasServerPagination = () => !!tableParams.pagination;
|
|
436
437
|
const needsClientPagination = () => !hasServerPagination() && !showAll() && clientPageSize() > 0 && filteredRows().length > clientPageSize();
|
|
437
|
-
const [
|
|
438
|
+
const [requestedClientPage, setClientPage] = solidJs.createSignal(tableParams.initialPage ?? 0);
|
|
438
439
|
const clientTotalPages = () => needsClientPagination() ? Math.ceil(filteredRows().length / clientPageSize()) : 1;
|
|
440
|
+
const clientPage = solidJs.createMemo(() => Math.max(0, Math.min(requestedClientPage(), clientTotalPages() - 1)));
|
|
441
|
+
solidJs.createEffect(() => {
|
|
442
|
+
if (requestedClientPage() !== clientPage()) setClientPage(clientPage());
|
|
443
|
+
});
|
|
439
444
|
const clientVisibleRows = solidJs.createMemo(() => {
|
|
440
445
|
if (showAll() || !needsClientPagination()) return filteredRows();
|
|
441
446
|
const start = clientPage() * clientPageSize();
|
|
@@ -890,7 +895,7 @@ ${dataRows}`;
|
|
|
890
895
|
}
|
|
891
896
|
}), _el$115, _co$25);
|
|
892
897
|
web.effect((_p$) => {
|
|
893
|
-
var _v$0 = `relative w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden group ${isExpanded() ? "flex-1 min-h-0 flex flex-col" : "h-full"}`, _v$1 = `p-4 ${isExpanded() ? "flex-1 min-h-0 flex flex-col" : ""}`, _v$10 = `overflow-x-auto ${isExpanded() ? "flex-1 min-h-0" : ""}`, _v$11 = (
|
|
898
|
+
var _v$0 = `relative w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden group ${isExpanded() ? "flex-1 min-h-0 flex flex-col" : "h-full"} ${tableParams.className || ""}`, _v$1 = `p-4 ${isExpanded() ? "flex-1 min-h-0 flex flex-col" : ""}`, _v$10 = `overflow-x-auto ${isExpanded() ? "flex-1 min-h-0" : ""}`, _v$11 = (
|
|
894
899
|
// v6.1.0 — when expanded, the scroll container fills the
|
|
895
900
|
// remaining vertical space and scrolls internally.
|
|
896
901
|
// v6.3.0 — `params.maxHeight` opt-out (axe 1 deposium handoff)
|
|
@@ -1772,13 +1777,14 @@ const UIResourceRenderer = (props) => {
|
|
|
1772
1777
|
}
|
|
1773
1778
|
return props.content;
|
|
1774
1779
|
};
|
|
1780
|
+
const responsiveGrid = createResponsiveGrid.createResponsiveGrid();
|
|
1775
1781
|
const gridContainerStyle = () => {
|
|
1776
|
-
const
|
|
1777
|
-
return `grid-template-columns: repeat(${
|
|
1782
|
+
const layoutData = layout();
|
|
1783
|
+
return `display: grid; grid-template-columns: repeat(${responsiveGrid.stacked() ? 1 : layoutData.grid.columns}, minmax(0, 1fr)); gap: ${layoutData.grid.gap}`;
|
|
1778
1784
|
};
|
|
1779
1785
|
const getGridStyleString = (component) => {
|
|
1780
|
-
if (!component.position) {
|
|
1781
|
-
return "grid-column: 1 /
|
|
1786
|
+
if (responsiveGrid.stacked() || !component.position) {
|
|
1787
|
+
return "grid-column: 1 / -1; grid-row: auto";
|
|
1782
1788
|
}
|
|
1783
1789
|
const {
|
|
1784
1790
|
colStart,
|
|
@@ -1790,30 +1796,29 @@ const UIResourceRenderer = (props) => {
|
|
|
1790
1796
|
};
|
|
1791
1797
|
const shouldShowAutoFooter = solidJs.createMemo(() => {
|
|
1792
1798
|
var _a;
|
|
1793
|
-
const
|
|
1794
|
-
if ((_a =
|
|
1799
|
+
const layoutData = layout();
|
|
1800
|
+
if ((_a = layoutData.metadata) == null ? void 0 : _a.hideFooter) {
|
|
1795
1801
|
return false;
|
|
1796
1802
|
}
|
|
1797
|
-
if (!
|
|
1803
|
+
if (!layoutData.metadata) {
|
|
1798
1804
|
return false;
|
|
1799
1805
|
}
|
|
1800
|
-
const hasExplicitFooter =
|
|
1806
|
+
const hasExplicitFooter = layoutData.components.some((c) => c.type === "footer");
|
|
1801
1807
|
if (hasExplicitFooter) {
|
|
1802
1808
|
return false;
|
|
1803
1809
|
}
|
|
1804
|
-
return !!(
|
|
1810
|
+
return !!(layoutData.metadata.executionTime || layoutData.metadata.sourceCount || layoutData.metadata.llmModel);
|
|
1805
1811
|
});
|
|
1806
1812
|
const autoFooterParams = solidJs.createMemo(() => {
|
|
1807
1813
|
var _a, _b, _c;
|
|
1808
|
-
const
|
|
1814
|
+
const layoutData = layout();
|
|
1809
1815
|
return {
|
|
1810
1816
|
poweredBy: "Deposium",
|
|
1811
|
-
executionTime: (_a =
|
|
1812
|
-
model: (_b =
|
|
1813
|
-
sourceCount: (_c =
|
|
1817
|
+
executionTime: (_a = layoutData.metadata) == null ? void 0 : _a.executionTime,
|
|
1818
|
+
model: (_b = layoutData.metadata) == null ? void 0 : _b.llmModel,
|
|
1819
|
+
sourceCount: (_c = layoutData.metadata) == null ? void 0 : _c.sourceCount
|
|
1814
1820
|
};
|
|
1815
1821
|
});
|
|
1816
|
-
const layoutData = layout();
|
|
1817
1822
|
const isLayoutContent = !("type" in props.content) || props.content.type === "composite";
|
|
1818
1823
|
const outerKey = solidJs.createMemo(() => stableKey.getUiResourceStableKey(props.content));
|
|
1819
1824
|
solidJs.onMount(() => {
|
|
@@ -1857,9 +1862,11 @@ const UIResourceRenderer = (props) => {
|
|
|
1857
1862
|
} : {
|
|
1858
1863
|
"data-mcp-ui-component-id": outerKey()
|
|
1859
1864
|
}), false, true);
|
|
1865
|
+
var _ref$3 = responsiveGrid.ref;
|
|
1866
|
+
typeof _ref$3 === "function" ? web.use(_ref$3, _el$239) : responsiveGrid.ref = _el$239;
|
|
1860
1867
|
web.insert(_el$239, web.createComponent(solidJs.For, {
|
|
1861
1868
|
get each() {
|
|
1862
|
-
return
|
|
1869
|
+
return layout().components;
|
|
1863
1870
|
},
|
|
1864
1871
|
children: (component) => (() => {
|
|
1865
1872
|
var _el$242 = web.getNextElement(_tmpl$56);
|
|
@@ -1879,9 +1886,9 @@ const UIResourceRenderer = (props) => {
|
|
|
1879
1886
|
}
|
|
1880
1887
|
}));
|
|
1881
1888
|
web.effect((_p$) => {
|
|
1882
|
-
var _v$
|
|
1883
|
-
_p$.e = web.style(_el$242, _v$
|
|
1884
|
-
_v$
|
|
1889
|
+
var _v$44 = getGridStyleString(component), _v$45 = stableKey.getUiResourceStableKey(component);
|
|
1890
|
+
_p$.e = web.style(_el$242, _v$44, _p$.e);
|
|
1891
|
+
_v$45 !== _p$.t && web.setAttribute(_el$242, "data-mcp-ui-component-id", _p$.t = _v$45);
|
|
1885
1892
|
return _p$;
|
|
1886
1893
|
}, {
|
|
1887
1894
|
e: void 0,
|
|
@@ -1902,7 +1909,15 @@ const UIResourceRenderer = (props) => {
|
|
|
1902
1909
|
});
|
|
1903
1910
|
}
|
|
1904
1911
|
}), _el$241, _co$51);
|
|
1905
|
-
web.effect((
|
|
1912
|
+
web.effect((_p$) => {
|
|
1913
|
+
var _v$42 = gridContainerStyle(), _v$43 = responsiveGrid.stacked();
|
|
1914
|
+
_p$.e = web.style(_el$239, _v$42, _p$.e);
|
|
1915
|
+
_v$43 !== _p$.t && web.setAttribute(_el$239, "data-mcp-ui-stacked", _p$.t = _v$43);
|
|
1916
|
+
return _p$;
|
|
1917
|
+
}, {
|
|
1918
|
+
e: void 0,
|
|
1919
|
+
t: void 0
|
|
1920
|
+
});
|
|
1906
1921
|
web.runHydrationEvents();
|
|
1907
1922
|
return _el$238;
|
|
1908
1923
|
}
|