@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
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { useCallback, useEffect, useReducer, useRef, useState } from "react";
|
|
2
|
+
import { decodeViewResult, errorMessage, resolveViewLifecycle, RETRY_IDLE, retryFocusTarget, retryReducer, waitKey, withSlowHint, } from "./view-lifecycle.js";
|
|
3
|
+
/**
|
|
4
|
+
* Drives the {@link resolveViewLifecycle} state machine: owns the retry and
|
|
5
|
+
* the slow-hint timer, and returns the current phase plus `retry()`.
|
|
6
|
+
*/
|
|
7
|
+
export function useViewLifecycle(options) {
|
|
8
|
+
const { toolName, toolInput, callTool, isValid, onResult, slowHintAfterMs } = options;
|
|
9
|
+
const [retryState, dispatch] = useReducer(retryReducer, RETRY_IDLE);
|
|
10
|
+
// The wait that went slow; a newer wait (another attempt) starts fresh.
|
|
11
|
+
const [slowWait, setSlowWait] = useState(null);
|
|
12
|
+
const unslowed = resolveViewLifecycle({
|
|
13
|
+
hasViewData: options.hasViewData,
|
|
14
|
+
callStatus: options.callStatus,
|
|
15
|
+
cancelled: options.cancelled,
|
|
16
|
+
callErrorReason: errorMessage(options.callError),
|
|
17
|
+
recoveryFailed: options.recoveryFailed,
|
|
18
|
+
retryState,
|
|
19
|
+
slow: false,
|
|
20
|
+
canRetry: toolName !== undefined,
|
|
21
|
+
});
|
|
22
|
+
const currentWait = waitKey(unslowed, retryState);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (currentWait === null)
|
|
25
|
+
return;
|
|
26
|
+
const timer = setTimeout(() => setSlowWait(currentWait), slowHintAfterMs);
|
|
27
|
+
return () => clearTimeout(timer);
|
|
28
|
+
}, [currentWait, slowHintAfterMs]);
|
|
29
|
+
const lifecycle = withSlowHint(unslowed, slowWait, currentWait);
|
|
30
|
+
const retry = useCallback(() => {
|
|
31
|
+
if (toolName === undefined)
|
|
32
|
+
return;
|
|
33
|
+
dispatch({ type: "start" });
|
|
34
|
+
void callTool(toolName, toolInput ?? {}).then((result) => {
|
|
35
|
+
const outcome = decodeViewResult(result, isValid);
|
|
36
|
+
if (outcome.ok) {
|
|
37
|
+
onResult(outcome.data);
|
|
38
|
+
dispatch({ type: "succeeded" });
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
dispatch({ type: "failed", reason: outcome.reason });
|
|
42
|
+
}
|
|
43
|
+
}, (err) => dispatch({ type: "failed", reason: errorMessage(err) }));
|
|
44
|
+
}, [callTool, isValid, onResult, toolInput, toolName]);
|
|
45
|
+
return { lifecycle, retry };
|
|
46
|
+
}
|
|
47
|
+
/** The retry button of the view's error state (the focus target after a failed retry). */
|
|
48
|
+
const RETRY_BUTTON = '[data-slot="error-state"] button';
|
|
49
|
+
/**
|
|
50
|
+
* Keeps keyboard focus in the view across a user retry: the pressed button
|
|
51
|
+
* unmounts when the view starts waiting, so focus moves to the frame (a
|
|
52
|
+
* `tabIndex={-1}` container), then to the new retry button when the retry
|
|
53
|
+
* failed, or stays on the frame once the view rendered (see
|
|
54
|
+
* {@link retryFocusTarget}). Focus the user moved elsewhere meanwhile is left
|
|
55
|
+
* alone. Returns the frame ref and `retry` wrapped to start the hand-off.
|
|
56
|
+
*/
|
|
57
|
+
export function useRetryFocus(phase, retry) {
|
|
58
|
+
const frameRef = useRef(null);
|
|
59
|
+
const owed = useRef(false);
|
|
60
|
+
const retryWithFocus = useCallback(() => {
|
|
61
|
+
owed.current = true;
|
|
62
|
+
retry();
|
|
63
|
+
}, [retry]);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const frame = frameRef.current;
|
|
66
|
+
if (!owed.current || !frame)
|
|
67
|
+
return;
|
|
68
|
+
const { target, settled } = retryFocusTarget(phase);
|
|
69
|
+
if (settled)
|
|
70
|
+
owed.current = false;
|
|
71
|
+
const active = frame.ownerDocument.activeElement;
|
|
72
|
+
if (active && active !== frame.ownerDocument.body && !frame.contains(active))
|
|
73
|
+
return;
|
|
74
|
+
const button = target === "retry" ? frame.querySelector(RETRY_BUTTON) : null;
|
|
75
|
+
(button ?? frame).focus();
|
|
76
|
+
}, [phase]);
|
|
77
|
+
return { frameRef, retry: retryWithFocus };
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=use-view-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-view-lifecycle.js","sourceRoot":"","sources":["../../src/app/use-view-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/** `useToolContext().status` of the rendering call. */
|
|
2
|
+
export type RenderCallStatus = "pending" | "ready" | "error";
|
|
3
|
+
/** The user-triggered retry of the rendering call. */
|
|
4
|
+
export type RetryState = {
|
|
5
|
+
status: "idle";
|
|
6
|
+
attempt: number;
|
|
7
|
+
} | {
|
|
8
|
+
status: "running";
|
|
9
|
+
attempt: number;
|
|
10
|
+
} | {
|
|
11
|
+
status: "failed";
|
|
12
|
+
attempt: number;
|
|
13
|
+
reason: string | undefined;
|
|
14
|
+
};
|
|
15
|
+
export declare const RETRY_IDLE: RetryState;
|
|
16
|
+
export type RetryAction = {
|
|
17
|
+
type: "start";
|
|
18
|
+
} | {
|
|
19
|
+
type: "failed";
|
|
20
|
+
reason: string | undefined;
|
|
21
|
+
} | {
|
|
22
|
+
type: "succeeded";
|
|
23
|
+
};
|
|
24
|
+
/** start → running (next attempt); failed → failed with reason; succeeded → idle. */
|
|
25
|
+
export declare function retryReducer(state: RetryState, action: RetryAction): RetryState;
|
|
26
|
+
export interface ViewLifecycleInput {
|
|
27
|
+
/** A renderable payload is in hand (host-delivered, recovered or retried). */
|
|
28
|
+
hasViewData: boolean;
|
|
29
|
+
/** Status of the original rendering call. */
|
|
30
|
+
callStatus: RenderCallStatus;
|
|
31
|
+
/** The host cancelled the original rendering call. */
|
|
32
|
+
cancelled: boolean;
|
|
33
|
+
/** Message of the original call's error, when it failed. */
|
|
34
|
+
callErrorReason: string | undefined;
|
|
35
|
+
/** The automatic stripped-result recovery ran and failed. */
|
|
36
|
+
recoveryFailed: boolean;
|
|
37
|
+
/** The user-triggered retry. */
|
|
38
|
+
retryState: RetryState;
|
|
39
|
+
/** Loading has outlasted the slow-hint delay. */
|
|
40
|
+
slow: boolean;
|
|
41
|
+
/** The originating tool is known, so a retry can re-run it. */
|
|
42
|
+
canRetry: boolean;
|
|
43
|
+
}
|
|
44
|
+
export type ViewLifecycle = {
|
|
45
|
+
phase: "result";
|
|
46
|
+
} | {
|
|
47
|
+
phase: "waiting";
|
|
48
|
+
slow: boolean;
|
|
49
|
+
} | {
|
|
50
|
+
phase: "cancelled";
|
|
51
|
+
} | {
|
|
52
|
+
phase: "error";
|
|
53
|
+
reason: string | undefined;
|
|
54
|
+
canRetry: boolean;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the single phase the view is in. Precedence: a payload always wins;
|
|
58
|
+
* a running retry is waiting; a failed retry is an error with ITS reason; a
|
|
59
|
+
* cancellation is terminal; a failed call, a failed recovery or a latched
|
|
60
|
+
* non-view result nothing can recover is an error; everything else is still
|
|
61
|
+
* waiting.
|
|
62
|
+
*/
|
|
63
|
+
export declare function resolveViewLifecycle(input: ViewLifecycleInput): ViewLifecycle;
|
|
64
|
+
/**
|
|
65
|
+
* The phase with its slow flag: a wait turns slow only while the wait that
|
|
66
|
+
* outlasted the delay (`slowWait`, a {@link waitKey}) is still the current one,
|
|
67
|
+
* so a new attempt starts without the hint.
|
|
68
|
+
*/
|
|
69
|
+
export declare function withSlowHint(lifecycle: ViewLifecycle, slowWait: string | null, currentWait: string | null): ViewLifecycle;
|
|
70
|
+
/**
|
|
71
|
+
* Where keyboard focus goes after the user pressed retry (the button unmounts
|
|
72
|
+
* as the view starts waiting): the view frame while waiting, the new retry
|
|
73
|
+
* button when the retry failed, the frame again once the view or a
|
|
74
|
+
* cancellation replaced the state. `settled` ends the hand-off.
|
|
75
|
+
*/
|
|
76
|
+
export declare function retryFocusTarget(phase: ViewLifecycle["phase"]): {
|
|
77
|
+
target: "frame" | "retry";
|
|
78
|
+
settled: boolean;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Identity of the current wait, so the slow-hint timer restarts for every new
|
|
82
|
+
* wait (the first load, then each retry attempt) and never for a finished one.
|
|
83
|
+
* `null` when the view is not waiting.
|
|
84
|
+
*/
|
|
85
|
+
export declare function waitKey(lifecycle: ViewLifecycle, retryState: RetryState): string | null;
|
|
86
|
+
/** Default delay before the waiting placeholder adds its slow hint. */
|
|
87
|
+
export declare const DEFAULT_SLOW_HINT_MS = 8000;
|
|
88
|
+
/**
|
|
89
|
+
* A decoded view call (a retry or a refresh), typed so a failure never turns
|
|
90
|
+
* into UI text: `isError` tells a tool error (with its raw `reason`, for the
|
|
91
|
+
* Details disclosure or the console) from a payload that is no view.
|
|
92
|
+
*/
|
|
93
|
+
export type ViewResultOutcome<T> = {
|
|
94
|
+
ok: true;
|
|
95
|
+
data: T;
|
|
96
|
+
} | {
|
|
97
|
+
ok: false;
|
|
98
|
+
isError: boolean;
|
|
99
|
+
reason: string | undefined;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Decode a view call's result: the payload when it is a complete view,
|
|
103
|
+
* otherwise a failure — a tool error with its `isError` text, or a payload
|
|
104
|
+
* the shell cannot render (no reason).
|
|
105
|
+
*/
|
|
106
|
+
export declare function decodeViewResult<T>(result: unknown, isValid: (value: unknown) => value is T): ViewResultOutcome<T>;
|
|
107
|
+
/** A displayable message for anything thrown. */
|
|
108
|
+
export declare function errorMessage(err: unknown): string | undefined;
|
|
109
|
+
//# sourceMappingURL=view-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-lifecycle.d.ts","sourceRoot":"","sources":["../../src/app/view-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `McpAppView` lifecycle as an explicit state machine (toolkit#176).
|
|
3
|
+
*
|
|
4
|
+
* Before the view payload exists the shell is in exactly one phase:
|
|
5
|
+
*
|
|
6
|
+
* waiting ──result──▶ result
|
|
7
|
+
* │ ╲
|
|
8
|
+
* │ ╲──tool error / failed recovery / unrecoverable result──▶ error ──retry──▶ waiting
|
|
9
|
+
* │
|
|
10
|
+
* └──host cancelled──▶ cancelled (terminal: the user stopped it)
|
|
11
|
+
*
|
|
12
|
+
* `waiting` carries a `slow` flag once loading outlasts the slow-hint delay.
|
|
13
|
+
* An `isError` result (or a failed call) is an `error`, never an endless
|
|
14
|
+
* skeleton, and a retry re-runs the originating tool once on the user's click.
|
|
15
|
+
* A latched result that is no view on a host that names no originating tool
|
|
16
|
+
* is an `error` too: nothing could recover it, so waiting would never end.
|
|
17
|
+
* Pure functions only: the hook in `use-view-lifecycle.ts` feeds them.
|
|
18
|
+
*/
|
|
19
|
+
import { parseToolResult } from "../lib/parse-tool-result.js";
|
|
20
|
+
export const RETRY_IDLE = { status: "idle", attempt: 0 };
|
|
21
|
+
/** start → running (next attempt); failed → failed with reason; succeeded → idle. */
|
|
22
|
+
export function retryReducer(state, action) {
|
|
23
|
+
switch (action.type) {
|
|
24
|
+
case "start":
|
|
25
|
+
return { status: "running", attempt: state.attempt + 1 };
|
|
26
|
+
case "failed":
|
|
27
|
+
return { status: "failed", attempt: state.attempt, reason: action.reason };
|
|
28
|
+
case "succeeded":
|
|
29
|
+
return { status: "idle", attempt: state.attempt };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the single phase the view is in. Precedence: a payload always wins;
|
|
34
|
+
* a running retry is waiting; a failed retry is an error with ITS reason; a
|
|
35
|
+
* cancellation is terminal; a failed call, a failed recovery or a latched
|
|
36
|
+
* non-view result nothing can recover is an error; everything else is still
|
|
37
|
+
* waiting.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveViewLifecycle(input) {
|
|
40
|
+
if (input.hasViewData)
|
|
41
|
+
return { phase: "result" };
|
|
42
|
+
const { retryState } = input;
|
|
43
|
+
if (retryState.status === "running")
|
|
44
|
+
return { phase: "waiting", slow: input.slow };
|
|
45
|
+
if (retryState.status === "failed") {
|
|
46
|
+
return { phase: "error", reason: retryState.reason, canRetry: input.canRetry };
|
|
47
|
+
}
|
|
48
|
+
if (input.cancelled)
|
|
49
|
+
return { phase: "cancelled" };
|
|
50
|
+
if (input.callStatus === "error") {
|
|
51
|
+
return { phase: "error", reason: input.callErrorReason, canRetry: input.canRetry };
|
|
52
|
+
}
|
|
53
|
+
if (input.recoveryFailed)
|
|
54
|
+
return { phase: "error", reason: undefined, canRetry: input.canRetry };
|
|
55
|
+
// A latched result without a renderable view: the recovery re-runs the
|
|
56
|
+
// originating tool, so it can only help when the host names that tool.
|
|
57
|
+
if (input.callStatus === "ready" && !input.canRetry) {
|
|
58
|
+
return { phase: "error", reason: undefined, canRetry: false };
|
|
59
|
+
}
|
|
60
|
+
return { phase: "waiting", slow: input.slow };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The phase with its slow flag: a wait turns slow only while the wait that
|
|
64
|
+
* outlasted the delay (`slowWait`, a {@link waitKey}) is still the current one,
|
|
65
|
+
* so a new attempt starts without the hint.
|
|
66
|
+
*/
|
|
67
|
+
export function withSlowHint(lifecycle, slowWait, currentWait) {
|
|
68
|
+
return lifecycle.phase === "waiting" && slowWait !== null && slowWait === currentWait
|
|
69
|
+
? { phase: "waiting", slow: true }
|
|
70
|
+
: lifecycle;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Where keyboard focus goes after the user pressed retry (the button unmounts
|
|
74
|
+
* as the view starts waiting): the view frame while waiting, the new retry
|
|
75
|
+
* button when the retry failed, the frame again once the view or a
|
|
76
|
+
* cancellation replaced the state. `settled` ends the hand-off.
|
|
77
|
+
*/
|
|
78
|
+
export function retryFocusTarget(phase) {
|
|
79
|
+
if (phase === "waiting")
|
|
80
|
+
return { target: "frame", settled: false };
|
|
81
|
+
if (phase === "error")
|
|
82
|
+
return { target: "retry", settled: true };
|
|
83
|
+
return { target: "frame", settled: true };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Identity of the current wait, so the slow-hint timer restarts for every new
|
|
87
|
+
* wait (the first load, then each retry attempt) and never for a finished one.
|
|
88
|
+
* `null` when the view is not waiting.
|
|
89
|
+
*/
|
|
90
|
+
export function waitKey(lifecycle, retryState) {
|
|
91
|
+
return lifecycle.phase === "waiting" ? `${retryState.status}:${retryState.attempt}` : null;
|
|
92
|
+
}
|
|
93
|
+
/** Default delay before the waiting placeholder adds its slow hint. */
|
|
94
|
+
export const DEFAULT_SLOW_HINT_MS = 8000;
|
|
95
|
+
/**
|
|
96
|
+
* Decode a view call's result: the payload when it is a complete view,
|
|
97
|
+
* otherwise a failure — a tool error with its `isError` text, or a payload
|
|
98
|
+
* the shell cannot render (no reason).
|
|
99
|
+
*/
|
|
100
|
+
export function decodeViewResult(result, isValid) {
|
|
101
|
+
let decoded;
|
|
102
|
+
try {
|
|
103
|
+
decoded = parseToolResult(result);
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
return { ok: false, isError: true, reason: errorMessage(err) };
|
|
107
|
+
}
|
|
108
|
+
return isValid(decoded)
|
|
109
|
+
? { ok: true, data: decoded }
|
|
110
|
+
: { ok: false, isError: false, reason: undefined };
|
|
111
|
+
}
|
|
112
|
+
/** A displayable message for anything thrown. */
|
|
113
|
+
export function errorMessage(err) {
|
|
114
|
+
if (err instanceof Error)
|
|
115
|
+
return err.message || undefined;
|
|
116
|
+
if (typeof err === "string")
|
|
117
|
+
return err || undefined;
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=view-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-lifecycle.js","sourceRoot":"","sources":["../../src/app/view-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAW7D,MAAM,CAAC,MAAM,UAAU,GAAe,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAA;AAKpE,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,KAAiB,EAAE,MAAmB;IACjE,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,OAAO;YACV,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,EAAE,CAAA;QAC1D,KAAK,QAAQ;YACX,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;QAC5E,KAAK,WAAW;YACd,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAA;IACrD,CAAC;AACH,CAAC;AA2BD;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAyB;IAC5D,IAAI,KAAK,CAAC,WAAW;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;IACjD,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAA;IAC5B,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAA;IAClF,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAA;IAChF,CAAC;IACD,IAAI,KAAK,CAAC,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAA;IAClD,IAAI,KAAK,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,eAAe,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAA;IACpF,CAAC;IACD,IAAI,KAAK,CAAC,cAAc;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAA;IAChG,uEAAuE;IACvE,uEAAuE;IACvE,IAAI,KAAK,CAAC,UAAU,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;IAC/D,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAA;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAwB,EACxB,QAAuB,EACvB,WAA0B;IAE1B,OAAO,SAAS,CAAC,KAAK,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,WAAW;QACnF,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE;QAClC,CAAC,CAAC,SAAS,CAAA;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA6B;IAI5D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;IACnE,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAChE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,SAAwB,EAAE,UAAsB;IACtE,OAAO,SAAS,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AAC5F,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAA;AAUxC;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAe,EACf,OAAuC;IAEvC,IAAI,OAAgB,CAAA;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,eAAe,CAAU,MAAM,CAAC,CAAA;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAA;IAChE,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC;QACrB,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;QAC7B,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;AACtD,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,IAAI,SAAS,CAAA;IACzD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,IAAI,SAAS,CAAA;IACpD,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
apply?: string;
|
|
5
|
-
cancel?: string;
|
|
6
|
-
reset?: string;
|
|
7
|
-
noProps?: string;
|
|
8
|
-
unsetOption?: string;
|
|
9
|
-
}
|
|
1
|
+
import type { PropsSheetMessages } from "../locale/toolkit-messages.js";
|
|
2
|
+
/** Override strings of the sheet; each defaults to the locale's `propsSheet` catalog. */
|
|
3
|
+
export type WidgetPropsSheetLabels = Partial<PropsSheetMessages>;
|
|
10
4
|
export interface WidgetPropsSheetProps {
|
|
11
5
|
open: boolean;
|
|
12
6
|
onOpenChange: (open: boolean) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget-props-sheet.d.ts","sourceRoot":"","sources":["../../src/app/widget-props-sheet.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"widget-props-sheet.d.ts","sourceRoot":"","sources":["../../src/app/widget-props-sheet.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAiCvE,yFAAyF;AACzF,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;AAIhE,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IAC3C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IAC1C,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAK,IAAI,CAAA;IAC5D,MAAM,CAAC,EAAE,sBAAsB,CAAA;CAChC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,KAAK,EACL,OAAO,EACP,MAAM,GACP,EAAE,qBAAqB,+BA+EvB"}
|
|
@@ -5,18 +5,11 @@ import { Input } from "../primitives/input.js";
|
|
|
5
5
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../primitives/select.js";
|
|
6
6
|
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "../primitives/sheet.js";
|
|
7
7
|
import { Switch } from "../primitives/switch.js";
|
|
8
|
-
|
|
9
|
-
title: "Configure widget",
|
|
10
|
-
description: "Set per-instance props for this widget.",
|
|
11
|
-
apply: "Apply",
|
|
12
|
-
cancel: "Cancel",
|
|
13
|
-
reset: "Reset",
|
|
14
|
-
noProps: "This widget takes no per-instance props.",
|
|
15
|
-
unsetOption: "(unset)",
|
|
16
|
-
};
|
|
8
|
+
import { useToolkitMessages } from "../locale/locale-provider.js";
|
|
17
9
|
const UNSET_SENTINEL = "__unset__";
|
|
18
10
|
export function WidgetPropsSheet({ open, onOpenChange, widgetId, schema, value, onApply, labels, }) {
|
|
19
|
-
const
|
|
11
|
+
const messages = useToolkitMessages();
|
|
12
|
+
const L = { ...messages.propsSheet, ...labels };
|
|
20
13
|
const obj = (schema ?? {});
|
|
21
14
|
const [draft, setDraft] = useState(value ?? {});
|
|
22
15
|
// Reset the form to the saved value on the open→true transition so a
|
|
@@ -41,7 +34,7 @@ export function WidgetPropsSheet({ open, onOpenChange, widgetId, schema, value,
|
|
|
41
34
|
onApply(Object.keys(cleaned).length > 0 ? cleaned : undefined);
|
|
42
35
|
onOpenChange(false);
|
|
43
36
|
};
|
|
44
|
-
return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { className: "w-[400px] sm:max-w-md", children: [_jsxs(SheetHeader, { children: [_jsx(SheetTitle, { children: L.title }), _jsxs(SheetDescription, { children: [_jsx("span", { className: "bg-muted rounded px-1 font-mono text-xs", children: widgetId })
|
|
37
|
+
return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { className: "w-[400px] sm:max-w-md", children: [_jsxs(SheetHeader, { children: [_jsx(SheetTitle, { children: L.title }), _jsxs(SheetDescription, { className: "flex flex-col items-start gap-1", children: [_jsx("span", { children: L.description }), _jsx("span", { className: "bg-muted rounded px-1 font-mono text-xs", children: widgetId })] })] }), _jsx("div", { className: "flex flex-col gap-4 px-4 py-4", children: propEntries.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-sm", children: L.noProps })) : (propEntries.map(([key, prop]) => (_jsx(PropertyField, { name: key, prop: prop, value: draft[key], unsetLabel: L.unsetOption, unsupportedLabel: L.unsupportedType, onChange: (v) => setDraft((prev) => {
|
|
45
38
|
if (v === undefined) {
|
|
46
39
|
const rest = {};
|
|
47
40
|
for (const [k, val] of Object.entries(prev)) {
|
|
@@ -53,7 +46,7 @@ export function WidgetPropsSheet({ open, onOpenChange, widgetId, schema, value,
|
|
|
53
46
|
return { ...prev, [key]: v };
|
|
54
47
|
}) }, key)))) }), _jsxs("div", { className: "flex items-center justify-end gap-2 border-t px-4 py-3", children: [_jsx(Button, { variant: "ghost", onClick: () => setDraft({}), children: L.reset }), _jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), children: L.cancel }), _jsx(Button, { onClick: handleApply, children: L.apply })] })] }) }));
|
|
55
48
|
}
|
|
56
|
-
function PropertyField({ name, prop, value, unsetLabel, onChange, }) {
|
|
49
|
+
function PropertyField({ name, prop, value, unsetLabel, unsupportedLabel, onChange, }) {
|
|
57
50
|
const id = `prop-${name}`;
|
|
58
51
|
if (prop.type === "string" && Array.isArray(prop.enum)) {
|
|
59
52
|
const options = prop.enum.filter((v) => typeof v === "string");
|
|
@@ -79,7 +72,7 @@ function PropertyField({ name, prop, value, unsetLabel, onChange, }) {
|
|
|
79
72
|
const current = value === true;
|
|
80
73
|
return (_jsx(FieldShell, { id: id, name: name, description: prop.description, children: _jsx(Switch, { id: id, checked: current, onCheckedChange: (checked) => onChange(checked || undefined) }) }));
|
|
81
74
|
}
|
|
82
|
-
return (_jsx(FieldShell, { id: id, name: name, description: prop.description, children:
|
|
75
|
+
return (_jsx(FieldShell, { id: id, name: name, description: prop.description, children: _jsx("p", { className: "text-muted-foreground text-xs italic", children: unsupportedLabel(prop.type ?? "?") }) }));
|
|
83
76
|
}
|
|
84
77
|
function FieldShell({ id, name, description, children, }) {
|
|
85
78
|
return (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("label", { htmlFor: id, className: "text-sm font-medium", children: name }), children, description ? _jsx("p", { className: "text-muted-foreground text-xs", children: description }) : null] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget-props-sheet.js","sourceRoot":"","sources":["../../src/app/widget-props-sheet.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EACL,MAAM,EACN,aAAa,EACb,UAAU,EACV,aAAa,EACb,WAAW,GACZ,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,KAAK,EACL,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,UAAU,GACX,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"widget-props-sheet.js","sourceRoot":"","sources":["../../src/app/widget-props-sheet.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import { Component, type ComponentType, type ReactNode, type ErrorInfo } from "react";
|
|
2
2
|
import type { LayoutConfig, PipelineContext, WidgetProps } from "@miragon/mcp-toolkit-core";
|
|
3
3
|
export type WidgetComponent = ComponentType<WidgetProps>;
|
|
4
|
+
/**
|
|
5
|
+
* True when two reset-key lists differ (length or any entry by identity).
|
|
6
|
+
* Exported for tests: it decides when a crashed widget gets a fresh render.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resetKeysChanged(prev: readonly unknown[] | undefined, next: readonly unknown[] | undefined): boolean;
|
|
4
9
|
/**
|
|
5
10
|
* Catches render-time crashes from a single widget so one broken widget
|
|
6
11
|
* can't take down the entire iframe view (or the builder canvas/preview).
|
|
7
12
|
*
|
|
13
|
+
* The fallback is localized, names what happened, keeps the raw error under
|
|
14
|
+
* "Details" and offers a retry. The boundary resets itself when its
|
|
15
|
+
* `resetKeys` change, so new data (a refresh, a new tool result, a builder
|
|
16
|
+
* edit) gets a fresh render instead of a latched failure (toolkit#176 N24).
|
|
17
|
+
* When a retry crashes again, keyboard focus moves to the new retry button
|
|
18
|
+
* instead of falling back to the document (the pressed one unmounted). After
|
|
19
|
+
* a retry that renders, the widget's own markup is unknown here, so focus
|
|
20
|
+
* returns to the document.
|
|
21
|
+
*
|
|
8
22
|
* Exported so the visual builder's canvas + preview render sites reuse the
|
|
9
23
|
* same isolation the rendered `WidgetRenderer` already had — every place a
|
|
10
24
|
* widget component is rendered goes through {@link RenderedWidget}, which
|
|
@@ -13,18 +27,39 @@ export type WidgetComponent = ComponentType<WidgetProps>;
|
|
|
13
27
|
export declare class WidgetErrorBoundary extends Component<{
|
|
14
28
|
widgetId: string;
|
|
15
29
|
children: ReactNode;
|
|
30
|
+
resetKeys?: readonly unknown[];
|
|
16
31
|
}, {
|
|
17
32
|
error: Error | null;
|
|
18
33
|
}> {
|
|
19
34
|
state: {
|
|
20
35
|
error: Error | null;
|
|
21
36
|
};
|
|
37
|
+
/** Set by the user's retry; consumed by the next update. */
|
|
38
|
+
private retryFocusOwed;
|
|
39
|
+
private readonly fallbackRef;
|
|
22
40
|
static getDerivedStateFromError(error: Error): {
|
|
23
41
|
error: Error;
|
|
24
42
|
};
|
|
25
43
|
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
44
|
+
componentDidUpdate(prevProps: {
|
|
45
|
+
resetKeys?: readonly unknown[];
|
|
46
|
+
}): void;
|
|
47
|
+
reset: () => void;
|
|
48
|
+
/** The fallback's retry: a reset that keeps keyboard focus if the widget crashes again. */
|
|
49
|
+
retry: () => void;
|
|
26
50
|
render(): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
|
|
27
51
|
}
|
|
52
|
+
/** The localized crash fallback of {@link WidgetErrorBoundary}. */
|
|
53
|
+
export declare function WidgetCrashFallback({ widgetId, error, onRetry, }: {
|
|
54
|
+
widgetId: string;
|
|
55
|
+
error: Error;
|
|
56
|
+
onRetry: () => void;
|
|
57
|
+
}): import("react").JSX.Element;
|
|
58
|
+
/** A layout cell names a widget the bundle does not contain: say so, quietly. */
|
|
59
|
+
export declare function UnavailableWidget({ widgetId, className, }: {
|
|
60
|
+
widgetId: string;
|
|
61
|
+
className?: string;
|
|
62
|
+
}): import("react").JSX.Element;
|
|
28
63
|
/**
|
|
29
64
|
* True when the pipeline context carries no widget data at all — no step
|
|
30
65
|
* results and no keys. A widget rendered against an empty context typically
|
|
@@ -40,7 +75,7 @@ export declare function contextHasNoData(context: PipelineContext): boolean;
|
|
|
40
75
|
* The single render site for a layout cell's widget, shared across the
|
|
41
76
|
* rendered view (`RowsRenderer`), the builder canvas, and the builder
|
|
42
77
|
* preview so all three isolate crashes identically:
|
|
43
|
-
* - missing component → "not
|
|
78
|
+
* - missing component → a localized "not available in this version" note,
|
|
44
79
|
* - render crash → caught by {@link WidgetErrorBoundary} (Finding [1]),
|
|
45
80
|
* - (builder only, opt-in) empty pipeline context → a dezent
|
|
46
81
|
* "no data yet" hint (Finding [4]).
|
|
@@ -83,5 +118,10 @@ export interface WidgetRendererProps {
|
|
|
83
118
|
*/
|
|
84
119
|
widgets: Record<string, WidgetComponent>;
|
|
85
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* The pipeline context widgets read. `WidgetRenderer` rebuilds it only when
|
|
123
|
+
* the view data changes — its identity is the error boundaries' reset key.
|
|
124
|
+
*/
|
|
125
|
+
export declare function buildPipelineContext(keys: Record<string, unknown>, stepData: WidgetRendererProps["stepData"], errors: WidgetRendererProps["errors"]): PipelineContext;
|
|
86
126
|
export declare function WidgetRenderer({ layout, keys, stepData, errors, widgets }: WidgetRendererProps): import("react").JSX.Element;
|
|
87
127
|
//# sourceMappingURL=widget-renderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget-renderer.d.ts","sourceRoot":"","sources":["../../src/app/widget-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"widget-renderer.d.ts","sourceRoot":"","sources":["../../src/app/widget-renderer.tsx"],"names":[],"mappings":"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"}
|