@miragon/mcp-toolkit-ui 2.6.0 → 2.8.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/README.md +14 -5
- package/dist/app/adapt-data-widget.d.ts +1 -22
- package/dist/app/adapt-data-widget.d.ts.map +1 -1
- package/dist/app/adapt-data-widget.js +1 -35
- package/dist/app/adapt-data-widget.js.map +1 -1
- package/dist/app/builder/BuilderBanners.d.ts +7 -2
- package/dist/app/builder/BuilderBanners.d.ts.map +1 -1
- package/dist/app/builder/BuilderBanners.js +8 -3
- package/dist/app/builder/BuilderBanners.js.map +1 -1
- package/dist/app/builder/CanvasRow.d.ts +4 -2
- package/dist/app/builder/CanvasRow.d.ts.map +1 -1
- package/dist/app/builder/CanvasRow.js +29 -17
- package/dist/app/builder/CanvasRow.js.map +1 -1
- package/dist/app/builder/CatalogueSheet.d.ts.map +1 -1
- package/dist/app/builder/CatalogueSheet.js +14 -6
- package/dist/app/builder/CatalogueSheet.js.map +1 -1
- package/dist/app/builder/CellPropsSheet.d.ts +7 -3
- package/dist/app/builder/CellPropsSheet.d.ts.map +1 -1
- package/dist/app/builder/CellPropsSheet.js +10 -3
- package/dist/app/builder/CellPropsSheet.js.map +1 -1
- package/dist/app/builder/DiscardDialog.d.ts +18 -0
- package/dist/app/builder/DiscardDialog.d.ts.map +1 -0
- package/dist/app/builder/DiscardDialog.js +18 -0
- package/dist/app/builder/DiscardDialog.js.map +1 -0
- package/dist/app/builder/EmptyHint.d.ts +4 -0
- package/dist/app/builder/EmptyHint.d.ts.map +1 -1
- package/dist/app/builder/EmptyHint.js +6 -1
- package/dist/app/builder/EmptyHint.js.map +1 -1
- package/dist/app/builder/LayoutSurface.d.ts +33 -9
- package/dist/app/builder/LayoutSurface.d.ts.map +1 -1
- package/dist/app/builder/LayoutSurface.js +74 -23
- package/dist/app/builder/LayoutSurface.js.map +1 -1
- package/dist/app/builder/PipelineStrip.d.ts +5 -2
- package/dist/app/builder/PipelineStrip.d.ts.map +1 -1
- package/dist/app/builder/PipelineStrip.js +33 -15
- package/dist/app/builder/PipelineStrip.js.map +1 -1
- package/dist/app/builder/SaveDialog.d.ts +9 -1
- package/dist/app/builder/SaveDialog.d.ts.map +1 -1
- package/dist/app/builder/SaveDialog.js +9 -3
- package/dist/app/builder/SaveDialog.js.map +1 -1
- package/dist/app/builder/Toolbar.d.ts +14 -4
- package/dist/app/builder/Toolbar.d.ts.map +1 -1
- package/dist/app/builder/Toolbar.js +24 -7
- package/dist/app/builder/Toolbar.js.map +1 -1
- package/dist/app/builder/Workspace.d.ts +23 -3
- package/dist/app/builder/Workspace.d.ts.map +1 -1
- package/dist/app/builder/Workspace.js +58 -8
- package/dist/app/builder/Workspace.js.map +1 -1
- package/dist/app/builder/builder-model.d.ts +146 -3
- package/dist/app/builder/builder-model.d.ts.map +1 -1
- package/dist/app/builder/builder-model.js +196 -5
- package/dist/app/builder/builder-model.js.map +1 -1
- package/dist/app/builder/labels.d.ts +13 -62
- package/dist/app/builder/labels.d.ts.map +1 -1
- package/dist/app/builder/labels.js +9 -58
- package/dist/app/builder/labels.js.map +1 -1
- package/dist/app/builder/reveal.d.ts +10 -0
- package/dist/app/builder/reveal.d.ts.map +1 -0
- package/dist/app/builder/reveal.js +10 -0
- package/dist/app/builder/reveal.js.map +1 -0
- package/dist/app/builder/status-chip.d.ts.map +1 -1
- package/dist/app/builder/status-chip.js +3 -2
- package/dist/app/builder/status-chip.js.map +1 -1
- package/dist/app/builder/use-builder-catalogue.d.ts +5 -1
- package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -1
- package/dist/app/builder/use-builder-catalogue.js +50 -17
- package/dist/app/builder/use-builder-catalogue.js.map +1 -1
- package/dist/app/builder/use-builder-session.d.ts +30 -0
- package/dist/app/builder/use-builder-session.d.ts.map +1 -0
- package/dist/app/builder/use-builder-session.js +58 -0
- package/dist/app/builder/use-builder-session.js.map +1 -0
- package/dist/app/builder/use-display-resolver.d.ts +17 -0
- package/dist/app/builder/use-display-resolver.d.ts.map +1 -0
- package/dist/app/builder/use-display-resolver.js +16 -0
- package/dist/app/builder/use-display-resolver.js.map +1 -0
- package/dist/app/builder/use-save-dashboard.d.ts +3 -1
- package/dist/app/builder/use-save-dashboard.d.ts.map +1 -1
- package/dist/app/builder/use-save-dashboard.js +3 -1
- package/dist/app/builder/use-save-dashboard.js.map +1 -1
- package/dist/app/index.d.ts +8 -3
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js +8 -2
- package/dist/app/index.js.map +1 -1
- package/dist/app/layout-builder.d.ts +18 -25
- package/dist/app/layout-builder.d.ts.map +1 -1
- package/dist/app/layout-builder.js +84 -78
- package/dist/app/layout-builder.js.map +1 -1
- package/dist/app/mcp-app-view-chrome.d.ts +103 -20
- package/dist/app/mcp-app-view-chrome.d.ts.map +1 -1
- package/dist/app/mcp-app-view-chrome.js +125 -40
- package/dist/app/mcp-app-view-chrome.js.map +1 -1
- package/dist/app/mcp-app-view-states.d.ts +23 -0
- package/dist/app/mcp-app-view-states.d.ts.map +1 -0
- package/dist/app/mcp-app-view-states.js +55 -0
- package/dist/app/mcp-app-view-states.js.map +1 -0
- package/dist/app/mcp-app-view.d.ts +72 -5
- package/dist/app/mcp-app-view.d.ts.map +1 -1
- package/dist/app/mcp-app-view.js +241 -141
- package/dist/app/mcp-app-view.js.map +1 -1
- package/dist/app/mcp-toolkit-app.d.ts +8 -2
- package/dist/app/mcp-toolkit-app.d.ts.map +1 -1
- package/dist/app/mcp-toolkit-app.js +33 -4
- package/dist/app/mcp-toolkit-app.js.map +1 -1
- package/dist/app/mcp-use-host-bridge.d.ts +15 -6
- package/dist/app/mcp-use-host-bridge.d.ts.map +1 -1
- package/dist/app/mcp-use-host-bridge.js +51 -22
- package/dist/app/mcp-use-host-bridge.js.map +1 -1
- package/dist/app/model-context.d.ts +71 -0
- package/dist/app/model-context.d.ts.map +1 -0
- package/dist/app/model-context.js +101 -0
- package/dist/app/model-context.js.map +1 -0
- package/dist/app/use-build-mode-focus.d.ts +33 -0
- package/dist/app/use-build-mode-focus.d.ts.map +1 -0
- package/dist/app/use-build-mode-focus.js +59 -0
- package/dist/app/use-build-mode-focus.js.map +1 -0
- package/dist/app/use-view-actions.d.ts +31 -0
- package/dist/app/use-view-actions.d.ts.map +1 -0
- package/dist/app/use-view-actions.js +81 -0
- package/dist/app/use-view-actions.js.map +1 -0
- package/dist/app/use-view-lifecycle.d.ts +42 -0
- package/dist/app/use-view-lifecycle.d.ts.map +1 -0
- package/dist/app/use-view-lifecycle.js +81 -0
- package/dist/app/use-view-lifecycle.js.map +1 -0
- package/dist/app/view-lifecycle.d.ts +185 -0
- package/dist/app/view-lifecycle.d.ts.map +1 -0
- package/dist/app/view-lifecycle.js +207 -0
- package/dist/app/view-lifecycle.js.map +1 -0
- package/dist/app/widget-fixture.d.ts +10 -3
- package/dist/app/widget-fixture.d.ts.map +1 -1
- package/dist/app/widget-fixture.js +21 -8
- package/dist/app/widget-fixture.js.map +1 -1
- package/dist/app/widget-props-sheet.d.ts +6 -10
- package/dist/app/widget-props-sheet.d.ts.map +1 -1
- package/dist/app/widget-props-sheet.js +25 -20
- package/dist/app/widget-props-sheet.js.map +1 -1
- package/dist/app/widget-renderer.d.ts +41 -1
- package/dist/app/widget-renderer.d.ts.map +1 -1
- package/dist/app/widget-renderer.js +82 -31
- package/dist/app/widget-renderer.js.map +1 -1
- package/dist/components/DrillButton.d.ts +9 -6
- package/dist/components/DrillButton.d.ts.map +1 -1
- package/dist/components/DrillButton.js +9 -6
- package/dist/components/DrillButton.js.map +1 -1
- package/dist/components/EmptyState.d.ts +33 -0
- package/dist/components/EmptyState.d.ts.map +1 -0
- package/dist/components/EmptyState.js +19 -0
- package/dist/components/EmptyState.js.map +1 -0
- package/dist/components/ErrorState.d.ts +53 -0
- package/dist/components/ErrorState.d.ts.map +1 -0
- package/dist/components/ErrorState.js +77 -0
- package/dist/components/ErrorState.js.map +1 -0
- package/dist/components/FilterBar.d.ts +16 -5
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +13 -5
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/GroupCard.d.ts.map +1 -1
- package/dist/components/GroupCard.js +2 -1
- package/dist/components/GroupCard.js.map +1 -1
- package/dist/components/KpiGrid.d.ts +70 -18
- package/dist/components/KpiGrid.d.ts.map +1 -1
- package/dist/components/KpiGrid.js +112 -23
- package/dist/components/KpiGrid.js.map +1 -1
- package/dist/components/ListFooter.d.ts +32 -4
- package/dist/components/ListFooter.d.ts.map +1 -1
- package/dist/components/ListFooter.js +35 -6
- package/dist/components/ListFooter.js.map +1 -1
- package/dist/components/PagedListFooter.d.ts +57 -0
- package/dist/components/PagedListFooter.d.ts.map +1 -0
- package/dist/components/PagedListFooter.js +27 -0
- package/dist/components/PagedListFooter.js.map +1 -0
- package/dist/components/Pills.d.ts +36 -12
- package/dist/components/Pills.d.ts.map +1 -1
- package/dist/components/Pills.js +29 -8
- package/dist/components/Pills.js.map +1 -1
- package/dist/components/SectionHeading.d.ts +3 -1
- package/dist/components/SectionHeading.d.ts.map +1 -1
- package/dist/components/SectionHeading.js +6 -2
- package/dist/components/SectionHeading.js.map +1 -1
- package/dist/components/Toast.d.ts +43 -0
- package/dist/components/Toast.d.ts.map +1 -0
- package/dist/components/Toast.js +106 -0
- package/dist/components/Toast.js.map +1 -0
- package/dist/components/WidgetHeader.d.ts +34 -10
- package/dist/components/WidgetHeader.d.ts.map +1 -1
- package/dist/components/WidgetHeader.js +11 -6
- package/dist/components/WidgetHeader.js.map +1 -1
- package/dist/hooks/index.d.ts +4 -4
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/tool-result-recovery-model.d.ts +155 -0
- package/dist/hooks/tool-result-recovery-model.d.ts.map +1 -0
- package/dist/hooks/tool-result-recovery-model.js +273 -0
- package/dist/hooks/tool-result-recovery-model.js.map +1 -0
- package/dist/hooks/use-tool-query.d.ts +56 -14
- package/dist/hooks/use-tool-query.d.ts.map +1 -1
- package/dist/hooks/use-tool-query.js +102 -25
- package/dist/hooks/use-tool-query.js.map +1 -1
- package/dist/hooks/use-tool-result-recovery.d.ts +61 -44
- package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -1
- package/dist/hooks/use-tool-result-recovery.js +62 -110
- package/dist/hooks/use-tool-result-recovery.js.map +1 -1
- package/dist/hooks/use-view-data.d.ts +55 -7
- package/dist/hooks/use-view-data.d.ts.map +1 -1
- package/dist/hooks/use-view-data.js +81 -11
- package/dist/hooks/use-view-data.js.map +1 -1
- package/dist/hooks/use-view-tool-query.d.ts +12 -7
- package/dist/hooks/use-view-tool-query.d.ts.map +1 -1
- package/dist/hooks/use-view-tool-query.js +15 -14
- package/dist/hooks/use-view-tool-query.js.map +1 -1
- package/dist/index.d.ts +27 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/focus-return.d.ts +61 -0
- package/dist/lib/focus-return.d.ts.map +1 -0
- package/dist/lib/focus-return.js +46 -0
- package/dist/lib/focus-return.js.map +1 -0
- package/dist/lib/focus-ring.d.ts +18 -0
- package/dist/lib/focus-ring.d.ts.map +1 -0
- package/dist/lib/focus-ring.js +18 -0
- package/dist/lib/focus-ring.js.map +1 -0
- package/dist/lib/icon-stroke.d.ts +12 -0
- package/dist/lib/icon-stroke.d.ts.map +1 -0
- package/dist/lib/icon-stroke.js +12 -0
- package/dist/lib/icon-stroke.js.map +1 -0
- package/dist/lib/parse-tool-result.d.ts +23 -1
- package/dist/lib/parse-tool-result.d.ts.map +1 -1
- package/dist/lib/parse-tool-result.js +38 -2
- package/dist/lib/parse-tool-result.js.map +1 -1
- package/dist/lib/toast-model.d.ts +86 -0
- package/dist/lib/toast-model.d.ts.map +1 -0
- package/dist/lib/toast-model.js +102 -0
- package/dist/lib/toast-model.js.map +1 -0
- package/dist/lib/tone-utils.d.ts +95 -9
- package/dist/lib/tone-utils.d.ts.map +1 -1
- package/dist/lib/tone-utils.js +100 -9
- package/dist/lib/tone-utils.js.map +1 -1
- package/dist/lib/tool-query.d.ts +107 -0
- package/dist/lib/tool-query.d.ts.map +1 -0
- package/dist/lib/tool-query.js +182 -0
- package/dist/lib/tool-query.js.map +1 -0
- package/dist/lib/tool-result-observer.d.ts +108 -0
- package/dist/lib/tool-result-observer.d.ts.map +1 -0
- package/dist/lib/tool-result-observer.js +158 -0
- package/dist/lib/tool-result-observer.js.map +1 -0
- package/dist/lib/typography.d.ts +37 -0
- package/dist/lib/typography.d.ts.map +1 -0
- package/dist/lib/typography.js +41 -0
- package/dist/lib/typography.js.map +1 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +11 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/locale/index.d.ts +3 -1
- package/dist/locale/index.d.ts.map +1 -1
- package/dist/locale/index.js +2 -1
- package/dist/locale/index.js.map +1 -1
- package/dist/locale/locale-provider.d.ts +42 -1
- package/dist/locale/locale-provider.d.ts.map +1 -1
- package/dist/locale/locale-provider.js +44 -3
- package/dist/locale/locale-provider.js.map +1 -1
- package/dist/locale/message-types.d.ts +336 -0
- package/dist/locale/message-types.d.ts.map +1 -0
- package/dist/locale/message-types.js +7 -0
- package/dist/locale/message-types.js.map +1 -0
- package/dist/locale/messages-de.d.ts +9 -0
- package/dist/locale/messages-de.d.ts.map +1 -0
- package/dist/locale/messages-de.js +185 -0
- package/dist/locale/messages-de.js.map +1 -0
- package/dist/locale/messages-en.d.ts +8 -0
- package/dist/locale/messages-en.d.ts.map +1 -0
- package/dist/locale/messages-en.js +184 -0
- package/dist/locale/messages-en.js.map +1 -0
- package/dist/locale/toolkit-messages.d.ts +57 -0
- package/dist/locale/toolkit-messages.d.ts.map +1 -0
- package/dist/locale/toolkit-messages.js +103 -0
- package/dist/locale/toolkit-messages.js.map +1 -0
- package/dist/primitives/alert.d.ts +1 -1
- package/dist/primitives/alert.d.ts.map +1 -1
- package/dist/primitives/alert.js +6 -2
- package/dist/primitives/alert.js.map +1 -1
- package/dist/primitives/badge.d.ts +1 -1
- package/dist/primitives/badge.d.ts.map +1 -1
- package/dist/primitives/badge.js +19 -6
- package/dist/primitives/badge.js.map +1 -1
- package/dist/primitives/button.d.ts +1 -1
- package/dist/primitives/button.d.ts.map +1 -1
- package/dist/primitives/button.js +12 -8
- package/dist/primitives/button.js.map +1 -1
- package/dist/primitives/card.js +4 -4
- package/dist/primitives/card.js.map +1 -1
- package/dist/primitives/dialog.d.ts +7 -3
- package/dist/primitives/dialog.d.ts.map +1 -1
- package/dist/primitives/dialog.js +22 -8
- package/dist/primitives/dialog.js.map +1 -1
- package/dist/primitives/input.d.ts.map +1 -1
- package/dist/primitives/input.js +4 -1
- package/dist/primitives/input.js.map +1 -1
- package/dist/primitives/scroll-area.js +1 -1
- package/dist/primitives/scroll-area.js.map +1 -1
- package/dist/primitives/select.d.ts.map +1 -1
- package/dist/primitives/select.js +6 -3
- package/dist/primitives/select.js.map +1 -1
- package/dist/primitives/sheet.d.ts +3 -1
- package/dist/primitives/sheet.d.ts.map +1 -1
- package/dist/primitives/sheet.js +17 -7
- package/dist/primitives/sheet.js.map +1 -1
- package/dist/primitives/skeleton.js +1 -1
- package/dist/primitives/skeleton.js.map +1 -1
- package/dist/primitives/switch.d.ts.map +1 -1
- package/dist/primitives/switch.js +2 -1
- package/dist/primitives/switch.js.map +1 -1
- package/dist/primitives/tabs.d.ts.map +1 -1
- package/dist/primitives/tabs.js +5 -3
- package/dist/primitives/tabs.js.map +1 -1
- package/dist/providers/query-provider.d.ts +32 -1
- package/dist/providers/query-provider.d.ts.map +1 -1
- package/dist/providers/query-provider.js +53 -4
- package/dist/providers/query-provider.js.map +1 -1
- package/dist/render-cases-primitives.js +1 -1
- package/dist/render-cases-primitives.js.map +1 -1
- package/dist/render-cases.d.ts.map +1 -1
- package/dist/render-cases.js +48 -6
- package/dist/render-cases.js.map +1 -1
- package/dist/render-effects.d.ts +42 -0
- package/dist/render-effects.d.ts.map +1 -0
- package/dist/render-effects.js +81 -0
- package/dist/render-effects.js.map +1 -0
- package/dist/render-scan.d.ts +25 -0
- package/dist/render-scan.d.ts.map +1 -0
- package/dist/render-scan.js +66 -0
- package/dist/render-scan.js.map +1 -0
- package/dist/theme/cd-tokens.d.ts +66 -0
- package/dist/theme/cd-tokens.d.ts.map +1 -0
- package/dist/theme/cd-tokens.js +64 -0
- package/dist/theme/cd-tokens.js.map +1 -0
- package/dist/theme/create-theme.d.ts +214 -39
- package/dist/theme/create-theme.d.ts.map +1 -1
- package/dist/theme/create-theme.js +204 -13
- package/dist/theme/create-theme.js.map +1 -1
- package/dist/theme/fonts.d.ts +38 -0
- package/dist/theme/fonts.d.ts.map +1 -0
- package/dist/theme/fonts.js +56 -0
- package/dist/theme/fonts.js.map +1 -0
- package/dist/theme/host-fonts.d.ts +39 -0
- package/dist/theme/host-fonts.d.ts.map +1 -0
- package/dist/theme/host-fonts.js +44 -0
- package/dist/theme/host-fonts.js.map +1 -0
- package/dist/theme/index.d.ts +8 -1
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +5 -1
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/portal-container.d.ts +16 -0
- package/dist/theme/portal-container.d.ts.map +1 -0
- package/dist/theme/portal-container.js +19 -0
- package/dist/theme/portal-container.js.map +1 -0
- package/dist/theme/presets.d.ts +24 -9
- package/dist/theme/presets.d.ts.map +1 -1
- package/dist/theme/presets.js +44 -11
- package/dist/theme/presets.js.map +1 -1
- package/dist/theme/theme-provider.d.ts +27 -9
- package/dist/theme/theme-provider.d.ts.map +1 -1
- package/dist/theme/theme-provider.js +42 -20
- package/dist/theme/theme-provider.js.map +1 -1
- package/package.json +11 -5
- package/src/app/adapt-data-widget.tsx +2 -42
- package/src/app/builder/BuilderBanners.tsx +26 -13
- package/src/app/builder/CanvasRow.tsx +79 -32
- package/src/app/builder/CatalogueSheet.tsx +58 -35
- package/src/app/builder/CellPropsSheet.tsx +17 -2
- package/src/app/builder/DiscardDialog.tsx +59 -0
- package/src/app/builder/EmptyHint.tsx +16 -11
- package/src/app/builder/LayoutSurface.tsx +207 -67
- package/src/app/builder/PipelineStrip.tsx +265 -156
- package/src/app/builder/SaveDialog.tsx +25 -14
- package/src/app/builder/Toolbar.tsx +154 -57
- package/src/app/builder/Workspace.tsx +226 -56
- package/src/app/builder/builder-feedback.test.tsx +75 -0
- package/src/app/builder/builder-model.test.ts +5 -0
- package/src/app/builder/builder-model.ts +346 -6
- package/src/app/builder/builder-model.ux.test.ts +456 -0
- package/src/app/builder/builder-ux.test.tsx +844 -0
- package/src/app/builder/labels.ts +15 -121
- package/src/app/builder/reveal.ts +10 -0
- package/src/app/builder/status-chip.tsx +8 -4
- package/src/app/builder/use-builder-catalogue.ts +62 -19
- package/src/app/builder/use-builder-session.ts +68 -0
- package/src/app/builder/use-display-resolver.ts +24 -0
- package/src/app/builder/use-save-dashboard.ts +5 -0
- package/src/app/index.ts +20 -3
- package/src/app/layout-builder.tsx +193 -186
- package/src/app/mcp-app-view-chrome.test.tsx +487 -14
- package/src/app/mcp-app-view-chrome.tsx +328 -100
- package/src/app/mcp-app-view-states.tsx +140 -0
- package/src/app/mcp-app-view.effects.test.tsx +292 -0
- package/src/app/mcp-app-view.test.tsx +478 -0
- package/src/app/mcp-app-view.tsx +447 -190
- package/src/app/mcp-toolkit-app.test.tsx +40 -0
- package/src/app/mcp-toolkit-app.tsx +39 -8
- package/src/app/mcp-use-host-bridge.test.tsx +180 -0
- package/src/app/mcp-use-host-bridge.tsx +67 -24
- package/src/app/model-context.test.tsx +116 -0
- package/src/app/model-context.tsx +125 -0
- package/src/app/use-build-mode-focus.ts +62 -0
- package/src/app/use-view-actions.ts +89 -0
- package/src/app/use-view-lifecycle.ts +122 -0
- package/src/app/view-lifecycle.test.ts +443 -0
- package/src/app/view-lifecycle.ts +334 -0
- package/src/app/widget-fixture.effects.test.tsx +51 -0
- package/src/app/widget-fixture.render.test.tsx +81 -0
- package/src/app/widget-fixture.tsx +34 -11
- package/src/app/widget-props-sheet.tsx +67 -39
- package/src/app/widget-renderer.render.test.tsx +131 -0
- package/src/app/widget-renderer.tsx +136 -38
- package/src/components/DrillButton.tsx +24 -10
- package/src/components/EmptyState.tsx +83 -0
- package/src/components/ErrorState.tsx +204 -0
- package/src/components/FilterBar.test.tsx +82 -0
- package/src/components/FilterBar.tsx +56 -27
- package/src/components/GroupCard.tsx +3 -2
- package/src/components/KpiGrid.test.tsx +279 -0
- package/src/components/KpiGrid.tsx +329 -91
- package/src/components/ListFooter.test.tsx +116 -0
- package/src/components/ListFooter.tsx +110 -12
- package/src/components/PagedListFooter.test.tsx +140 -0
- package/src/components/PagedListFooter.tsx +107 -0
- package/src/components/Pills.test.tsx +77 -0
- package/src/components/Pills.tsx +78 -16
- package/src/components/SectionHeading.tsx +9 -3
- package/src/components/Toast.tsx +206 -0
- package/src/components/WidgetHeader.test.tsx +78 -0
- package/src/components/WidgetHeader.tsx +63 -16
- package/src/components/feedback-states.test.tsx +314 -0
- package/src/components/tone-figures.test.tsx +58 -0
- package/src/fonts.css +19 -0
- package/src/globals.css +9 -165
- package/src/hooks/index.ts +6 -3
- package/src/hooks/tool-result-recovery-model.test.ts +744 -0
- package/src/hooks/tool-result-recovery-model.ts +418 -0
- package/src/hooks/use-tool-query.effects.test.tsx +205 -0
- package/src/hooks/use-tool-query.ts +156 -33
- package/src/hooks/use-tool-result-recovery.effects.test.tsx +141 -0
- package/src/hooks/use-tool-result-recovery.test.ts +28 -5
- package/src/hooks/use-tool-result-recovery.ts +101 -131
- package/src/hooks/use-view-data.test.tsx +169 -0
- package/src/hooks/use-view-data.ts +131 -10
- package/src/hooks/use-view-tool-query.ts +25 -19
- package/src/i18n-coverage.test.tsx +425 -0
- package/src/index.ts +102 -13
- package/src/lib/focus-return.test.ts +288 -0
- package/src/lib/focus-return.ts +96 -0
- package/src/lib/focus-ring.ts +20 -0
- package/src/lib/icon-stroke.test.ts +59 -0
- package/src/lib/icon-stroke.ts +13 -0
- package/src/lib/parse-tool-result.test.ts +46 -1
- package/src/lib/parse-tool-result.ts +40 -2
- package/src/lib/toast-model.test.ts +233 -0
- package/src/lib/toast-model.ts +165 -0
- package/src/lib/tone-utils.test.ts +125 -16
- package/src/lib/tone-utils.ts +144 -15
- package/src/lib/tool-query.test.ts +569 -0
- package/src/lib/tool-query.ts +253 -0
- package/src/lib/tool-result-observer.test.ts +296 -0
- package/src/lib/tool-result-observer.ts +211 -0
- package/src/lib/typography.test.ts +45 -0
- package/src/lib/typography.ts +47 -0
- package/src/lib/utils.ts +12 -1
- package/src/locale/index.ts +14 -1
- package/src/locale/locale-provider.test.tsx +87 -0
- package/src/locale/locale-provider.tsx +90 -3
- package/src/locale/message-types.ts +337 -0
- package/src/locale/messages-de.ts +198 -0
- package/src/locale/messages-en.ts +196 -0
- package/src/locale/toolkit-messages.test.ts +349 -0
- package/src/locale/toolkit-messages.ts +143 -0
- package/src/no-hardcoded-copy.test.ts +432 -0
- package/src/primitives/alert.tsx +7 -2
- package/src/primitives/badge.tsx +19 -7
- package/src/primitives/button.tsx +13 -8
- package/src/primitives/card.tsx +4 -4
- package/src/primitives/dialog.tsx +42 -8
- package/src/primitives/input.tsx +5 -3
- package/src/primitives/scroll-area.tsx +1 -1
- package/src/primitives/select.tsx +7 -4
- package/src/primitives/sheet.tsx +33 -6
- package/src/primitives/skeleton.tsx +1 -1
- package/src/primitives/switch.tsx +4 -2
- package/src/primitives/tabs.tsx +9 -6
- package/src/providers/query-provider.test.tsx +154 -0
- package/src/providers/query-provider.tsx +66 -5
- package/src/render-cases-primitives.tsx +1 -1
- package/src/render-cases.tsx +82 -6
- package/src/render-effects.tsx +96 -0
- package/src/render-scan.ts +75 -0
- package/src/theme/cd-tokens.generated.css +48 -0
- package/src/theme/cd-tokens.test.ts +109 -0
- package/src/theme/cd-tokens.ts +67 -0
- package/src/theme/create-theme.test.ts +253 -5
- package/src/theme/create-theme.ts +341 -41
- package/src/theme/fonts.test.ts +85 -0
- package/src/theme/fonts.ts +72 -0
- package/src/theme/host-fonts.test.ts +135 -0
- package/src/theme/host-fonts.ts +52 -0
- package/src/theme/index.ts +15 -1
- package/src/theme/portal-container.ts +20 -0
- package/src/theme/presets.ts +44 -11
- package/src/theme/theme-css.test.ts +619 -0
- package/src/theme/theme-provider.test.tsx +82 -0
- package/src/theme/theme-provider.tsx +60 -24
- package/src/theme.css +344 -0
- package/ui-catalog.json +783 -49
|
@@ -4,7 +4,11 @@ import * as React from "react"
|
|
|
4
4
|
import { XIcon } from "lucide-react"
|
|
5
5
|
import { Dialog as DialogPrimitive } from "radix-ui"
|
|
6
6
|
|
|
7
|
+
import { FOCUS_RING } from "../lib/focus-ring.js"
|
|
8
|
+
import { useFocusReturn } from "../lib/focus-return.js"
|
|
9
|
+
import { useToolkitMessages } from "../locale/locale-provider.js"
|
|
7
10
|
import { cn } from "../lib/utils.js"
|
|
11
|
+
import { usePortalContainer } from "../theme/portal-container.js"
|
|
8
12
|
import { Button } from "./button.js"
|
|
9
13
|
|
|
10
14
|
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
@@ -15,8 +19,19 @@ function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive
|
|
|
15
19
|
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
function DialogPortal({
|
|
19
|
-
|
|
22
|
+
function DialogPortal({
|
|
23
|
+
container,
|
|
24
|
+
...props
|
|
25
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
26
|
+
// Default to the nearest ThemeProvider scope (theme + mode), not <body>.
|
|
27
|
+
const portalContainer = usePortalContainer()
|
|
28
|
+
return (
|
|
29
|
+
<DialogPrimitive.Portal
|
|
30
|
+
data-slot="dialog-portal"
|
|
31
|
+
container={container ?? portalContainer ?? undefined}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
20
35
|
}
|
|
21
36
|
|
|
22
37
|
function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
@@ -31,7 +46,7 @@ function DialogOverlay({
|
|
|
31
46
|
<DialogPrimitive.Overlay
|
|
32
47
|
data-slot="dialog-overlay"
|
|
33
48
|
className={cn(
|
|
34
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 fixed inset-0 z-50
|
|
49
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 bg-scrim fixed inset-0 z-50 backdrop-blur-sm",
|
|
35
50
|
className,
|
|
36
51
|
)}
|
|
37
52
|
{...props}
|
|
@@ -43,29 +58,42 @@ function DialogContent({
|
|
|
43
58
|
className,
|
|
44
59
|
children,
|
|
45
60
|
showCloseButton = true,
|
|
61
|
+
closeLabel,
|
|
62
|
+
onOpenAutoFocus,
|
|
63
|
+
onCloseAutoFocus,
|
|
46
64
|
...props
|
|
47
65
|
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
48
66
|
showCloseButton?: boolean
|
|
67
|
+
/** Accessible name of the close button. Default: the locale's "Close". */
|
|
68
|
+
closeLabel?: string
|
|
49
69
|
}) {
|
|
70
|
+
const messages = useToolkitMessages()
|
|
71
|
+
// Without a DialogTrigger, Radix returns the focus nowhere: hand it back to
|
|
72
|
+
// the element that opened it (lib/focus-return.ts).
|
|
73
|
+
const focusReturn = useFocusReturn({ onOpenAutoFocus, onCloseAutoFocus })
|
|
50
74
|
return (
|
|
51
75
|
<DialogPortal data-slot="dialog-portal">
|
|
52
76
|
<DialogOverlay />
|
|
53
77
|
<DialogPrimitive.Content
|
|
54
78
|
data-slot="dialog-content"
|
|
55
79
|
className={cn(
|
|
56
|
-
"bg-
|
|
80
|
+
"bg-popover text-popover-foreground dark:border-input data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 shadow-3 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-md border p-6 outline-hidden duration-(--motion-base) sm:max-w-lg",
|
|
57
81
|
className,
|
|
58
82
|
)}
|
|
59
83
|
{...props}
|
|
84
|
+
{...focusReturn}
|
|
60
85
|
>
|
|
61
86
|
{children}
|
|
62
87
|
{showCloseButton && (
|
|
63
88
|
<DialogPrimitive.Close
|
|
64
89
|
data-slot="dialog-close"
|
|
65
|
-
className=
|
|
90
|
+
className={cn(
|
|
91
|
+
"text-muted-foreground hover:text-foreground absolute top-4 right-4 rounded-sm transition-colors disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
92
|
+
FOCUS_RING,
|
|
93
|
+
)}
|
|
66
94
|
>
|
|
67
95
|
<XIcon />
|
|
68
|
-
<span className="sr-only">
|
|
96
|
+
<span className="sr-only">{closeLabel ?? messages.common.close}</span>
|
|
69
97
|
</DialogPrimitive.Close>
|
|
70
98
|
)}
|
|
71
99
|
</DialogPrimitive.Content>
|
|
@@ -86,11 +114,15 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
86
114
|
function DialogFooter({
|
|
87
115
|
className,
|
|
88
116
|
showCloseButton = false,
|
|
117
|
+
closeLabel,
|
|
89
118
|
children,
|
|
90
119
|
...props
|
|
91
120
|
}: React.ComponentProps<"div"> & {
|
|
92
121
|
showCloseButton?: boolean
|
|
122
|
+
/** Label of the footer close button. Default: the locale's "Close". */
|
|
123
|
+
closeLabel?: string
|
|
93
124
|
}) {
|
|
125
|
+
const messages = useToolkitMessages()
|
|
94
126
|
return (
|
|
95
127
|
<div
|
|
96
128
|
data-slot="dialog-footer"
|
|
@@ -100,7 +132,7 @@ function DialogFooter({
|
|
|
100
132
|
{children}
|
|
101
133
|
{showCloseButton && (
|
|
102
134
|
<DialogPrimitive.Close asChild>
|
|
103
|
-
<Button variant="outline">
|
|
135
|
+
<Button variant="outline">{closeLabel ?? messages.common.close}</Button>
|
|
104
136
|
</DialogPrimitive.Close>
|
|
105
137
|
)}
|
|
106
138
|
</div>
|
|
@@ -111,7 +143,9 @@ function DialogTitle({ className, ...props }: React.ComponentProps<typeof Dialog
|
|
|
111
143
|
return (
|
|
112
144
|
<DialogPrimitive.Title
|
|
113
145
|
data-slot="dialog-title"
|
|
114
|
-
|
|
146
|
+
// The dialog's heading row (CI §8: weight 600) on the type scale's
|
|
147
|
+
// section step (21 px / 600, the CI h3).
|
|
148
|
+
className={cn("text-section", className)}
|
|
115
149
|
{...props}
|
|
116
150
|
/>
|
|
117
151
|
)
|
package/src/primitives/input.tsx
CHANGED
|
@@ -8,9 +8,11 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|
|
8
8
|
type={type}
|
|
9
9
|
data-slot="input"
|
|
10
10
|
className={cn(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
11
|
+
// Input border in --input (3:1 on its surface); focus turns border and a
|
|
12
|
+
// 1px ring --focus: a 2px opaque blue edge (CI §8).
|
|
13
|
+
"border-input selection:bg-primary selection:text-primary-foreground file:text-foreground placeholder:text-muted-foreground bg-background h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base outline-hidden transition-[color,box-shadow,border-color] file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
14
|
+
"focus-visible:border-focus focus-visible:ring-focus focus-visible:ring-1",
|
|
15
|
+
"aria-invalid:border-danger aria-invalid:ring-danger aria-invalid:ring-1",
|
|
14
16
|
className,
|
|
15
17
|
)}
|
|
16
18
|
{...props}
|
|
@@ -16,7 +16,7 @@ function ScrollArea({
|
|
|
16
16
|
>
|
|
17
17
|
<ScrollAreaPrimitive.Viewport
|
|
18
18
|
data-slot="scroll-area-viewport"
|
|
19
|
-
className="focus-visible:ring-
|
|
19
|
+
className="focus-visible:ring-focus size-full rounded-[inherit] outline-hidden transition-[color,box-shadow] focus-visible:ring-2 focus-visible:ring-inset"
|
|
20
20
|
>
|
|
21
21
|
{children}
|
|
22
22
|
</ScrollAreaPrimitive.Viewport>
|
|
@@ -3,6 +3,7 @@ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
|
3
3
|
import { Select as SelectPrimitive } from "radix-ui"
|
|
4
4
|
|
|
5
5
|
import { cn } from "../lib/utils.js"
|
|
6
|
+
import { usePortalContainer } from "../theme/portal-container.js"
|
|
6
7
|
|
|
7
8
|
function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
|
8
9
|
return <SelectPrimitive.Root data-slot="select" {...props} />
|
|
@@ -29,7 +30,7 @@ function SelectTrigger({
|
|
|
29
30
|
data-slot="select-trigger"
|
|
30
31
|
data-size={size}
|
|
31
32
|
className={cn(
|
|
32
|
-
"border-input focus-visible:border-
|
|
33
|
+
"border-input focus-visible:border-focus focus-visible:ring-focus aria-invalid:border-danger aria-invalid:ring-danger data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground bg-background hover:border-focus flex w-fit items-center justify-between gap-2 rounded-md border px-3 py-2 text-sm whitespace-nowrap outline-hidden transition-[color,box-shadow,border-color] focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-1 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
33
34
|
className,
|
|
34
35
|
)}
|
|
35
36
|
{...props}
|
|
@@ -49,12 +50,14 @@ function SelectContent({
|
|
|
49
50
|
align = "center",
|
|
50
51
|
...props
|
|
51
52
|
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
|
53
|
+
// Portal into the nearest ThemeProvider scope (theme + mode), not <body>.
|
|
54
|
+
const portalContainer = usePortalContainer()
|
|
52
55
|
return (
|
|
53
|
-
<SelectPrimitive.Portal>
|
|
56
|
+
<SelectPrimitive.Portal container={portalContainer ?? undefined}>
|
|
54
57
|
<SelectPrimitive.Content
|
|
55
58
|
data-slot="select-content"
|
|
56
59
|
className={cn(
|
|
57
|
-
"bg-popover text-popover-foreground data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border
|
|
60
|
+
"bg-popover text-popover-foreground dark:border-input data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 shadow-3 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border",
|
|
58
61
|
position === "popper" &&
|
|
59
62
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
60
63
|
className,
|
|
@@ -83,7 +86,7 @@ function SelectLabel({ className, ...props }: React.ComponentProps<typeof Select
|
|
|
83
86
|
return (
|
|
84
87
|
<SelectPrimitive.Label
|
|
85
88
|
data-slot="select-label"
|
|
86
|
-
className={cn("text-muted-foreground px-2 py-1.5
|
|
89
|
+
className={cn("text-muted-foreground text-small px-2 py-1.5", className)}
|
|
87
90
|
{...props}
|
|
88
91
|
/>
|
|
89
92
|
)
|
package/src/primitives/sheet.tsx
CHANGED
|
@@ -4,7 +4,11 @@ import * as React from "react"
|
|
|
4
4
|
import { XIcon } from "lucide-react"
|
|
5
5
|
import { Dialog as SheetPrimitive } from "radix-ui"
|
|
6
6
|
|
|
7
|
+
import { FOCUS_RING } from "../lib/focus-ring.js"
|
|
8
|
+
import { useFocusReturn } from "../lib/focus-return.js"
|
|
9
|
+
import { useToolkitMessages } from "../locale/locale-provider.js"
|
|
7
10
|
import { cn } from "../lib/utils.js"
|
|
11
|
+
import { usePortalContainer } from "../theme/portal-container.js"
|
|
8
12
|
|
|
9
13
|
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
|
10
14
|
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
|
@@ -18,8 +22,16 @@ function SheetClose({ ...props }: React.ComponentProps<typeof SheetPrimitive.Clo
|
|
|
18
22
|
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
function SheetPortal({ ...props }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
|
|
22
|
-
|
|
25
|
+
function SheetPortal({ container, ...props }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
|
|
26
|
+
// Default to the nearest ThemeProvider scope (theme + mode), not <body>.
|
|
27
|
+
const portalContainer = usePortalContainer()
|
|
28
|
+
return (
|
|
29
|
+
<SheetPrimitive.Portal
|
|
30
|
+
data-slot="sheet-portal"
|
|
31
|
+
container={container ?? portalContainer ?? undefined}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
23
35
|
}
|
|
24
36
|
|
|
25
37
|
function SheetOverlay({
|
|
@@ -30,7 +42,7 @@ function SheetOverlay({
|
|
|
30
42
|
<SheetPrimitive.Overlay
|
|
31
43
|
data-slot="sheet-overlay"
|
|
32
44
|
className={cn(
|
|
33
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 fixed inset-0 z-50
|
|
45
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 bg-scrim fixed inset-0 z-50 backdrop-blur-sm",
|
|
34
46
|
className,
|
|
35
47
|
)}
|
|
36
48
|
{...props}
|
|
@@ -43,18 +55,27 @@ function SheetContent({
|
|
|
43
55
|
children,
|
|
44
56
|
side = "right",
|
|
45
57
|
showCloseButton = true,
|
|
58
|
+
closeLabel,
|
|
59
|
+
onOpenAutoFocus,
|
|
60
|
+
onCloseAutoFocus,
|
|
46
61
|
...props
|
|
47
62
|
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
|
|
48
63
|
side?: "top" | "right" | "bottom" | "left"
|
|
49
64
|
showCloseButton?: boolean
|
|
65
|
+
/** Accessible name of the close button. Default: the locale's "Close". */
|
|
66
|
+
closeLabel?: string
|
|
50
67
|
}) {
|
|
68
|
+
const messages = useToolkitMessages()
|
|
69
|
+
// Without a SheetTrigger, Radix returns the focus nowhere: hand it back to
|
|
70
|
+
// the element that opened it (lib/focus-return.ts).
|
|
71
|
+
const focusReturn = useFocusReturn({ onOpenAutoFocus, onCloseAutoFocus })
|
|
51
72
|
return (
|
|
52
73
|
<SheetPortal>
|
|
53
74
|
<SheetOverlay />
|
|
54
75
|
<SheetPrimitive.Content
|
|
55
76
|
data-slot="sheet-content"
|
|
56
77
|
className={cn(
|
|
57
|
-
"bg-
|
|
78
|
+
"bg-popover text-popover-foreground dark:border-input data-[state=closed]:animate-out data-[state=open]:animate-in shadow-3 fixed z-50 flex flex-col gap-4 transition data-[state=closed]:duration-(--motion-base) data-[state=open]:duration-(--motion-slow)",
|
|
58
79
|
side === "right" &&
|
|
59
80
|
"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
|
|
60
81
|
side === "left" &&
|
|
@@ -66,12 +87,18 @@ function SheetContent({
|
|
|
66
87
|
className,
|
|
67
88
|
)}
|
|
68
89
|
{...props}
|
|
90
|
+
{...focusReturn}
|
|
69
91
|
>
|
|
70
92
|
{children}
|
|
71
93
|
{showCloseButton && (
|
|
72
|
-
<SheetPrimitive.Close
|
|
94
|
+
<SheetPrimitive.Close
|
|
95
|
+
className={cn(
|
|
96
|
+
"text-muted-foreground hover:text-foreground absolute top-4 right-4 rounded-sm transition-colors disabled:pointer-events-none",
|
|
97
|
+
FOCUS_RING,
|
|
98
|
+
)}
|
|
99
|
+
>
|
|
73
100
|
<XIcon className="size-4" />
|
|
74
|
-
<span className="sr-only">
|
|
101
|
+
<span className="sr-only">{closeLabel ?? messages.common.close}</span>
|
|
75
102
|
</SheetPrimitive.Close>
|
|
76
103
|
)}
|
|
77
104
|
</SheetPrimitive.Content>
|
|
@@ -4,7 +4,7 @@ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
4
4
|
return (
|
|
5
5
|
<div
|
|
6
6
|
data-slot="skeleton"
|
|
7
|
-
className={cn("bg-
|
|
7
|
+
className={cn("bg-border animate-pulse rounded-md", className)}
|
|
8
8
|
{...props}
|
|
9
9
|
/>
|
|
10
10
|
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import { Switch as SwitchPrimitive } from "radix-ui"
|
|
3
3
|
|
|
4
|
+
import { FOCUS_RING } from "../lib/focus-ring.js"
|
|
4
5
|
import { cn } from "../lib/utils.js"
|
|
5
6
|
|
|
6
7
|
function Switch({ className, ...props }: React.ComponentProps<typeof SwitchPrimitive.Root>) {
|
|
@@ -8,14 +9,15 @@ function Switch({ className, ...props }: React.ComponentProps<typeof SwitchPrimi
|
|
|
8
9
|
<SwitchPrimitive.Root
|
|
9
10
|
data-slot="switch"
|
|
10
11
|
className={cn(
|
|
11
|
-
"peer
|
|
12
|
+
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
13
|
+
FOCUS_RING,
|
|
12
14
|
className,
|
|
13
15
|
)}
|
|
14
16
|
{...props}
|
|
15
17
|
>
|
|
16
18
|
<SwitchPrimitive.Thumb
|
|
17
19
|
data-slot="switch-thumb"
|
|
18
|
-
className="bg-
|
|
20
|
+
className="bg-primary-foreground shadow-1 pointer-events-none block h-4 w-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
|
|
19
21
|
/>
|
|
20
22
|
</SwitchPrimitive.Root>
|
|
21
23
|
)
|
package/src/primitives/tabs.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import * as React from "react"
|
|
|
2
2
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
3
|
import { Tabs as TabsPrimitive } from "radix-ui"
|
|
4
4
|
|
|
5
|
+
import { FOCUS_RING, FOCUS_RING_INSET } from "../lib/focus-ring.js"
|
|
5
6
|
import { cn } from "../lib/utils.js"
|
|
6
7
|
|
|
7
8
|
function Tabs({
|
|
@@ -21,7 +22,7 @@ function Tabs({
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const tabsListVariants = cva(
|
|
24
|
-
"group/tabs-list inline-flex w-fit items-center justify-center rounded-
|
|
25
|
+
"group/tabs-list inline-flex w-fit items-center justify-center rounded-md p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-9 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none",
|
|
25
26
|
{
|
|
26
27
|
variants: {
|
|
27
28
|
variant: {
|
|
@@ -55,10 +56,11 @@ function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPr
|
|
|
55
56
|
<TabsPrimitive.Trigger
|
|
56
57
|
data-slot="tabs-trigger"
|
|
57
58
|
className={cn(
|
|
58
|
-
"text-foreground
|
|
59
|
-
|
|
60
|
-
"data-[
|
|
61
|
-
"
|
|
59
|
+
"text-muted-foreground hover:text-foreground group-data-[variant=default]/tabs-list:data-[state=active]:shadow-1 relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-sm border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start disabled:pointer-events-none disabled:opacity-50 group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
60
|
+
FOCUS_RING,
|
|
61
|
+
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
|
|
62
|
+
"data-[state=active]:border-border data-[state=active]:bg-background data-[state=active]:text-foreground",
|
|
63
|
+
"after:bg-primary after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
|
|
62
64
|
className,
|
|
63
65
|
)}
|
|
64
66
|
{...props}
|
|
@@ -67,10 +69,11 @@ function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPr
|
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
|
72
|
+
// Radix makes the panel a tab stop (tabIndex 0), so it needs a visible focus.
|
|
70
73
|
return (
|
|
71
74
|
<TabsPrimitive.Content
|
|
72
75
|
data-slot="tabs-content"
|
|
73
|
-
className={cn("flex-1
|
|
76
|
+
className={cn("flex-1", FOCUS_RING_INSET, className)}
|
|
74
77
|
{...props}
|
|
75
78
|
/>
|
|
76
79
|
)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { QueryClient, QueryClientProvider, useQueryClient } from "@tanstack/react-query"
|
|
2
|
+
import { renderToStaticMarkup } from "react-dom/server"
|
|
3
|
+
import { describe, expect, it, vi } from "vitest"
|
|
4
|
+
import { createStandaloneHostBridge, HostBridgeProvider } from "../app/host-bridge.js"
|
|
5
|
+
import { useToolQueryKey } from "../hooks/use-tool-query.js"
|
|
6
|
+
import {
|
|
7
|
+
AppQueryProvider,
|
|
8
|
+
queryClient,
|
|
9
|
+
useCallTool,
|
|
10
|
+
useToolNameInQueryKey,
|
|
11
|
+
} from "./query-provider.js"
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The tool transport and client of the data hooks (toolkit#176 N25, K18):
|
|
15
|
+
* `AppQueryProvider`'s `callTool`, else the nearest HostBridge — so the
|
|
16
|
+
* documented HostBridgeProvider mount fetches instead of idling.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
type Caller = ReturnType<typeof useCallTool>
|
|
20
|
+
|
|
21
|
+
function probe(tree: (node: React.ReactNode) => React.ReactNode): {
|
|
22
|
+
callTool: Caller
|
|
23
|
+
client: QueryClient
|
|
24
|
+
} {
|
|
25
|
+
let callTool: Caller
|
|
26
|
+
let client: QueryClient | undefined
|
|
27
|
+
function Probe() {
|
|
28
|
+
callTool = useCallTool()
|
|
29
|
+
client = useQueryClient()
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
renderToStaticMarkup(tree(<Probe />))
|
|
33
|
+
if (!client) throw new Error("probe did not render")
|
|
34
|
+
return { callTool, client }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("useCallTool", () => {
|
|
38
|
+
it("AppQueryProvider's callTool wins over a bridge", async () => {
|
|
39
|
+
const explicit = vi.fn(() => Promise.resolve("explicit"))
|
|
40
|
+
const bridgeCall = vi.fn(() => Promise.resolve("bridge"))
|
|
41
|
+
const bridge = createStandaloneHostBridge({ callTool: bridgeCall })
|
|
42
|
+
const { callTool } = probe((node) => (
|
|
43
|
+
<HostBridgeProvider bridge={bridge}>
|
|
44
|
+
<AppQueryProvider callTool={explicit}>{node}</AppQueryProvider>
|
|
45
|
+
</HostBridgeProvider>
|
|
46
|
+
))
|
|
47
|
+
await expect(callTool?.("t", { a: 1 })).resolves.toBe("explicit")
|
|
48
|
+
expect(explicit).toHaveBeenCalledWith("t", { a: 1 })
|
|
49
|
+
expect(bridgeCall).not.toHaveBeenCalled()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it("falls back to the nearest HostBridgeProvider's callTool (N25)", async () => {
|
|
53
|
+
const bridgeCall = vi.fn(() => Promise.resolve("bridge"))
|
|
54
|
+
const bridge = createStandaloneHostBridge({ callTool: bridgeCall })
|
|
55
|
+
const { callTool } = probe((node) => (
|
|
56
|
+
<AppQueryProvider>
|
|
57
|
+
<HostBridgeProvider bridge={bridge}>{node}</HostBridgeProvider>
|
|
58
|
+
</AppQueryProvider>
|
|
59
|
+
))
|
|
60
|
+
await expect(callTool?.("orders_get", { id: 7 })).resolves.toBe("bridge")
|
|
61
|
+
expect(bridgeCall).toHaveBeenCalledWith("orders_get", { id: 7 })
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it("is undefined with neither (the query then fails with NoToolTransportError)", () => {
|
|
65
|
+
const { callTool } = probe((node) => <AppQueryProvider>{node}</AppQueryProvider>)
|
|
66
|
+
expect(callTool).toBeUndefined()
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
describe("AppQueryProvider", () => {
|
|
71
|
+
it("shares the toolkit's client by default", () => {
|
|
72
|
+
expect(probe((node) => <AppQueryProvider>{node}</AppQueryProvider>).client).toBe(queryClient)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it("takes a client of its own, e.g. one per mount", () => {
|
|
76
|
+
const own = new QueryClient()
|
|
77
|
+
expect(probe((node) => <AppQueryProvider client={own}>{node}</AppQueryProvider>).client).toBe(
|
|
78
|
+
own,
|
|
79
|
+
)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it("a nested provider without client keeps its parent's, like toolNameInQueryKey", () => {
|
|
83
|
+
const own = new QueryClient()
|
|
84
|
+
const other = new QueryClient()
|
|
85
|
+
const nested = probe((node) => (
|
|
86
|
+
<AppQueryProvider client={own}>
|
|
87
|
+
<AppQueryProvider callTool={vi.fn()}>{node}</AppQueryProvider>
|
|
88
|
+
</AppQueryProvider>
|
|
89
|
+
))
|
|
90
|
+
expect(nested.client).toBe(own)
|
|
91
|
+
const replaced = probe((node) => (
|
|
92
|
+
<AppQueryProvider client={own}>
|
|
93
|
+
<AppQueryProvider client={other}>{node}</AppQueryProvider>
|
|
94
|
+
</AppQueryProvider>
|
|
95
|
+
))
|
|
96
|
+
expect(replaced.client).toBe(other)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it("a plain TanStack QueryClientProvider is not inherited: the shared client stays", () => {
|
|
100
|
+
const foreign = new QueryClient()
|
|
101
|
+
const { client } = probe((node) => (
|
|
102
|
+
<QueryClientProvider client={foreign}>
|
|
103
|
+
<AppQueryProvider>{node}</AppQueryProvider>
|
|
104
|
+
</QueryClientProvider>
|
|
105
|
+
))
|
|
106
|
+
expect(client).toBe(queryClient)
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
describe("AppQueryProvider toolNameInQueryKey (K18)", () => {
|
|
111
|
+
/** The setting and the key `useToolQueryKey` builds under `tree`. */
|
|
112
|
+
function keyUnder(tree: (node: React.ReactNode) => React.ReactNode) {
|
|
113
|
+
let setting: boolean | undefined
|
|
114
|
+
let key: unknown[] | undefined
|
|
115
|
+
function Probe() {
|
|
116
|
+
setting = useToolNameInQueryKey()
|
|
117
|
+
key = useToolQueryKey(["feed"], "feed_data", { id: 1 })
|
|
118
|
+
return null
|
|
119
|
+
}
|
|
120
|
+
renderToStaticMarkup(tree(<Probe />))
|
|
121
|
+
return { setting, key }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
it("is off by default: the 2.x key, outside a provider too", () => {
|
|
125
|
+
expect(keyUnder((node) => node)).toEqual({ setting: false, key: ["feed", { id: 1 }] })
|
|
126
|
+
expect(keyUnder((node) => <AppQueryProvider>{node}</AppQueryProvider>)).toEqual({
|
|
127
|
+
setting: false,
|
|
128
|
+
key: ["feed", { id: 1 }],
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it("on, the hooks' key carries the tool name", () => {
|
|
133
|
+
expect(
|
|
134
|
+
keyUnder((node) => <AppQueryProvider toolNameInQueryKey>{node}</AppQueryProvider>),
|
|
135
|
+
).toEqual({ setting: true, key: ["feed", "feed_data", { id: 1 }] })
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it("a nested provider keeps its parent's setting unless it sets its own", () => {
|
|
139
|
+
expect(
|
|
140
|
+
keyUnder((node) => (
|
|
141
|
+
<AppQueryProvider toolNameInQueryKey>
|
|
142
|
+
<AppQueryProvider callTool={vi.fn()}>{node}</AppQueryProvider>
|
|
143
|
+
</AppQueryProvider>
|
|
144
|
+
)).setting,
|
|
145
|
+
).toBe(true)
|
|
146
|
+
expect(
|
|
147
|
+
keyUnder((node) => (
|
|
148
|
+
<AppQueryProvider toolNameInQueryKey>
|
|
149
|
+
<AppQueryProvider toolNameInQueryKey={false}>{node}</AppQueryProvider>
|
|
150
|
+
</AppQueryProvider>
|
|
151
|
+
)).setting,
|
|
152
|
+
).toBe(false)
|
|
153
|
+
})
|
|
154
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { createContext, useContext, type ReactNode } from "react"
|
|
1
|
+
import { createContext, useContext, useMemo, type ReactNode } from "react"
|
|
2
2
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
|
3
|
+
import { useHostBridgeOrNull } from "../app/host-bridge.js"
|
|
3
4
|
|
|
4
5
|
// `object` (not `Record<string, unknown>`) because generated tool input
|
|
5
6
|
// interfaces lack an implicit index signature and TS rejects the assignment
|
|
@@ -8,6 +9,9 @@ type CallToolFn = (name: string, args: object) => Promise<unknown>
|
|
|
8
9
|
|
|
9
10
|
const CallToolContext = createContext<CallToolFn | undefined>(undefined)
|
|
10
11
|
|
|
12
|
+
/** Whether the data hooks put the tool name into their cache keys (`toolQueryKey`). */
|
|
13
|
+
const ToolNameInQueryKeyContext = createContext(false)
|
|
14
|
+
|
|
11
15
|
const queryClient = new QueryClient({
|
|
12
16
|
defaultOptions: {
|
|
13
17
|
queries: {
|
|
@@ -17,22 +21,79 @@ const queryClient = new QueryClient({
|
|
|
17
21
|
},
|
|
18
22
|
})
|
|
19
23
|
|
|
24
|
+
/** The client of the nearest `AppQueryProvider`, which a nested one without `client` keeps. */
|
|
25
|
+
const AppQueryClientContext = createContext<QueryClient>(queryClient)
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The query client and tool transport of the toolkit's data hooks.
|
|
29
|
+
*
|
|
30
|
+
* `callTool` is how `useToolQuery` & co. reach the server; without it they
|
|
31
|
+
* fall back to the nearest `HostBridgeProvider`'s bridge (toolkit#176 N25).
|
|
32
|
+
* `client` replaces the shared module-level client, e.g. one per mount;
|
|
33
|
+
* omitted, a nested provider keeps its parent's client (as `McpAppView`'s
|
|
34
|
+
* own provider does), and the outermost one shares the toolkit's client
|
|
35
|
+
* (`queryClient`). `toolNameInQueryKey` puts the tool name into the hooks'
|
|
36
|
+
* cache keys (`[...queryKey, toolName, args]`, see `toolQueryKey`), so two
|
|
37
|
+
* tools never share an entry; omitted, a nested provider keeps its parent's
|
|
38
|
+
* setting, and the outermost one uses the 2.x key `[...queryKey, args]`. The
|
|
39
|
+
* next major makes the tool name the default.
|
|
40
|
+
*/
|
|
20
41
|
export function AppQueryProvider({
|
|
21
42
|
children,
|
|
22
43
|
callTool,
|
|
44
|
+
client,
|
|
45
|
+
toolNameInQueryKey,
|
|
23
46
|
}: {
|
|
24
47
|
children: ReactNode
|
|
25
48
|
callTool?: CallToolFn
|
|
49
|
+
client?: QueryClient
|
|
50
|
+
toolNameInQueryKey?: boolean
|
|
26
51
|
}) {
|
|
52
|
+
const inheritedClient = useAppQueryClient()
|
|
53
|
+
const inherited = useContext(ToolNameInQueryKeyContext)
|
|
54
|
+
const effective = client ?? inheritedClient
|
|
27
55
|
return (
|
|
28
|
-
<
|
|
29
|
-
<
|
|
30
|
-
|
|
56
|
+
<AppQueryClientContext.Provider value={effective}>
|
|
57
|
+
<QueryClientProvider client={effective}>
|
|
58
|
+
<CallToolContext.Provider value={callTool}>
|
|
59
|
+
<ToolNameInQueryKeyContext.Provider value={toolNameInQueryKey ?? inherited}>
|
|
60
|
+
{children}
|
|
61
|
+
</ToolNameInQueryKeyContext.Provider>
|
|
62
|
+
</CallToolContext.Provider>
|
|
63
|
+
</QueryClientProvider>
|
|
64
|
+
</AppQueryClientContext.Provider>
|
|
31
65
|
)
|
|
32
66
|
}
|
|
33
67
|
|
|
68
|
+
/**
|
|
69
|
+
* The client an `AppQueryProvider` without `client` uses at this point: the
|
|
70
|
+
* nearest `AppQueryProvider`'s, else the toolkit's shared `queryClient`. A
|
|
71
|
+
* plain TanStack `QueryClientProvider` does not count.
|
|
72
|
+
*/
|
|
73
|
+
export function useAppQueryClient(): QueryClient {
|
|
74
|
+
return useContext(AppQueryClientContext)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Whether the nearest `AppQueryProvider` puts the tool name into the data
|
|
79
|
+
* hooks' cache keys (`toolNameInQueryKey`); `false` outside one.
|
|
80
|
+
*/
|
|
81
|
+
export function useToolNameInQueryKey(): boolean {
|
|
82
|
+
return useContext(ToolNameInQueryKeyContext)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The tool transport of the data hooks: `AppQueryProvider`'s `callTool`,
|
|
87
|
+
* else the nearest `HostBridgeProvider`'s `callTool`, else `undefined`.
|
|
88
|
+
*/
|
|
34
89
|
export function useCallTool(): CallToolFn | undefined {
|
|
35
|
-
|
|
90
|
+
const explicit = useContext(CallToolContext)
|
|
91
|
+
const bridge = useHostBridgeOrNull()
|
|
92
|
+
return useMemo<CallToolFn | undefined>(() => {
|
|
93
|
+
if (explicit) return explicit
|
|
94
|
+
if (!bridge) return undefined
|
|
95
|
+
return (name, args) => bridge.callTool(name, args as Record<string, unknown>)
|
|
96
|
+
}, [explicit, bridge])
|
|
36
97
|
}
|
|
37
98
|
|
|
38
99
|
export { queryClient }
|
|
@@ -226,7 +226,7 @@ export const PRIMITIVE_RENDER_CASES: RenderCase[] = [
|
|
|
226
226
|
name: "Alert",
|
|
227
227
|
marker: "RC:Alert",
|
|
228
228
|
render: () => (
|
|
229
|
-
<Alert variant="
|
|
229
|
+
<Alert variant="danger">
|
|
230
230
|
<AlertTitle>RC:Alert</AlertTitle>
|
|
231
231
|
<AlertDescription>The engine rejected the job.</AlertDescription>
|
|
232
232
|
</Alert>
|