@miragon/mcp-toolkit-ui 2.6.0 → 2.7.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 +7 -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.map +1 -1
- package/dist/app/builder/CanvasRow.js +12 -14
- 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 +6 -5
- package/dist/app/builder/CatalogueSheet.js.map +1 -1
- 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.js +3 -3
- package/dist/app/builder/LayoutSurface.js.map +1 -1
- package/dist/app/builder/PipelineStrip.d.ts +3 -1
- package/dist/app/builder/PipelineStrip.d.ts.map +1 -1
- package/dist/app/builder/PipelineStrip.js +11 -6
- package/dist/app/builder/PipelineStrip.js.map +1 -1
- package/dist/app/builder/SaveDialog.d.ts.map +1 -1
- package/dist/app/builder/SaveDialog.js +2 -2
- package/dist/app/builder/SaveDialog.js.map +1 -1
- package/dist/app/builder/Toolbar.d.ts +3 -1
- package/dist/app/builder/Toolbar.d.ts.map +1 -1
- package/dist/app/builder/Toolbar.js +9 -3
- package/dist/app/builder/Toolbar.js.map +1 -1
- package/dist/app/builder/Workspace.js +2 -2
- package/dist/app/builder/Workspace.js.map +1 -1
- package/dist/app/builder/builder-model.d.ts +3 -2
- package/dist/app/builder/builder-model.d.ts.map +1 -1
- package/dist/app/builder/builder-model.js +5 -4
- 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/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 +1 -0
- package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -1
- package/dist/app/builder/use-builder-catalogue.js +6 -0
- package/dist/app/builder/use-builder-catalogue.js.map +1 -1
- 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 +1 -1
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js.map +1 -1
- package/dist/app/layout-builder.d.ts +7 -2
- package/dist/app/layout-builder.d.ts.map +1 -1
- package/dist/app/layout-builder.js +17 -5
- package/dist/app/layout-builder.js.map +1 -1
- package/dist/app/mcp-app-view-chrome.d.ts +94 -20
- package/dist/app/mcp-app-view-chrome.d.ts.map +1 -1
- package/dist/app/mcp-app-view-chrome.js +109 -40
- package/dist/app/mcp-app-view-chrome.js.map +1 -1
- package/dist/app/mcp-app-view-states.d.ts +15 -0
- package/dist/app/mcp-app-view-states.d.ts.map +1 -0
- package/dist/app/mcp-app-view-states.js +34 -0
- package/dist/app/mcp-app-view-states.js.map +1 -0
- package/dist/app/mcp-app-view.d.ts +40 -5
- package/dist/app/mcp-app-view.d.ts.map +1 -1
- package/dist/app/mcp-app-view.js +174 -128
- package/dist/app/mcp-app-view.js.map +1 -1
- package/dist/app/mcp-toolkit-app.d.ts +2 -1
- package/dist/app/mcp-toolkit-app.d.ts.map +1 -1
- package/dist/app/mcp-toolkit-app.js +25 -3
- package/dist/app/mcp-toolkit-app.js.map +1 -1
- package/dist/app/use-view-lifecycle.d.ts +38 -0
- package/dist/app/use-view-lifecycle.d.ts.map +1 -0
- package/dist/app/use-view-lifecycle.js +79 -0
- package/dist/app/use-view-lifecycle.js.map +1 -0
- package/dist/app/view-lifecycle.d.ts +109 -0
- package/dist/app/view-lifecycle.d.ts.map +1 -0
- package/dist/app/view-lifecycle.js +120 -0
- package/dist/app/view-lifecycle.js.map +1 -0
- package/dist/app/widget-props-sheet.d.ts +3 -9
- package/dist/app/widget-props-sheet.d.ts.map +1 -1
- package/dist/app/widget-props-sheet.js +6 -13
- 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.map +1 -1
- package/dist/components/DrillButton.js +2 -1
- 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 +17 -0
- package/dist/components/EmptyState.js.map +1 -0
- package/dist/components/ErrorState.d.ts +50 -0
- package/dist/components/ErrorState.d.ts.map +1 -0
- package/dist/components/ErrorState.js +60 -0
- package/dist/components/ErrorState.js.map +1 -0
- package/dist/components/FilterBar.d.ts +1 -1
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +7 -4
- 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 +10 -3
- package/dist/components/KpiGrid.d.ts.map +1 -1
- package/dist/components/KpiGrid.js +31 -9
- package/dist/components/KpiGrid.js.map +1 -1
- package/dist/components/ListFooter.d.ts +3 -2
- package/dist/components/ListFooter.d.ts.map +1 -1
- package/dist/components/ListFooter.js +14 -4
- package/dist/components/ListFooter.js.map +1 -1
- package/dist/components/Pills.d.ts +10 -6
- package/dist/components/Pills.d.ts.map +1 -1
- package/dist/components/Pills.js +12 -6
- package/dist/components/Pills.js.map +1 -1
- package/dist/components/Toast.d.ts +37 -0
- package/dist/components/Toast.d.ts.map +1 -0
- package/dist/components/Toast.js +91 -0
- package/dist/components/Toast.js.map +1 -0
- package/dist/components/WidgetHeader.js +1 -1
- package/dist/hooks/use-tool-result-recovery.d.ts +23 -1
- package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -1
- package/dist/hooks/use-tool-result-recovery.js +21 -7
- package/dist/hooks/use-tool-result-recovery.js.map +1 -1
- package/dist/hooks/use-view-data.d.ts +6 -0
- package/dist/hooks/use-view-data.d.ts.map +1 -1
- package/dist/hooks/use-view-data.js +6 -1
- package/dist/hooks/use-view-data.js.map +1 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -4
- package/dist/index.js.map +1 -1
- 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/toast-model.d.ts +46 -0
- package/dist/lib/toast-model.d.ts.map +1 -0
- package/dist/lib/toast-model.js +36 -0
- package/dist/lib/toast-model.js.map +1 -0
- package/dist/lib/tone-utils.d.ts +43 -9
- package/dist/lib/tone-utils.d.ts.map +1 -1
- package/dist/lib/tone-utils.js +36 -7
- package/dist/lib/tone-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 +223 -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 +151 -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 +150 -0
- package/dist/locale/messages-en.js.map +1 -0
- package/dist/locale/toolkit-messages.d.ts +39 -0
- package/dist/locale/toolkit-messages.d.ts.map +1 -0
- package/dist/locale/toolkit-messages.js +50 -0
- package/dist/locale/toolkit-messages.js.map +1 -0
- package/dist/primitives/alert.d.ts.map +1 -1
- package/dist/primitives/alert.js +4 -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 +14 -6
- package/dist/primitives/badge.js.map +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 +14 -7
- 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 +5 -2
- 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 +12 -6
- 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/render-cases.d.ts.map +1 -1
- package/dist/render-cases.js +20 -2
- package/dist/render-cases.js.map +1 -1
- 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 +196 -39
- package/dist/theme/create-theme.d.ts.map +1 -1
- package/dist/theme/create-theme.js +189 -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 +9 -4
- package/src/app/builder/BuilderBanners.tsx +26 -13
- package/src/app/builder/CanvasRow.tsx +22 -21
- package/src/app/builder/CatalogueSheet.tsx +16 -14
- package/src/app/builder/EmptyHint.tsx +16 -11
- package/src/app/builder/LayoutSurface.tsx +7 -7
- package/src/app/builder/PipelineStrip.tsx +26 -17
- package/src/app/builder/SaveDialog.tsx +11 -12
- package/src/app/builder/Toolbar.tsx +19 -7
- package/src/app/builder/Workspace.tsx +5 -3
- 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 +5 -4
- package/src/app/builder/labels.ts +15 -121
- package/src/app/builder/status-chip.tsx +8 -4
- package/src/app/builder/use-builder-catalogue.ts +6 -0
- package/src/app/builder/use-save-dashboard.ts +5 -0
- package/src/app/index.ts +8 -1
- package/src/app/layout-builder.tsx +23 -3
- package/src/app/mcp-app-view-chrome.test.tsx +347 -14
- package/src/app/mcp-app-view-chrome.tsx +278 -100
- package/src/app/mcp-app-view-states.tsx +100 -0
- package/src/app/mcp-app-view.test.tsx +258 -0
- package/src/app/mcp-app-view.tsx +292 -185
- package/src/app/mcp-toolkit-app.tsx +31 -7
- package/src/app/use-view-lifecycle.ts +116 -0
- package/src/app/view-lifecycle.test.ts +227 -0
- package/src/app/view-lifecycle.ts +174 -0
- package/src/app/widget-props-sheet.tsx +13 -26
- package/src/app/widget-renderer.render.test.tsx +131 -0
- package/src/app/widget-renderer.tsx +136 -38
- package/src/components/DrillButton.tsx +2 -1
- package/src/components/EmptyState.tsx +81 -0
- package/src/components/ErrorState.tsx +182 -0
- package/src/components/FilterBar.tsx +9 -6
- package/src/components/GroupCard.tsx +3 -2
- package/src/components/KpiGrid.tsx +75 -44
- package/src/components/ListFooter.tsx +17 -6
- package/src/components/Pills.tsx +20 -11
- package/src/components/Toast.tsx +188 -0
- package/src/components/WidgetHeader.tsx +1 -1
- package/src/components/feedback-states.test.tsx +225 -0
- package/src/components/tone-figures.test.tsx +54 -0
- package/src/fonts.css +19 -0
- package/src/globals.css +9 -165
- package/src/hooks/use-tool-result-recovery.test.ts +25 -1
- package/src/hooks/use-tool-result-recovery.ts +34 -6
- package/src/hooks/use-view-data.test.tsx +60 -0
- package/src/hooks/use-view-data.ts +12 -1
- package/src/i18n-coverage.test.tsx +323 -0
- package/src/index.ts +57 -5
- 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/toast-model.test.ts +68 -0
- package/src/lib/toast-model.ts +63 -0
- package/src/lib/tone-utils.test.ts +47 -14
- package/src/lib/tone-utils.ts +61 -13
- package/src/locale/index.ts +13 -1
- package/src/locale/locale-provider.test.tsx +87 -0
- package/src/locale/locale-provider.tsx +90 -3
- package/src/locale/message-types.ts +221 -0
- package/src/locale/messages-de.ts +159 -0
- package/src/locale/messages-en.ts +157 -0
- package/src/locale/toolkit-messages.test.ts +216 -0
- package/src/locale/toolkit-messages.ts +82 -0
- package/src/no-hardcoded-copy.test.ts +432 -0
- package/src/primitives/alert.tsx +4 -2
- package/src/primitives/badge.tsx +14 -7
- package/src/primitives/button.tsx +13 -8
- package/src/primitives/card.tsx +4 -4
- package/src/primitives/dialog.tsx +32 -7
- package/src/primitives/input.tsx +5 -3
- package/src/primitives/scroll-area.tsx +1 -1
- package/src/primitives/select.tsx +6 -3
- package/src/primitives/sheet.tsx +26 -6
- package/src/primitives/skeleton.tsx +1 -1
- package/src/primitives/switch.tsx +4 -2
- package/src/primitives/tabs.tsx +9 -6
- package/src/render-cases.tsx +45 -1
- package/src/render-scan.ts +75 -0
- package/src/theme/cd-tokens.generated.css +48 -0
- package/src/theme/cd-tokens.test.ts +107 -0
- package/src/theme/cd-tokens.ts +67 -0
- package/src/theme/create-theme.test.ts +243 -5
- package/src/theme/create-theme.ts +313 -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 +568 -0
- package/src/theme/theme-provider.test.tsx +82 -0
- package/src/theme/theme-provider.tsx +60 -24
- package/src/theme.css +314 -0
- package/ui-catalog.json +344 -17
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { memo } from "react"
|
|
2
|
-
import { Check, Eye, Layers, Library, Save } from "lucide-react"
|
|
2
|
+
import { Check, Eye, Layers, Library, LucideProvider, Save } from "lucide-react"
|
|
3
|
+
import { DENSE_ICON_STROKE } from "../../lib/icon-stroke.js"
|
|
3
4
|
import { Badge } from "../../primitives/badge.js"
|
|
4
5
|
import { Button } from "../../primitives/button.js"
|
|
6
|
+
import { TONE_DOT, TONE_SOFT } from "../../lib/tone-utils.js"
|
|
5
7
|
import { cn } from "../../lib/utils.js"
|
|
6
8
|
import type { LayoutBuilderLabels, RefreshStatus } from "./labels.js"
|
|
7
9
|
import { StatusChip } from "./status-chip.js"
|
|
@@ -41,7 +43,7 @@ function ToolbarImpl({
|
|
|
41
43
|
<span
|
|
42
44
|
className={cn(
|
|
43
45
|
"inline-flex size-6 items-center justify-center rounded-md",
|
|
44
|
-
previewMode ?
|
|
46
|
+
previewMode ? TONE_SOFT.success : TONE_SOFT.info,
|
|
45
47
|
)}
|
|
46
48
|
aria-hidden="true"
|
|
47
49
|
>
|
|
@@ -55,20 +57,21 @@ function ToolbarImpl({
|
|
|
55
57
|
|
|
56
58
|
<div className="text-muted-foreground hidden items-center gap-3 text-[11px] sm:flex">
|
|
57
59
|
<span className="inline-flex items-center gap-1.5">
|
|
58
|
-
<span className=
|
|
60
|
+
<span aria-hidden="true" className={`size-1.5 rounded-full ${TONE_DOT.success}`} />
|
|
59
61
|
<span>
|
|
60
|
-
<span className="text-foreground font-medium">{liveKeys}</span>
|
|
62
|
+
<span className="text-foreground font-medium">{liveKeys}</span> {L.statsLive}
|
|
61
63
|
</span>
|
|
62
64
|
</span>
|
|
63
65
|
<span className="bg-border h-3 w-px" aria-hidden="true" />
|
|
64
66
|
<span>
|
|
65
|
-
<span className="text-foreground font-medium">{reachableCount}</span>
|
|
67
|
+
<span className="text-foreground font-medium">{reachableCount}</span> {L.statsReachable}
|
|
66
68
|
</span>
|
|
67
69
|
{unreachableCount > 0 && (
|
|
68
70
|
<>
|
|
69
71
|
<span className="bg-border h-3 w-px" aria-hidden="true" />
|
|
70
72
|
<span>
|
|
71
|
-
<span className="text-foreground font-medium">{unreachableCount}</span>
|
|
73
|
+
<span className="text-foreground font-medium">{unreachableCount}</span>{" "}
|
|
74
|
+
{L.statsUnreachable}
|
|
72
75
|
</span>
|
|
73
76
|
</>
|
|
74
77
|
)}
|
|
@@ -92,4 +95,13 @@ function ToolbarImpl({
|
|
|
92
95
|
)
|
|
93
96
|
}
|
|
94
97
|
|
|
95
|
-
|
|
98
|
+
/** A dense chrome bar: its Lucide icons draw at stroke 2 (CI §11), not the view's 2.5. */
|
|
99
|
+
function DenseToolbar(props: Parameters<typeof ToolbarImpl>[0]) {
|
|
100
|
+
return (
|
|
101
|
+
<LucideProvider strokeWidth={DENSE_ICON_STROKE}>
|
|
102
|
+
<ToolbarImpl {...props} />
|
|
103
|
+
</LucideProvider>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const Toolbar = memo(DenseToolbar)
|
|
@@ -82,7 +82,7 @@ function WorkspaceImpl({
|
|
|
82
82
|
<div className="flex flex-col gap-3 pr-1">
|
|
83
83
|
{paletteByApp.map(([app, ws]) => (
|
|
84
84
|
<div key={app} className="flex flex-col gap-1">
|
|
85
|
-
<div className="text-muted-foreground
|
|
85
|
+
<div className="text-muted-foreground text-[10px] font-semibold tracking-wide uppercase">
|
|
86
86
|
{app}
|
|
87
87
|
</div>
|
|
88
88
|
{ws.map((w) => (
|
|
@@ -160,10 +160,12 @@ function PaletteItemImpl({ w, onClick }: { w: ReachableWidget; onClick: () => vo
|
|
|
160
160
|
>
|
|
161
161
|
<span className="flex w-full items-center justify-between gap-2">
|
|
162
162
|
<span className="truncate font-mono">{w.id}</span>
|
|
163
|
-
<GripVertical className="text-muted-foreground
|
|
163
|
+
<GripVertical className="text-muted-foreground group-hover:text-accent-foreground size-3" />
|
|
164
164
|
</span>
|
|
165
165
|
{w.requires.length > 0 && (
|
|
166
|
-
|
|
166
|
+
// On the hovered --accent surface quiet text takes the surface's
|
|
167
|
+
// foreground: --muted-foreground drops to 3.66:1 there in dark.
|
|
168
|
+
<span className="text-muted-foreground group-hover:text-accent-foreground truncate font-mono text-[10px]">
|
|
167
169
|
← {w.requires.join(", ")}
|
|
168
170
|
</span>
|
|
169
171
|
)}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { ReactNode } from "react"
|
|
2
|
+
import { renderToStaticMarkup } from "react-dom/server"
|
|
3
|
+
import { describe, expect, it } from "vitest"
|
|
4
|
+
import { LocaleProvider } from "../../locale/locale-provider.js"
|
|
5
|
+
import { TOOLKIT_MESSAGES } from "../../locale/toolkit-messages.js"
|
|
6
|
+
import { attribute, decodeEntities, openingTags } from "../../render-scan.js"
|
|
7
|
+
import { BuilderBanners } from "./BuilderBanners.js"
|
|
8
|
+
import { EmptyHint } from "./EmptyHint.js"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The builder's feedback states on their SSR markup: a failure says what
|
|
12
|
+
* happened and what to do in catalog words, keeps the raw reason under
|
|
13
|
+
* "Details", and offers the next step; the empty state leads with the blue
|
|
14
|
+
* primary button (CI §9).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const de = TOOLKIT_MESSAGES.de
|
|
18
|
+
const inGerman = (node: ReactNode) =>
|
|
19
|
+
renderToStaticMarkup(<LocaleProvider locale="de-DE">{node}</LocaleProvider>)
|
|
20
|
+
const noop = (): void => {}
|
|
21
|
+
const RAW = "MCP error -32602: Tool get-builder-catalogue not found"
|
|
22
|
+
|
|
23
|
+
describe("BuilderBanners: catalogue failure", () => {
|
|
24
|
+
const html = inGerman(
|
|
25
|
+
<BuilderBanners
|
|
26
|
+
L={de.builder}
|
|
27
|
+
catalogueToolName="get-builder-catalogue"
|
|
28
|
+
refreshError={RAW}
|
|
29
|
+
validationIssues={[]}
|
|
30
|
+
onRetry={noop}
|
|
31
|
+
/>,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
it("is the kit's inline error state, announced as an alert", () => {
|
|
35
|
+
const root = openingTags(html, "div").find((t) => /data-slot="error-state"/.test(t)) ?? ""
|
|
36
|
+
expect(attribute(root, "role")).toBe("alert")
|
|
37
|
+
expect(attribute(root, "data-variant")).toBe("inline")
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it("says what happened and what to do in German, with a retry", () => {
|
|
41
|
+
const text = decodeEntities(html)
|
|
42
|
+
expect(text).toContain(de.builder.catalogueError)
|
|
43
|
+
expect(text).toContain(de.builder.catalogueErrorHint)
|
|
44
|
+
expect(text).toContain(`${de.common.retry}</button>`)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it("keeps the raw reason under Details only, never in a sentence the user reads", () => {
|
|
48
|
+
const details = /<details[^>]*>([\s\S]*?)<\/details>/.exec(html)?.[1] ?? ""
|
|
49
|
+
expect(decodeEntities(details)).toContain(`get-builder-catalogue: ${RAW}`)
|
|
50
|
+
const outside = decodeEntities(html.replace(/<details[\s\S]*?<\/details>/g, ""))
|
|
51
|
+
expect(outside).not.toContain(RAW)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it("has no retry without a handler", () => {
|
|
55
|
+
const bare = inGerman(
|
|
56
|
+
<BuilderBanners
|
|
57
|
+
L={de.builder}
|
|
58
|
+
catalogueToolName="get-builder-catalogue"
|
|
59
|
+
refreshError={RAW}
|
|
60
|
+
validationIssues={[]}
|
|
61
|
+
/>,
|
|
62
|
+
)
|
|
63
|
+
expect(bare).not.toContain("<button")
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
describe("EmptyHint", () => {
|
|
68
|
+
it("offers its one next step as the primary (blue) button", () => {
|
|
69
|
+
const html = inGerman(<EmptyHint L={de.builder} onGotoPipeline={noop} />)
|
|
70
|
+
const buttons = openingTags(html, "button")
|
|
71
|
+
expect(buttons).toHaveLength(1)
|
|
72
|
+
expect(attribute(buttons[0] ?? "", "data-variant")).toBe("default")
|
|
73
|
+
expect(decodeEntities(html)).toContain(`${de.builder.openDataSources}</button>`)
|
|
74
|
+
})
|
|
75
|
+
})
|
|
@@ -260,6 +260,11 @@ describe("formatLiveKeyValue", () => {
|
|
|
260
260
|
expect(formatLiveKeyValue("abc")).toBe("live: abc")
|
|
261
261
|
})
|
|
262
262
|
|
|
263
|
+
it("takes the localized prefix", () => {
|
|
264
|
+
expect(formatLiveKeyValue("abc", "vorhanden")).toBe("vorhanden: abc")
|
|
265
|
+
expect(formatLiveKeyValue(42, "vorhanden")).toBe("vorhanden: 42")
|
|
266
|
+
})
|
|
267
|
+
|
|
263
268
|
it("JSON-stringifies non-string values", () => {
|
|
264
269
|
expect(formatLiveKeyValue(42)).toBe("live: 42")
|
|
265
270
|
expect(formatLiveKeyValue({ a: 1 })).toBe('live: {"a":1}')
|
|
@@ -136,14 +136,15 @@ export function entriesToKeys(entries: KeyEntry[]): Record<string, unknown> {
|
|
|
136
136
|
* Compact preview of a value as it currently lives in the pipeline.
|
|
137
137
|
* Used as the placeholder when the editor's `rawValue` is empty so the
|
|
138
138
|
* user can see what the server is actually working with right now
|
|
139
|
-
* without the editor overwriting their (empty) input.
|
|
139
|
+
* without the editor overwriting their (empty) input. `prefix` is the
|
|
140
|
+
* localized word for "live" (the builder passes its catalog's).
|
|
140
141
|
*/
|
|
141
|
-
export function formatLiveKeyValue(value: unknown): string | undefined {
|
|
142
|
+
export function formatLiveKeyValue(value: unknown, prefix = "live"): string | undefined {
|
|
142
143
|
if (value === undefined) return undefined
|
|
143
144
|
if (value === "") return undefined
|
|
144
|
-
if (typeof value === "string") return
|
|
145
|
+
if (typeof value === "string") return `${prefix}: ${value}`
|
|
145
146
|
try {
|
|
146
|
-
return
|
|
147
|
+
return `${prefix}: ${JSON.stringify(value)}`
|
|
147
148
|
} catch {
|
|
148
149
|
return undefined
|
|
149
150
|
}
|
|
@@ -4,130 +4,24 @@
|
|
|
4
4
|
* Extracted from `layout-builder.tsx` so the presentational sub-components
|
|
5
5
|
* (Toolbar, PipelineStrip, Workspace, CatalogueSheet, SaveDialog, PreviewPane)
|
|
6
6
|
* can depend on the labels without importing the orchestrating container —
|
|
7
|
-
* which would create an import cycle. React-free and `mcp-use`-free.
|
|
7
|
+
* which would create an import cycle. React-free and `mcp-use`-free. The
|
|
8
|
+
* strings themselves live in the toolkit catalog (`locale/messages-*.ts`).
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
title?: string
|
|
12
|
-
builderBadge?: string
|
|
13
|
-
previewBadge?: string
|
|
14
|
-
catalogue?: string
|
|
15
|
-
save?: string
|
|
16
|
-
done?: string
|
|
17
|
-
viewLayoutTab?: string
|
|
18
|
-
viewPipelineTab?: string
|
|
19
|
-
viewPreviewTab?: string
|
|
20
|
-
saveDialogTitle?: string
|
|
21
|
-
saveDialogDescription?: string
|
|
22
|
-
saveNameLabel?: string
|
|
23
|
-
saveDescriptionLabel?: string
|
|
24
|
-
saveConfirm?: string
|
|
25
|
-
cancel?: string
|
|
26
|
-
pipelineHeader?: string
|
|
27
|
-
keysHeader?: string
|
|
28
|
-
stepsHeader?: string
|
|
29
|
-
keyName?: string
|
|
30
|
-
keyValue?: string
|
|
31
|
-
stepContextId?: string
|
|
32
|
-
stepPickerLabel?: string
|
|
33
|
-
addKey?: string
|
|
34
|
-
addStep?: string
|
|
35
|
-
emptyKeys?: string
|
|
36
|
-
emptySteps?: string
|
|
37
|
-
statusUpToDate?: string
|
|
38
|
-
statusPending?: string
|
|
39
|
-
statusRefreshing?: string
|
|
40
|
-
paletteHeader?: string
|
|
41
|
-
paletteEmpty?: string
|
|
42
|
-
canvasEmpty?: string
|
|
43
|
-
canvasDropHint?: string
|
|
44
|
-
addRow?: string
|
|
45
|
-
addTab?: string
|
|
46
|
-
removeRow?: string
|
|
47
|
-
renameTab?: string
|
|
48
|
-
removeTab?: string
|
|
49
|
-
tabsLabel?: string
|
|
50
|
-
catalogueDescription?: string
|
|
51
|
-
catalogueKeys?: string
|
|
52
|
-
catalogueSteps?: string
|
|
53
|
-
catalogueUnreachable?: string
|
|
54
|
-
catalogueUnreachableEmpty?: string
|
|
55
|
-
catalogueProducedBy?: string
|
|
56
|
-
catalogueConsumedBy?: string
|
|
57
|
-
catalogueNeedsKeys?: string
|
|
58
|
-
cataloguePickKey?: string
|
|
59
|
-
catalogueAddProducingStep?: string
|
|
60
|
-
catalogueLive?: string
|
|
61
|
-
catalogueMissing?: string
|
|
62
|
-
/** Banner shown when the catalogue fetch fails (prefixes the reason). */
|
|
63
|
-
catalogueError?: string
|
|
64
|
-
/** Heading for the pipeline-validation warning banner. */
|
|
65
|
-
validationWarning?: string
|
|
66
|
-
/** Inline message when a save fails (prefixes the reason). */
|
|
67
|
-
saveError?: string
|
|
68
|
-
/** Inline message when a tab rename is rejected (duplicate label). */
|
|
69
|
-
renameDuplicate?: string
|
|
70
|
-
}
|
|
11
|
+
import { TOOLKIT_MESSAGES, type BuilderMessages } from "../../locale/toolkit-messages.js"
|
|
71
12
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"Persists the current layout along with the keys and steps that populate it.",
|
|
85
|
-
saveNameLabel: "Name",
|
|
86
|
-
saveDescriptionLabel: "Description",
|
|
87
|
-
saveConfirm: "Save dashboard",
|
|
88
|
-
cancel: "Cancel",
|
|
89
|
-
pipelineHeader: "Pipeline",
|
|
90
|
-
keysHeader: "Keys",
|
|
91
|
-
stepsHeader: "Steps",
|
|
92
|
-
keyName: "key",
|
|
93
|
-
keyValue: 'value, "literal", true, {…}',
|
|
94
|
-
stepContextId: "ctx id",
|
|
95
|
-
stepPickerLabel: "pick a step",
|
|
96
|
-
addKey: "Add key",
|
|
97
|
-
addStep: "Add step",
|
|
98
|
-
emptyKeys: "No keys seeded.",
|
|
99
|
-
emptySteps: "No steps configured.",
|
|
100
|
-
statusUpToDate: "Up to date",
|
|
101
|
-
statusPending: "Applying soon…",
|
|
102
|
-
statusRefreshing: "Applying…",
|
|
103
|
-
paletteHeader: "Palette",
|
|
104
|
-
paletteEmpty: "No widgets reachable yet — seed a key or add a step.",
|
|
105
|
-
canvasEmpty: "Drag a widget here, or click one in the palette.",
|
|
106
|
-
canvasDropHint: "Drop to add",
|
|
107
|
-
addRow: "Add row",
|
|
108
|
-
addTab: "Add tab",
|
|
109
|
-
removeRow: "Remove row",
|
|
110
|
-
renameTab: "Rename tab",
|
|
111
|
-
removeTab: "Remove tab",
|
|
112
|
-
tabsLabel: "Tabs",
|
|
113
|
-
catalogueDescription:
|
|
114
|
-
"Every key and widget the framework knows about, whether or not it's reachable right now.",
|
|
115
|
-
catalogueKeys: "Keys",
|
|
116
|
-
catalogueSteps: "Steps",
|
|
117
|
-
catalogueUnreachable: "Unreachable widgets",
|
|
118
|
-
catalogueUnreachableEmpty: "Every registered widget is reachable.",
|
|
119
|
-
catalogueProducedBy: "produced by",
|
|
120
|
-
catalogueConsumedBy: "consumed by",
|
|
121
|
-
catalogueNeedsKeys: "needs",
|
|
122
|
-
cataloguePickKey: "Add as key",
|
|
123
|
-
catalogueAddProducingStep: "Add producing step",
|
|
124
|
-
catalogueLive: "live",
|
|
125
|
-
catalogueMissing: "missing",
|
|
126
|
-
catalogueError: "Couldn't refresh the builder catalogue",
|
|
127
|
-
validationWarning: "This pipeline won't render as configured",
|
|
128
|
-
saveError: "Couldn't save",
|
|
129
|
-
renameDuplicate: "A tab with that name already exists.",
|
|
130
|
-
}
|
|
13
|
+
/**
|
|
14
|
+
* Override strings for every user-facing caption in the builder. Each field
|
|
15
|
+
* defaults to the active locale's toolkit catalog (`useToolkitMessages().builder`).
|
|
16
|
+
*/
|
|
17
|
+
export type LayoutBuilderLabels = Partial<BuilderMessages>
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* English builder strings.
|
|
21
|
+
* @deprecated Read the active locale's strings with `useToolkitMessages().builder`
|
|
22
|
+
* (or `TOOLKIT_MESSAGES.en.builder`); this alias stays for existing imports.
|
|
23
|
+
*/
|
|
24
|
+
export const DEFAULT_LABELS: Required<LayoutBuilderLabels> = TOOLKIT_MESSAGES.en.builder
|
|
131
25
|
|
|
132
26
|
/**
|
|
133
27
|
* MIME type used to carry a widget id across the palette → canvas drag.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CircleDot, Loader2 } from "lucide-react"
|
|
2
|
+
import { TONE_DOT, TONE_TEXT } from "../../lib/tone-utils.js"
|
|
2
3
|
import type { LayoutBuilderLabels, RefreshStatus } from "./labels.js"
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -22,15 +23,18 @@ export function StatusChip({
|
|
|
22
23
|
}
|
|
23
24
|
if (status === "pending") {
|
|
24
25
|
return (
|
|
25
|
-
<span className=
|
|
26
|
-
<span
|
|
26
|
+
<span className={`inline-flex items-center gap-1.5 ${TONE_TEXT.warning}`}>
|
|
27
|
+
<span
|
|
28
|
+
aria-hidden="true"
|
|
29
|
+
className={`size-1.5 animate-pulse rounded-full ${TONE_DOT.warning}`}
|
|
30
|
+
/>
|
|
27
31
|
{L.statusPending}
|
|
28
32
|
</span>
|
|
29
33
|
)
|
|
30
34
|
}
|
|
31
35
|
return (
|
|
32
|
-
<span className=
|
|
33
|
-
<Loader2 className="size-3 animate-spin" />
|
|
36
|
+
<span className={`inline-flex items-center gap-1.5 ${TONE_TEXT.info}`}>
|
|
37
|
+
<Loader2 aria-hidden="true" className="size-3 animate-spin" />
|
|
34
38
|
{L.statusRefreshing}
|
|
35
39
|
</span>
|
|
36
40
|
)
|
|
@@ -111,6 +111,11 @@ export function useBuilderCatalogue({
|
|
|
111
111
|
useEffect(() => {
|
|
112
112
|
refreshRef.current = refreshBuilder
|
|
113
113
|
}, [refreshBuilder])
|
|
114
|
+
// Retry of the catalogue error state: fetch again right away, with the
|
|
115
|
+
// current keys and steps.
|
|
116
|
+
const retryCatalogue = useCallback(() => {
|
|
117
|
+
void refreshRef.current()
|
|
118
|
+
}, [])
|
|
114
119
|
const isFirstRun = useRef(true)
|
|
115
120
|
useEffect(() => {
|
|
116
121
|
if (isFirstRun.current) {
|
|
@@ -178,6 +183,7 @@ export function useBuilderCatalogue({
|
|
|
178
183
|
validationIssues,
|
|
179
184
|
status,
|
|
180
185
|
refreshError,
|
|
186
|
+
retryCatalogue,
|
|
181
187
|
widgetById,
|
|
182
188
|
propsSchemaByWidgetId,
|
|
183
189
|
paletteByApp,
|
|
@@ -22,6 +22,7 @@ export function useSaveDashboard({
|
|
|
22
22
|
stepEntries,
|
|
23
23
|
draft,
|
|
24
24
|
onSaved,
|
|
25
|
+
onSuccess,
|
|
25
26
|
}: {
|
|
26
27
|
callTool: (name: string, args: object) => Promise<unknown>
|
|
27
28
|
saveToolName: string
|
|
@@ -31,6 +32,8 @@ export function useSaveDashboard({
|
|
|
31
32
|
stepEntries: PipelineStepRef[]
|
|
32
33
|
draft: DraftLayout
|
|
33
34
|
onSaved?: (result: { id: string; name: string }) => void
|
|
35
|
+
/** Confirms every successful save (the builder raises a toast), with the saved name. */
|
|
36
|
+
onSuccess?: (name: string) => void
|
|
34
37
|
}) {
|
|
35
38
|
const [isBusy, setBusy] = useState(false)
|
|
36
39
|
const [saveOpen, setSaveOpen] = useState(false)
|
|
@@ -56,6 +59,7 @@ export function useSaveDashboard({
|
|
|
56
59
|
})
|
|
57
60
|
const saved = parseToolResult<{ id?: string; name?: string } | null>(result)
|
|
58
61
|
setSaveOpen(false)
|
|
62
|
+
onSuccess?.(saved?.name ?? saveName.trim())
|
|
59
63
|
if (saved?.id && onSaved) {
|
|
60
64
|
onSaved({
|
|
61
65
|
id: saved.id,
|
|
@@ -75,6 +79,7 @@ export function useSaveDashboard({
|
|
|
75
79
|
draft,
|
|
76
80
|
keyEntries,
|
|
77
81
|
onSaved,
|
|
82
|
+
onSuccess,
|
|
78
83
|
saveDescription,
|
|
79
84
|
saveName,
|
|
80
85
|
saveToolName,
|
package/src/app/index.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
export { McpAppView } from "./mcp-app-view.js"
|
|
2
|
-
export type {
|
|
2
|
+
export type {
|
|
3
|
+
McpAppViewProps,
|
|
4
|
+
McpAppViewLabels,
|
|
5
|
+
DescribeStep,
|
|
6
|
+
DescribeViewError,
|
|
7
|
+
ViewTitleLevel,
|
|
8
|
+
ViewTitleMode,
|
|
9
|
+
} from "./mcp-app-view.js"
|
|
3
10
|
export { McpToolkitApp, mountMcpToolkitApp } from "./mcp-toolkit-app.js"
|
|
4
11
|
export {
|
|
5
12
|
WidgetRenderer,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
initBuilderState,
|
|
8
8
|
type BuilderDraftState,
|
|
9
9
|
} from "./builder/builder-reducer.js"
|
|
10
|
-
import {
|
|
10
|
+
import type { LayoutBuilderLabels } from "./builder/labels.js"
|
|
11
11
|
import { Toolbar } from "./builder/Toolbar.js"
|
|
12
12
|
import { PipelineStrip } from "./builder/PipelineStrip.js"
|
|
13
13
|
import { CatalogueSheet } from "./builder/CatalogueSheet.js"
|
|
@@ -21,6 +21,8 @@ import { useBuilderCatalogue } from "./builder/use-builder-catalogue.js"
|
|
|
21
21
|
import { useKeyStepEntries } from "./builder/use-key-step-entries.js"
|
|
22
22
|
import { useSaveDashboard } from "./builder/use-save-dashboard.js"
|
|
23
23
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../primitives/tabs.js"
|
|
24
|
+
import { ToastProvider, useToast } from "../components/Toast.js"
|
|
25
|
+
import { useToolkitMessages } from "../locale/locale-provider.js"
|
|
24
26
|
import { type WidgetComponent } from "./widget-renderer.js"
|
|
25
27
|
|
|
26
28
|
// -------------------------------------------------------------------------- //
|
|
@@ -73,7 +75,20 @@ export interface LayoutBuilderProps {
|
|
|
73
75
|
// Main component
|
|
74
76
|
// -------------------------------------------------------------------------- //
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
/**
|
|
79
|
+
* The visual view builder. Confirms a successful save with a toast (it mounts
|
|
80
|
+
* a `ToastProvider` when none is above it — inside `McpAppView` it shares the
|
|
81
|
+
* view's). Every caption follows the active locale (`labels` overrides).
|
|
82
|
+
*/
|
|
83
|
+
export function LayoutBuilder(props: LayoutBuilderProps) {
|
|
84
|
+
return (
|
|
85
|
+
<ToastProvider>
|
|
86
|
+
<LayoutBuilderImpl {...props} />
|
|
87
|
+
</ToastProvider>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function LayoutBuilderImpl({
|
|
77
92
|
initialLayout,
|
|
78
93
|
title,
|
|
79
94
|
initialKeys,
|
|
@@ -87,7 +102,9 @@ export function LayoutBuilder({
|
|
|
87
102
|
onSaved,
|
|
88
103
|
onExit,
|
|
89
104
|
}: LayoutBuilderProps) {
|
|
90
|
-
const
|
|
105
|
+
const messages = useToolkitMessages()
|
|
106
|
+
const L = useMemo(() => ({ ...messages.builder, ...labels }), [messages.builder, labels])
|
|
107
|
+
const toast = useToast()
|
|
91
108
|
|
|
92
109
|
// ── Draft layout (pure reducer) ─────────────────────────────────────────
|
|
93
110
|
// The draft plus the UI indices coupled to draft mutations
|
|
@@ -148,6 +165,7 @@ export function LayoutBuilder({
|
|
|
148
165
|
validationIssues,
|
|
149
166
|
status,
|
|
150
167
|
refreshError,
|
|
168
|
+
retryCatalogue,
|
|
151
169
|
widgetById,
|
|
152
170
|
propsSchemaByWidgetId,
|
|
153
171
|
paletteByApp,
|
|
@@ -176,6 +194,7 @@ export function LayoutBuilder({
|
|
|
176
194
|
stepEntries,
|
|
177
195
|
draft,
|
|
178
196
|
onSaved,
|
|
197
|
+
onSuccess: (name) => toast.show({ tone: "success", title: L.saved(name) }),
|
|
179
198
|
})
|
|
180
199
|
|
|
181
200
|
// ── DnD ──────────────────────────────────────────────────────────────────
|
|
@@ -326,6 +345,7 @@ export function LayoutBuilder({
|
|
|
326
345
|
catalogueToolName={catalogueToolName}
|
|
327
346
|
refreshError={refreshError}
|
|
328
347
|
validationIssues={validationIssues}
|
|
348
|
+
onRetry={retryCatalogue}
|
|
329
349
|
/>
|
|
330
350
|
|
|
331
351
|
<Tabs value={view} onValueChange={(v) => setView(v as typeof view)}>
|