@miragon/mcp-toolkit-ui 2.7.0 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- 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.js +1 -1
- 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 +21 -7
- 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 +11 -4
- 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/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 +2 -1
- package/dist/app/builder/PipelineStrip.d.ts.map +1 -1
- package/dist/app/builder/PipelineStrip.js +26 -13
- 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 +8 -2
- package/dist/app/builder/SaveDialog.js.map +1 -1
- package/dist/app/builder/Toolbar.d.ts +12 -4
- package/dist/app/builder/Toolbar.d.ts.map +1 -1
- package/dist/app/builder/Toolbar.js +18 -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 +143 -1
- package/dist/app/builder/builder-model.d.ts.map +1 -1
- package/dist/app/builder/builder-model.js +191 -1
- package/dist/app/builder/builder-model.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/use-builder-catalogue.d.ts +4 -1
- package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -1
- package/dist/app/builder/use-builder-catalogue.js +44 -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/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 +13 -25
- package/dist/app/layout-builder.d.ts.map +1 -1
- package/dist/app/layout-builder.js +75 -81
- package/dist/app/layout-builder.js.map +1 -1
- package/dist/app/mcp-app-view-chrome.d.ts +12 -3
- package/dist/app/mcp-app-view-chrome.d.ts.map +1 -1
- package/dist/app/mcp-app-view-chrome.js +21 -5
- package/dist/app/mcp-app-view-chrome.js.map +1 -1
- package/dist/app/mcp-app-view-states.d.ts +11 -3
- package/dist/app/mcp-app-view-states.d.ts.map +1 -1
- package/dist/app/mcp-app-view-states.js +29 -8
- package/dist/app/mcp-app-view-states.js.map +1 -1
- package/dist/app/mcp-app-view.d.ts +33 -1
- package/dist/app/mcp-app-view.d.ts.map +1 -1
- package/dist/app/mcp-app-view.js +181 -127
- package/dist/app/mcp-app-view.js.map +1 -1
- package/dist/app/mcp-toolkit-app.d.ts +6 -1
- package/dist/app/mcp-toolkit-app.d.ts.map +1 -1
- package/dist/app/mcp-toolkit-app.js +8 -1
- 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 +4 -0
- package/dist/app/use-view-lifecycle.d.ts.map +1 -1
- package/dist/app/use-view-lifecycle.js +2 -0
- package/dist/app/use-view-lifecycle.js.map +1 -1
- package/dist/app/view-lifecycle.d.ts +80 -4
- package/dist/app/view-lifecycle.d.ts.map +1 -1
- package/dist/app/view-lifecycle.js +90 -3
- package/dist/app/view-lifecycle.js.map +1 -1
- 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 +3 -1
- package/dist/app/widget-props-sheet.d.ts.map +1 -1
- package/dist/app/widget-props-sheet.js +22 -10
- package/dist/app/widget-props-sheet.js.map +1 -1
- package/dist/app/widget-renderer.js +1 -1
- package/dist/app/widget-renderer.js.map +1 -1
- package/dist/components/DrillButton.d.ts +14 -6
- package/dist/components/DrillButton.d.ts.map +1 -1
- package/dist/components/DrillButton.js +14 -7
- package/dist/components/DrillButton.js.map +1 -1
- package/dist/components/EmptyState.d.ts.map +1 -1
- package/dist/components/EmptyState.js +4 -2
- package/dist/components/EmptyState.js.map +1 -1
- package/dist/components/ErrorState.d.ts +5 -2
- package/dist/components/ErrorState.d.ts.map +1 -1
- package/dist/components/ErrorState.js +25 -8
- package/dist/components/ErrorState.js.map +1 -1
- package/dist/components/FilterBar.d.ts +15 -4
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +11 -6
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/KpiGrid.d.ts +66 -21
- package/dist/components/KpiGrid.d.ts.map +1 -1
- package/dist/components/KpiGrid.js +101 -34
- package/dist/components/KpiGrid.js.map +1 -1
- package/dist/components/ListFooter.d.ts +31 -4
- package/dist/components/ListFooter.d.ts.map +1 -1
- package/dist/components/ListFooter.js +30 -11
- 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 +27 -7
- package/dist/components/Pills.d.ts.map +1 -1
- package/dist/components/Pills.js +21 -6
- 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 +9 -3
- package/dist/components/Toast.d.ts.map +1 -1
- package/dist/components/Toast.js +31 -16
- package/dist/components/Toast.js.map +1 -1
- 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 +47 -52
- package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -1
- package/dist/hooks/use-tool-result-recovery.js +58 -120
- package/dist/hooks/use-tool-result-recovery.js.map +1 -1
- package/dist/hooks/use-view-data.d.ts +52 -10
- package/dist/hooks/use-view-data.d.ts.map +1 -1
- package/dist/hooks/use-view-data.js +81 -16
- 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 +17 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -6
- 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/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 +41 -1
- package/dist/lib/toast-model.d.ts.map +1 -1
- package/dist/lib/toast-model.js +67 -1
- package/dist/lib/toast-model.js.map +1 -1
- package/dist/lib/tone-utils.d.ts +58 -6
- package/dist/lib/tone-utils.d.ts.map +1 -1
- package/dist/lib/tone-utils.js +66 -4
- 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 +1 -1
- package/dist/locale/index.d.ts.map +1 -1
- package/dist/locale/message-types.d.ts +117 -4
- package/dist/locale/message-types.d.ts.map +1 -1
- package/dist/locale/messages-de.d.ts.map +1 -1
- package/dist/locale/messages-de.js +44 -10
- package/dist/locale/messages-de.js.map +1 -1
- package/dist/locale/messages-en.d.ts.map +1 -1
- package/dist/locale/messages-en.js +44 -10
- package/dist/locale/messages-en.js.map +1 -1
- package/dist/locale/toolkit-messages.d.ts +19 -1
- package/dist/locale/toolkit-messages.d.ts.map +1 -1
- package/dist/locale/toolkit-messages.js +54 -1
- package/dist/locale/toolkit-messages.js.map +1 -1
- package/dist/primitives/alert.d.ts +1 -1
- package/dist/primitives/alert.d.ts.map +1 -1
- package/dist/primitives/alert.js +2 -0
- 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 +9 -4
- package/dist/primitives/badge.js.map +1 -1
- package/dist/primitives/button.d.ts +1 -1
- package/dist/primitives/button.js +1 -1
- package/dist/primitives/button.js.map +1 -1
- package/dist/primitives/dialog.d.ts +1 -1
- package/dist/primitives/dialog.d.ts.map +1 -1
- package/dist/primitives/dialog.js +10 -3
- package/dist/primitives/dialog.js.map +1 -1
- package/dist/primitives/select.js +1 -1
- package/dist/primitives/select.js.map +1 -1
- package/dist/primitives/sheet.d.ts +1 -1
- package/dist/primitives/sheet.d.ts.map +1 -1
- package/dist/primitives/sheet.js +6 -2
- package/dist/primitives/sheet.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 +30 -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/theme/create-theme.d.ts +19 -1
- package/dist/theme/create-theme.d.ts.map +1 -1
- package/dist/theme/create-theme.js +15 -0
- package/dist/theme/create-theme.js.map +1 -1
- package/package.json +5 -4
- package/src/app/adapt-data-widget.tsx +2 -42
- package/src/app/builder/BuilderBanners.tsx +1 -1
- package/src/app/builder/CanvasRow.tsx +63 -17
- package/src/app/builder/CatalogueSheet.tsx +50 -29
- package/src/app/builder/CellPropsSheet.tsx +17 -2
- package/src/app/builder/DiscardDialog.tsx +59 -0
- package/src/app/builder/LayoutSurface.tsx +206 -66
- package/src/app/builder/PipelineStrip.tsx +253 -153
- package/src/app/builder/SaveDialog.tsx +14 -2
- package/src/app/builder/Toolbar.tsx +144 -59
- package/src/app/builder/Workspace.tsx +226 -58
- package/src/app/builder/builder-model.ts +341 -2
- 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/reveal.ts +10 -0
- package/src/app/builder/use-builder-catalogue.ts +56 -19
- package/src/app/builder/use-builder-session.ts +68 -0
- package/src/app/builder/use-display-resolver.ts +24 -0
- package/src/app/index.ts +12 -2
- package/src/app/layout-builder.tsx +178 -191
- package/src/app/mcp-app-view-chrome.test.tsx +141 -1
- package/src/app/mcp-app-view-chrome.tsx +56 -6
- package/src/app/mcp-app-view-states.tsx +51 -11
- package/src/app/mcp-app-view.effects.test.tsx +292 -0
- package/src/app/mcp-app-view.test.tsx +222 -2
- package/src/app/mcp-app-view.tsx +267 -117
- package/src/app/mcp-toolkit-app.test.tsx +40 -0
- package/src/app/mcp-toolkit-app.tsx +8 -1
- 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 +6 -0
- package/src/app/view-lifecycle.test.ts +216 -0
- package/src/app/view-lifecycle.ts +165 -5
- 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 +57 -16
- package/src/app/widget-renderer.tsx +1 -1
- package/src/components/DrillButton.test.tsx +48 -0
- package/src/components/DrillButton.tsx +26 -11
- package/src/components/EmptyState.tsx +6 -4
- package/src/components/ErrorState.tsx +31 -9
- package/src/components/FilterBar.test.tsx +82 -0
- package/src/components/FilterBar.tsx +52 -26
- package/src/components/KpiGrid.test.tsx +279 -0
- package/src/components/KpiGrid.tsx +297 -90
- package/src/components/ListFooter.test.tsx +116 -0
- package/src/components/ListFooter.tsx +102 -15
- 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 +63 -10
- package/src/components/SectionHeading.tsx +9 -3
- package/src/components/Toast.tsx +37 -19
- package/src/components/WidgetHeader.test.tsx +78 -0
- package/src/components/WidgetHeader.tsx +63 -16
- package/src/components/feedback-states.test.tsx +98 -9
- package/src/components/tone-figures.test.tsx +8 -4
- 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 +3 -4
- package/src/hooks/use-tool-result-recovery.ts +84 -142
- package/src/hooks/use-view-data.test.tsx +118 -9
- package/src/hooks/use-view-data.ts +128 -18
- package/src/hooks/use-view-tool-query.ts +25 -19
- package/src/i18n-coverage.test.tsx +104 -2
- package/src/index.ts +48 -11
- package/src/lib/focus-return.test.ts +288 -0
- package/src/lib/focus-return.ts +96 -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 +166 -1
- package/src/lib/toast-model.ts +104 -2
- package/src/lib/tone-utils.test.ts +86 -10
- package/src/lib/tone-utils.ts +89 -8
- 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 +1 -0
- package/src/locale/message-types.ts +118 -2
- package/src/locale/messages-de.ts +49 -10
- package/src/locale/messages-en.ts +49 -10
- package/src/locale/toolkit-messages.test.ts +133 -0
- package/src/locale/toolkit-messages.ts +63 -2
- package/src/primitives/alert.tsx +3 -0
- package/src/primitives/badge.tsx +9 -4
- package/src/primitives/button.tsx +1 -1
- package/src/primitives/dialog.tsx +10 -1
- package/src/primitives/select.tsx +1 -1
- package/src/primitives/sheet.tsx +7 -0
- 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 +38 -6
- package/src/render-effects.tsx +96 -0
- package/src/theme/cd-tokens.test.ts +3 -1
- package/src/theme/create-theme.test.ts +10 -0
- package/src/theme/create-theme.ts +28 -0
- package/src/theme/theme-css.test.ts +51 -0
- package/src/theme.css +31 -1
- package/ui-catalog.json +448 -41
|
@@ -12,14 +12,231 @@ import {
|
|
|
12
12
|
SelectTrigger,
|
|
13
13
|
SelectValue,
|
|
14
14
|
} from "../../primitives/select.js"
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
displayLabel,
|
|
17
|
+
formatLiveKeyValue,
|
|
18
|
+
valueTypeLabel,
|
|
19
|
+
type DisplayKeyResolver,
|
|
20
|
+
type KeyEntry,
|
|
21
|
+
} from "./builder-model.js"
|
|
16
22
|
import type { LayoutBuilderLabels, RefreshStatus } from "./labels.js"
|
|
17
23
|
import { StatusChip } from "./status-chip.js"
|
|
24
|
+
import { useDisplayResolver } from "./use-display-resolver.js"
|
|
18
25
|
|
|
19
26
|
// -------------------------------------------------------------------------- //
|
|
20
|
-
// Pipeline strip —
|
|
27
|
+
// Pipeline strip — the data sources (advanced mode): keys + steps
|
|
21
28
|
// -------------------------------------------------------------------------- //
|
|
22
29
|
|
|
30
|
+
type Labels = Required<LayoutBuilderLabels>
|
|
31
|
+
|
|
32
|
+
/** "needs a, b · provides c" in words (no arrow glyphs): a step's contract. */
|
|
33
|
+
function StepContract({ L, step }: { L: Labels; step: AvailableStep }) {
|
|
34
|
+
return (
|
|
35
|
+
<span className="text-muted-foreground text-small flex flex-wrap gap-x-2">
|
|
36
|
+
<span>
|
|
37
|
+
{L.catalogueNeedsKeys}{" "}
|
|
38
|
+
<span className="font-mono">
|
|
39
|
+
{step.requires.length ? step.requires.join(", ") : L.noInputs}
|
|
40
|
+
</span>
|
|
41
|
+
</span>
|
|
42
|
+
<span>
|
|
43
|
+
{L.stepProvides}{" "}
|
|
44
|
+
<span className="font-mono">
|
|
45
|
+
{step.produces.length ? step.produces.join(", ") : L.noOutputs}
|
|
46
|
+
</span>
|
|
47
|
+
</span>
|
|
48
|
+
</span>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function KeyRows({
|
|
53
|
+
L,
|
|
54
|
+
keyEntries,
|
|
55
|
+
keyCatalog,
|
|
56
|
+
liveKeys,
|
|
57
|
+
onUpdateKey,
|
|
58
|
+
onRemoveKey,
|
|
59
|
+
}: {
|
|
60
|
+
L: Labels
|
|
61
|
+
keyEntries: KeyEntry[]
|
|
62
|
+
keyCatalog: KeyCatalogEntry[]
|
|
63
|
+
liveKeys: Record<string, unknown>
|
|
64
|
+
onUpdateKey: (idx: number, patch: Partial<KeyEntry>) => void
|
|
65
|
+
onRemoveKey: (idx: number) => void
|
|
66
|
+
}) {
|
|
67
|
+
return (
|
|
68
|
+
<ul className="flex flex-col gap-1">
|
|
69
|
+
{keyEntries.map((entry, idx) => {
|
|
70
|
+
const livePreview = formatLiveKeyValue(liveKeys[entry.name], L.catalogueLive)
|
|
71
|
+
const usedNames = new Set(
|
|
72
|
+
keyEntries.map((e, i) => (i === idx ? "" : e.name)).filter(Boolean),
|
|
73
|
+
)
|
|
74
|
+
const pickable = keyCatalog.filter((c) => c.key === entry.name || !usedNames.has(c.key))
|
|
75
|
+
return (
|
|
76
|
+
<li key={idx} className="grid grid-cols-2 items-center gap-1">
|
|
77
|
+
<Select
|
|
78
|
+
value={entry.name || undefined}
|
|
79
|
+
onValueChange={(value) => onUpdateKey(idx, { name: value })}
|
|
80
|
+
>
|
|
81
|
+
<SelectTrigger aria-label={L.keyName} className="text-small h-7 min-w-0 font-mono">
|
|
82
|
+
{/* The trigger names the chosen key only; who uses it shows in the list. */}
|
|
83
|
+
<SelectValue placeholder={L.keyName}>{entry.name || null}</SelectValue>
|
|
84
|
+
</SelectTrigger>
|
|
85
|
+
<SelectContent>
|
|
86
|
+
{pickable.length === 0 ? (
|
|
87
|
+
<div className="text-muted-foreground text-small px-2 py-1.5 italic">
|
|
88
|
+
{L.noMoreKeys}
|
|
89
|
+
</div>
|
|
90
|
+
) : (
|
|
91
|
+
pickable.map((c) => (
|
|
92
|
+
<SelectItem key={c.key} value={c.key} className="py-1.5">
|
|
93
|
+
<div className="flex flex-col gap-0.5">
|
|
94
|
+
<span className="text-small font-mono">{c.key}</span>
|
|
95
|
+
{c.consumedByWidgets.length + c.consumedBySteps.length > 0 && (
|
|
96
|
+
<span className="text-muted-foreground text-small">
|
|
97
|
+
{L.catalogueConsumedBy}{" "}
|
|
98
|
+
<span className="font-mono">
|
|
99
|
+
{[...c.consumedByWidgets, ...c.consumedBySteps].join(", ")}
|
|
100
|
+
</span>
|
|
101
|
+
</span>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
</SelectItem>
|
|
105
|
+
))
|
|
106
|
+
)}
|
|
107
|
+
</SelectContent>
|
|
108
|
+
</Select>
|
|
109
|
+
<div className="flex min-w-0 items-center gap-1">
|
|
110
|
+
<div className="relative min-w-0 flex-1">
|
|
111
|
+
<Input
|
|
112
|
+
aria-label={L.keyValueFor(entry.name)}
|
|
113
|
+
value={entry.rawValue}
|
|
114
|
+
onChange={(e) => onUpdateKey(idx, { rawValue: e.target.value })}
|
|
115
|
+
placeholder={livePreview ?? L.keyValue}
|
|
116
|
+
className="text-small h-7 pr-14 font-mono"
|
|
117
|
+
/>
|
|
118
|
+
<span
|
|
119
|
+
className="text-muted-foreground text-small pointer-events-none absolute top-1/2 right-2 -translate-y-1/2 tabular-nums"
|
|
120
|
+
title={L.parsedType}
|
|
121
|
+
>
|
|
122
|
+
{L.valueType(valueTypeLabel(entry.rawValue))}
|
|
123
|
+
</span>
|
|
124
|
+
</div>
|
|
125
|
+
<Button
|
|
126
|
+
variant="ghost"
|
|
127
|
+
size="icon-xs"
|
|
128
|
+
onClick={() => onRemoveKey(idx)}
|
|
129
|
+
aria-label={L.removeKey}
|
|
130
|
+
>
|
|
131
|
+
<X aria-hidden="true" />
|
|
132
|
+
</Button>
|
|
133
|
+
</div>
|
|
134
|
+
</li>
|
|
135
|
+
)
|
|
136
|
+
})}
|
|
137
|
+
</ul>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function StepRows({
|
|
142
|
+
L,
|
|
143
|
+
stepEntries,
|
|
144
|
+
stepLookup,
|
|
145
|
+
stepsByApp,
|
|
146
|
+
locale,
|
|
147
|
+
resolveKey,
|
|
148
|
+
onUpdateStep,
|
|
149
|
+
onRemoveStep,
|
|
150
|
+
}: {
|
|
151
|
+
L: Labels
|
|
152
|
+
stepEntries: PipelineStepRef[]
|
|
153
|
+
stepLookup: Map<string, AvailableStep>
|
|
154
|
+
stepsByApp: [string, AvailableStep[]][]
|
|
155
|
+
locale: string
|
|
156
|
+
resolveKey: DisplayKeyResolver
|
|
157
|
+
onUpdateStep: (idx: number, patch: Partial<PipelineStepRef>) => void
|
|
158
|
+
onRemoveStep: (idx: number) => void
|
|
159
|
+
}) {
|
|
160
|
+
return (
|
|
161
|
+
<ul className="flex flex-col gap-1">
|
|
162
|
+
{stepEntries.map((step, idx) => {
|
|
163
|
+
const meta = stepLookup.get(step.step)
|
|
164
|
+
const selected = meta ? displayLabel(meta, meta.id, locale, resolveKey).label : step.step
|
|
165
|
+
return (
|
|
166
|
+
<li key={idx} className="flex flex-col gap-0.5">
|
|
167
|
+
<div className="flex items-center gap-1">
|
|
168
|
+
<Input
|
|
169
|
+
aria-label={L.stepContextId}
|
|
170
|
+
value={step.id}
|
|
171
|
+
onChange={(e) => onUpdateStep(idx, { id: e.target.value })}
|
|
172
|
+
placeholder={L.stepContextId}
|
|
173
|
+
className="text-small h-7 w-24 font-mono"
|
|
174
|
+
/>
|
|
175
|
+
<Select
|
|
176
|
+
value={step.step || undefined}
|
|
177
|
+
onValueChange={(value) => onUpdateStep(idx, { step: value })}
|
|
178
|
+
>
|
|
179
|
+
<SelectTrigger
|
|
180
|
+
aria-label={L.stepPickerLabel}
|
|
181
|
+
className="text-small h-7 min-w-0 flex-1"
|
|
182
|
+
>
|
|
183
|
+
{/* The trigger names the chosen step only; its contract follows below. */}
|
|
184
|
+
<SelectValue placeholder={L.stepPickerLabel}>
|
|
185
|
+
{step.step ? selected : null}
|
|
186
|
+
</SelectValue>
|
|
187
|
+
</SelectTrigger>
|
|
188
|
+
<SelectContent>
|
|
189
|
+
{stepsByApp.map(([app, items]) => (
|
|
190
|
+
<div key={app}>
|
|
191
|
+
<div className="text-muted-foreground text-small px-2 py-1 font-semibold">
|
|
192
|
+
{app}
|
|
193
|
+
</div>
|
|
194
|
+
{items.map((s) => {
|
|
195
|
+
const name = displayLabel(s, s.id, locale, resolveKey)
|
|
196
|
+
return (
|
|
197
|
+
<SelectItem key={s.id} value={s.id} className="py-2">
|
|
198
|
+
<div className="flex flex-col gap-0.5">
|
|
199
|
+
<span className="text-small font-medium">{name.label}</span>
|
|
200
|
+
{name.summary && (
|
|
201
|
+
<span className="text-muted-foreground text-small">
|
|
202
|
+
{name.summary}
|
|
203
|
+
</span>
|
|
204
|
+
)}
|
|
205
|
+
{name.hint && (
|
|
206
|
+
<span className="text-muted-foreground text-small font-mono">
|
|
207
|
+
{name.hint}
|
|
208
|
+
</span>
|
|
209
|
+
)}
|
|
210
|
+
<StepContract L={L} step={s} />
|
|
211
|
+
</div>
|
|
212
|
+
</SelectItem>
|
|
213
|
+
)
|
|
214
|
+
})}
|
|
215
|
+
</div>
|
|
216
|
+
))}
|
|
217
|
+
</SelectContent>
|
|
218
|
+
</Select>
|
|
219
|
+
<Button
|
|
220
|
+
variant="ghost"
|
|
221
|
+
size="icon-xs"
|
|
222
|
+
onClick={() => onRemoveStep(idx)}
|
|
223
|
+
aria-label={L.removeStep}
|
|
224
|
+
>
|
|
225
|
+
<X aria-hidden="true" />
|
|
226
|
+
</Button>
|
|
227
|
+
</div>
|
|
228
|
+
{meta && (
|
|
229
|
+
<div className="ml-1 pl-24">
|
|
230
|
+
<StepContract L={L} step={meta} />
|
|
231
|
+
</div>
|
|
232
|
+
)}
|
|
233
|
+
</li>
|
|
234
|
+
)
|
|
235
|
+
})}
|
|
236
|
+
</ul>
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
|
|
23
240
|
function PipelineStripImpl({
|
|
24
241
|
L,
|
|
25
242
|
keyEntries,
|
|
@@ -36,7 +253,7 @@ function PipelineStripImpl({
|
|
|
36
253
|
onRemoveStep,
|
|
37
254
|
status,
|
|
38
255
|
}: {
|
|
39
|
-
L:
|
|
256
|
+
L: Labels
|
|
40
257
|
keyEntries: KeyEntry[]
|
|
41
258
|
stepEntries: PipelineStepRef[]
|
|
42
259
|
keyCatalog: KeyCatalogEntry[]
|
|
@@ -51,6 +268,7 @@ function PipelineStripImpl({
|
|
|
51
268
|
onRemoveStep: (idx: number) => void
|
|
52
269
|
status: RefreshStatus
|
|
53
270
|
}) {
|
|
271
|
+
const { locale, resolveKey } = useDisplayResolver()
|
|
54
272
|
const stepLookup = useMemo(() => {
|
|
55
273
|
const map = new Map<string, AvailableStep>()
|
|
56
274
|
for (const s of availableSteps) map.set(s.id, s)
|
|
@@ -59,97 +277,36 @@ function PipelineStripImpl({
|
|
|
59
277
|
|
|
60
278
|
return (
|
|
61
279
|
<section className="bg-muted/30 -mx-1 rounded-lg border px-3 py-3">
|
|
62
|
-
<div className="mb-2 flex items-center gap-2">
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<span className="text-muted-foreground text-[10px]">· {L.autoApplies}</span>
|
|
67
|
-
<div className="ml-auto text-[11px]">
|
|
280
|
+
<div className="mb-2 flex flex-wrap items-center gap-2">
|
|
281
|
+
<h3 className="text-muted-foreground text-small font-semibold">{L.pipelineHeader}</h3>
|
|
282
|
+
<span className="text-muted-foreground text-small">{L.autoApplies}</span>
|
|
283
|
+
<div className="text-small ml-auto">
|
|
68
284
|
<StatusChip status={status} L={L} />
|
|
69
285
|
</div>
|
|
70
286
|
</div>
|
|
71
287
|
|
|
72
288
|
<div className="grid grid-cols-1 gap-x-6 gap-y-3 lg:grid-cols-2">
|
|
73
289
|
<div className="flex flex-col gap-1.5">
|
|
74
|
-
<div className="text-muted-foreground flex items-center gap-1.5
|
|
75
|
-
<ArrowRightToLine className="size-3" />
|
|
290
|
+
<div className="text-muted-foreground text-small flex items-center gap-1.5 font-semibold">
|
|
291
|
+
<ArrowRightToLine aria-hidden="true" className="size-3.5" />
|
|
76
292
|
{L.keysHeader}
|
|
77
|
-
<Badge variant="outline" className="px-1.5
|
|
293
|
+
<Badge variant="outline" className="px-1.5">
|
|
78
294
|
{keyEntries.length}
|
|
79
295
|
</Badge>
|
|
80
296
|
</div>
|
|
81
297
|
{keyEntries.length === 0 ? (
|
|
82
|
-
<div className="text-muted-foreground rounded-md border border-dashed px-2 py-1.5
|
|
298
|
+
<div className="text-muted-foreground text-small rounded-md border border-dashed px-2 py-1.5 italic">
|
|
83
299
|
{L.emptyKeys}
|
|
84
300
|
</div>
|
|
85
301
|
) : (
|
|
86
|
-
<
|
|
87
|
-
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
95
|
-
return (
|
|
96
|
-
<li key={idx} className="grid grid-cols-2 items-center gap-1">
|
|
97
|
-
<Select
|
|
98
|
-
value={entry.name || undefined}
|
|
99
|
-
onValueChange={(value) => onUpdateKey(idx, { name: value })}
|
|
100
|
-
>
|
|
101
|
-
<SelectTrigger className="h-7 min-w-0 font-mono text-xs">
|
|
102
|
-
<SelectValue placeholder={L.keyName} />
|
|
103
|
-
</SelectTrigger>
|
|
104
|
-
<SelectContent>
|
|
105
|
-
{pickable.length === 0 ? (
|
|
106
|
-
<div className="text-muted-foreground px-2 py-1.5 text-xs italic">
|
|
107
|
-
{L.noMoreKeys}
|
|
108
|
-
</div>
|
|
109
|
-
) : (
|
|
110
|
-
pickable.map((c) => (
|
|
111
|
-
<SelectItem key={c.key} value={c.key} className="py-1.5">
|
|
112
|
-
<div className="flex flex-col gap-0.5">
|
|
113
|
-
<span className="font-mono text-xs">{c.key}</span>
|
|
114
|
-
{c.consumedByWidgets.length + c.consumedBySteps.length > 0 && (
|
|
115
|
-
<span className="text-muted-foreground font-mono text-[10px]">
|
|
116
|
-
→ {[...c.consumedByWidgets, ...c.consumedBySteps].join(", ")}
|
|
117
|
-
</span>
|
|
118
|
-
)}
|
|
119
|
-
</div>
|
|
120
|
-
</SelectItem>
|
|
121
|
-
))
|
|
122
|
-
)}
|
|
123
|
-
</SelectContent>
|
|
124
|
-
</Select>
|
|
125
|
-
<div className="flex min-w-0 items-center gap-1">
|
|
126
|
-
<div className="relative min-w-0 flex-1">
|
|
127
|
-
<Input
|
|
128
|
-
value={entry.rawValue}
|
|
129
|
-
onChange={(e) => onUpdateKey(idx, { rawValue: e.target.value })}
|
|
130
|
-
placeholder={livePreview ?? L.keyValue}
|
|
131
|
-
className="h-7 pr-10 font-mono text-xs"
|
|
132
|
-
/>
|
|
133
|
-
<span
|
|
134
|
-
className="text-muted-foreground pointer-events-none absolute top-1/2 right-2 -translate-y-1/2 font-mono text-[10px] tabular-nums"
|
|
135
|
-
title={L.parsedType}
|
|
136
|
-
>
|
|
137
|
-
{L.valueType(valueTypeLabel(entry.rawValue))}
|
|
138
|
-
</span>
|
|
139
|
-
</div>
|
|
140
|
-
<Button
|
|
141
|
-
variant="ghost"
|
|
142
|
-
size="icon-xs"
|
|
143
|
-
onClick={() => onRemoveKey(idx)}
|
|
144
|
-
aria-label={L.removeKey}
|
|
145
|
-
>
|
|
146
|
-
<X />
|
|
147
|
-
</Button>
|
|
148
|
-
</div>
|
|
149
|
-
</li>
|
|
150
|
-
)
|
|
151
|
-
})}
|
|
152
|
-
</ul>
|
|
302
|
+
<KeyRows
|
|
303
|
+
L={L}
|
|
304
|
+
keyEntries={keyEntries}
|
|
305
|
+
keyCatalog={keyCatalog}
|
|
306
|
+
liveKeys={liveKeys}
|
|
307
|
+
onUpdateKey={onUpdateKey}
|
|
308
|
+
onRemoveKey={onRemoveKey}
|
|
309
|
+
/>
|
|
153
310
|
)}
|
|
154
311
|
<Button
|
|
155
312
|
variant="ghost"
|
|
@@ -157,90 +314,33 @@ function PipelineStripImpl({
|
|
|
157
314
|
onClick={() => onAddKey()}
|
|
158
315
|
className="text-muted-foreground hover:text-foreground self-start"
|
|
159
316
|
>
|
|
160
|
-
<Plus /> {L.addKey}
|
|
317
|
+
<Plus aria-hidden="true" /> {L.addKey}
|
|
161
318
|
</Button>
|
|
162
319
|
</div>
|
|
163
320
|
|
|
164
321
|
<div className="flex flex-col gap-1.5">
|
|
165
|
-
<div className="text-muted-foreground flex items-center gap-1.5
|
|
166
|
-
<ArrowDownToLine className="size-3" />
|
|
322
|
+
<div className="text-muted-foreground text-small flex items-center gap-1.5 font-semibold">
|
|
323
|
+
<ArrowDownToLine aria-hidden="true" className="size-3.5" />
|
|
167
324
|
{L.stepsHeader}
|
|
168
|
-
<Badge variant="outline" className="px-1.5
|
|
325
|
+
<Badge variant="outline" className="px-1.5">
|
|
169
326
|
{stepEntries.length}
|
|
170
327
|
</Badge>
|
|
171
328
|
</div>
|
|
172
329
|
{stepEntries.length === 0 ? (
|
|
173
|
-
<div className="text-muted-foreground rounded-md border border-dashed px-2 py-1.5
|
|
330
|
+
<div className="text-muted-foreground text-small rounded-md border border-dashed px-2 py-1.5 italic">
|
|
174
331
|
{L.emptySteps}
|
|
175
332
|
</div>
|
|
176
333
|
) : (
|
|
177
|
-
<
|
|
178
|
-
{
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
className="h-7 w-24 font-mono text-xs"
|
|
188
|
-
/>
|
|
189
|
-
<Select
|
|
190
|
-
value={step.step || undefined}
|
|
191
|
-
onValueChange={(value) => onUpdateStep(idx, { step: value })}
|
|
192
|
-
>
|
|
193
|
-
<SelectTrigger className="h-7 flex-1 text-xs">
|
|
194
|
-
<SelectValue placeholder={L.stepPickerLabel} />
|
|
195
|
-
</SelectTrigger>
|
|
196
|
-
<SelectContent>
|
|
197
|
-
{stepsByApp.map(([app, items]) => (
|
|
198
|
-
<div key={app}>
|
|
199
|
-
<div className="text-muted-foreground px-2 py-1 text-[10px] font-semibold tracking-wide uppercase">
|
|
200
|
-
{app}
|
|
201
|
-
</div>
|
|
202
|
-
{items.map((s) => (
|
|
203
|
-
<SelectItem key={s.id} value={s.id} className="py-2">
|
|
204
|
-
<div className="flex flex-col gap-0.5">
|
|
205
|
-
<span className="font-mono text-xs">{s.id}</span>
|
|
206
|
-
<div className="text-muted-foreground flex flex-wrap gap-x-2 text-[10px]">
|
|
207
|
-
<span className="font-mono">
|
|
208
|
-
← {s.requires.length ? s.requires.join(", ") : L.noInputs}
|
|
209
|
-
</span>
|
|
210
|
-
<span className="font-mono">
|
|
211
|
-
→ {s.produces.length ? s.produces.join(", ") : L.noOutputs}
|
|
212
|
-
</span>
|
|
213
|
-
</div>
|
|
214
|
-
</div>
|
|
215
|
-
</SelectItem>
|
|
216
|
-
))}
|
|
217
|
-
</div>
|
|
218
|
-
))}
|
|
219
|
-
</SelectContent>
|
|
220
|
-
</Select>
|
|
221
|
-
<Button
|
|
222
|
-
variant="ghost"
|
|
223
|
-
size="icon-xs"
|
|
224
|
-
onClick={() => onRemoveStep(idx)}
|
|
225
|
-
aria-label={L.removeStep}
|
|
226
|
-
>
|
|
227
|
-
<X />
|
|
228
|
-
</Button>
|
|
229
|
-
</div>
|
|
230
|
-
{meta && (
|
|
231
|
-
<div className="text-muted-foreground ml-1 flex flex-wrap gap-x-2 pl-24 text-[10px]">
|
|
232
|
-
<span className="font-mono">
|
|
233
|
-
← {meta.requires.length ? meta.requires.join(", ") : L.noInputs}
|
|
234
|
-
</span>
|
|
235
|
-
<span className="font-mono">
|
|
236
|
-
→ {meta.produces.length ? meta.produces.join(", ") : L.noOutputs}
|
|
237
|
-
</span>
|
|
238
|
-
</div>
|
|
239
|
-
)}
|
|
240
|
-
</li>
|
|
241
|
-
)
|
|
242
|
-
})}
|
|
243
|
-
</ul>
|
|
334
|
+
<StepRows
|
|
335
|
+
L={L}
|
|
336
|
+
stepEntries={stepEntries}
|
|
337
|
+
stepLookup={stepLookup}
|
|
338
|
+
stepsByApp={stepsByApp}
|
|
339
|
+
locale={locale}
|
|
340
|
+
resolveKey={resolveKey}
|
|
341
|
+
onUpdateStep={onUpdateStep}
|
|
342
|
+
onRemoveStep={onRemoveStep}
|
|
343
|
+
/>
|
|
244
344
|
)}
|
|
245
345
|
<Button
|
|
246
346
|
variant="ghost"
|
|
@@ -249,7 +349,7 @@ function PipelineStripImpl({
|
|
|
249
349
|
disabled={availableSteps.length === 0}
|
|
250
350
|
className="text-muted-foreground hover:text-foreground self-start"
|
|
251
351
|
>
|
|
252
|
-
<Plus /> {L.addStep}
|
|
352
|
+
<Plus aria-hidden="true" /> {L.addStep}
|
|
253
353
|
</Button>
|
|
254
354
|
</div>
|
|
255
355
|
</div>
|
|
@@ -16,10 +16,17 @@ import type { LayoutBuilderLabels } from "./labels.js"
|
|
|
16
16
|
// Save dialog
|
|
17
17
|
// -------------------------------------------------------------------------- //
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Names the draft and saves it as a dashboard. Its description mentions Apply
|
|
21
|
+
* only where there is one (`canApply`: the builder has an `onExit`). Opens
|
|
22
|
+
* with the focus on the name field and hands it back to "Save as dashboard"
|
|
23
|
+
* when it closes.
|
|
24
|
+
*/
|
|
19
25
|
export function SaveDialog({
|
|
20
26
|
L,
|
|
21
27
|
open,
|
|
22
28
|
onOpenChange,
|
|
29
|
+
canApply,
|
|
23
30
|
name,
|
|
24
31
|
setName,
|
|
25
32
|
description,
|
|
@@ -31,6 +38,8 @@ export function SaveDialog({
|
|
|
31
38
|
L: Required<LayoutBuilderLabels>
|
|
32
39
|
open: boolean
|
|
33
40
|
onOpenChange: (open: boolean) => void
|
|
41
|
+
/** The builder has a view to apply the draft to (an `onExit`). */
|
|
42
|
+
canApply: boolean
|
|
34
43
|
name: string
|
|
35
44
|
setName: (v: string) => void
|
|
36
45
|
description: string
|
|
@@ -44,16 +53,19 @@ export function SaveDialog({
|
|
|
44
53
|
<DialogContent>
|
|
45
54
|
<DialogHeader>
|
|
46
55
|
<DialogTitle>{L.saveDialogTitle}</DialogTitle>
|
|
47
|
-
<DialogDescription>
|
|
56
|
+
<DialogDescription>
|
|
57
|
+
{canApply ? L.saveDialogDescription : L.saveDialogDescriptionStandalone}
|
|
58
|
+
</DialogDescription>
|
|
48
59
|
</DialogHeader>
|
|
49
60
|
<div className="flex flex-col gap-3">
|
|
50
61
|
<label className="flex flex-col gap-1 text-sm">
|
|
51
62
|
<span className="font-medium">{L.saveNameLabel}</span>
|
|
63
|
+
{/* No autoFocus: the dialog focuses this first field itself, and
|
|
64
|
+
only then notes where to hand the focus back on close. */}
|
|
52
65
|
<Input
|
|
53
66
|
value={name}
|
|
54
67
|
onChange={(e) => setName(e.target.value)}
|
|
55
68
|
placeholder={L.saveNamePlaceholder}
|
|
56
|
-
autoFocus
|
|
57
69
|
/>
|
|
58
70
|
</label>
|
|
59
71
|
<label className="flex flex-col gap-1 text-sm">
|