@jini-ai/ui 0.6.15-rc.2 → 0.6.15
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/dist/browser/useDismissOnOutsideOrEscape.js +1 -1
- package/dist/browser/useGlobalKeydown.js +2 -2
- package/dist/browser/useModalWindowDragGuard.js +1 -1
- package/dist/core/theme/css-name.d.ts +3 -0
- package/dist/core/theme/css-name.js +5 -0
- package/dist/core/theme/stylesheet.js +2 -1
- package/dist/core/theme/validation.js +15 -4
- package/dist/features/about/rules.js +2 -1
- package/dist/features/admin-widgets/components/InfoTip.hooks.js +22 -12
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.js +1 -1
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.js +1 -1
- package/dist/features/admin-widgets/components/SeeMore/SeeMore.hooks.js +2 -2
- package/dist/features/admin-widgets/components/SeeMore/SeeMore.js +4 -2
- package/dist/features/admin-widgets/components/Select/Select.hooks.js +2 -1
- package/dist/features/admin-widgets/components/Select/Select.js +2 -1
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.js +4 -2
- package/dist/features/admin-widgets/components/useDebouncedHtmlPreview.hooks.js +3 -2
- package/dist/features/asset-grid/react/components/AssetGrid.js +8 -3
- package/dist/features/asset-grid/react/hooks/useAssetGridKeyboardShortcuts.js +7 -6
- package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.js +8 -10
- package/dist/features/asset-grid/react/hooks/useRubberBandDrag.js +1 -1
- package/dist/features/asset-tree-browser/react/components/AssetTreeFileRow.js +6 -8
- package/dist/features/asset-tree-browser/react/hooks/useAssetTreeRowMenu.js +1 -1
- package/dist/features/asset-tree-browser/rules.js +1 -3
- package/dist/features/browser-chrome/rules.js +10 -8
- package/dist/features/charts/browser.js +2 -1
- package/dist/features/charts/react.js +3 -1
- package/dist/features/connectors/ConnectorsBrowser.js +3 -1
- package/dist/features/connectors/hooks/useConnectorAuthorization.js +1 -1
- package/dist/features/connectors/hooks/useConnectorCatalog.js +2 -2
- package/dist/features/connectors/rules.js +10 -14
- package/dist/features/execution/react/components/AgentDiagnosticRow.js +2 -0
- package/dist/features/execution/react/components/ByokProviderForm.js +1 -3
- package/dist/features/execution/react/components/LocalCliAgentSettings.js +2 -1
- package/dist/features/execution/react/hooks/use-byok-field-validation.hooks.js +6 -2
- package/dist/features/execution/react/hooks/useExecutionTab.js +9 -5
- package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +3 -6
- package/dist/features/execution/react/hooks/useReasoningControl.js +3 -3
- package/dist/features/execution/rules.js +23 -18
- package/dist/features/external-mcp/react/components/ExternalMcpTab.js +10 -1
- package/dist/features/file-dropzone/rules.js +3 -2
- package/dist/features/html-editor/canvas-embed-placeholders.js +2 -3
- package/dist/features/html-editor/css.js +7 -5
- package/dist/features/html-editor/editor-blocks.js +60 -6
- package/dist/features/html-editor/protected-elements.js +5 -3
- package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +3 -3
- package/dist/features/html-editor/source-splice.js +6 -4
- package/dist/features/iframe-pool/react/components/IframeKeepAliveProvider.js +5 -5
- package/dist/features/iframe-pool/react/dom-sync.js +2 -2
- package/dist/features/integrations/react/components/IntegrationsTab.js +3 -1
- package/dist/features/integrations/rules.js +6 -4
- package/dist/features/interactive-ui/providers/shadcn/data-table.js +10 -5
- package/dist/features/interactive-ui/table-data.js +1 -1
- package/dist/features/lexical-rich-text-editor/deserialize.js +2 -2
- package/dist/features/lexical-rich-text-editor/mention-parser.js +4 -4
- package/dist/features/lexical-rich-text-editor/react/components/RichTextInput.js +2 -1
- package/dist/features/lexical-rich-text-editor/react/hooks/useCaretFloatingLayerPosition.js +1 -1
- package/dist/features/lexical-rich-text-editor/react/hooks/useMentionColorStamping.js +1 -1
- package/dist/features/lexical-rich-text-editor/serialize.js +13 -10
- package/dist/features/list-detail-panel/react/components/ListDetailPanel.js +1 -1
- package/dist/features/mcp-ui/confirmation-store.js +3 -6
- package/dist/features/mcp-ui/surfaces/confirmation.d.ts +5 -0
- package/dist/features/mcp-ui/surfaces/confirmation.js +1 -0
- package/dist/features/mcp-ui/surfaces/document.d.ts +3 -15
- package/dist/features/mcp-ui/surfaces/document.js +37 -6
- package/dist/features/mcp-ui/surfaces/fields.js +2 -0
- package/dist/features/mcp-ui/surfaces/host-theme.js +2 -1
- package/dist/features/mcp-ui/surfaces/index.d.ts +1 -0
- package/dist/features/mcp-ui/surfaces/index.js +1 -0
- package/dist/features/mcp-ui/surfaces/outcome.js +1 -1
- package/dist/features/mcp-ui/surfaces/select.js +2 -1
- package/dist/features/mcp-ui/surfaces/structured-details.d.ts +40 -0
- package/dist/features/mcp-ui/surfaces/structured-details.js +159 -0
- package/dist/features/mcp-ui/surfaces/text-input.js +1 -1
- package/dist/features/mcp-ui/surfaces/tool-approval.d.ts +21 -0
- package/dist/features/mcp-ui/surfaces/tool-approval.js +41 -0
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +2 -1
- package/dist/features/memory/async-commit-guard.js +4 -1
- package/dist/features/memory/formatters.js +5 -1
- package/dist/features/memory/react/components/MemoryConnectedPanel.js +3 -1
- package/dist/features/memory/react/components/MemoryEntryCard.js +1 -1
- package/dist/features/memory/react/components/MemorySettingsPanel.js +3 -1
- package/dist/features/memory/react/hooks/useMemoryConfig.hooks.js +12 -10
- package/dist/features/memory/react/hooks/useMemoryConnectors.hooks.js +2 -5
- package/dist/features/memory/react/hooks/useMemoryConnectors.rules.js +10 -9
- package/dist/features/memory/react/hooks/useMemoryEntries.hooks.js +4 -2
- package/dist/features/memory/react/hooks/useMemoryFlash.hooks.js +1 -1
- package/dist/features/memory/rules.js +2 -1
- package/dist/features/panel-kit/fetch-query/adapter.react.js +3 -2
- package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +3 -2
- package/dist/features/panel-kit/fetch-query/binding.react.js +2 -1
- package/dist/features/panel-kit/helpers/standing-draft-recovery-message.js +13 -4
- package/dist/features/panel-kit/hooks/use-dirty-guard.hooks.js +1 -1
- package/dist/features/panel-kit/hooks/use-focus-trap.hooks.js +1 -1
- package/dist/features/panel-kit/hooks/use-settings-slice.hooks.js +14 -10
- package/dist/features/panel-kit/hooks/use-standing-draft-autosave.hooks.js +2 -2
- package/dist/features/progress-card/components/ProgressCard.d.ts +1 -1
- package/dist/features/progress-card/reference-adapters.js +23 -13
- package/dist/features/progress-card/rules.d.ts +0 -1
- package/dist/features/progress-card/rules.js +14 -20
- package/dist/features/progress-card/types.d.ts +1 -1
- package/dist/features/project-locations/dependencies.js +6 -1
- package/dist/features/project-locations/react/components/ProjectLocationsTab.js +2 -1
- package/dist/features/project-locations/rules.js +2 -1
- package/dist/features/resource-dashboard/react/components/ResourceBoardToolbar.js +8 -1
- package/dist/features/resource-dashboard/react/components/ResourceCardParts.js +2 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListItem.js +3 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.js +2 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListView.js +1 -1
- package/dist/features/resource-dashboard/react/hooks/useResourceBoard.js +1 -1
- package/dist/features/schedule-picker/rules.js +13 -7
- package/dist/features/sketch-editor/constants.d.ts +0 -6
- package/dist/features/sketch-editor/constants.js +17 -15
- package/dist/features/sketch-editor/dom.js +4 -7
- package/dist/features/sketch-editor/react/components/SketchMainMenu.js +2 -1
- package/dist/features/sketch-editor/react/components/SketchSaveStateBadge.js +2 -1
- package/dist/features/sketch-editor/react/hooks/useSketchDomEnhancements.js +1 -1
- package/dist/features/sketch-editor/rules.js +13 -12
- package/dist/features/skills/dependencies.js +9 -4
- package/dist/features/skills/react/components/SkillRow.js +2 -1
- package/dist/features/skills/react/components/SkillsTab.js +2 -1
- package/dist/features/skills/rules.js +3 -3
- package/dist/features/source-config-list/agent-handles.js +4 -3
- package/dist/features/source-config-list/react/components/SourceConfigItemCard.js +3 -1
- package/dist/features/tab-strip/react/components/TabBar.hooks.js +4 -2
- package/dist/features/version-manager/react/components/VersionPreviewFrame.js +4 -1
- package/dist/features/version-manager/react/components/VersionSidebar.js +8 -6
- package/dist/features/version-manager/react/hooks/usePreviewCanvasSize.js +1 -1
- package/dist/features/version-manager/react/hooks/useVersionManager.js +5 -7
- package/dist/features/version-manager/rules.js +3 -5
- package/dist/features/viewer-shell/react/components/CommentSidePanel.js +2 -1
- package/dist/features/viewer-shell/react/components/SegmentedToggle.js +2 -1
- package/dist/features/viewer-shell/react/components/ViewerShell.js +2 -1
- package/dist/features/viewer-shell/rules.js +8 -7
- package/dist/react/components/BrandLogo.js +10 -2
- package/dist/react/components/CustomSelect.js +1 -1
- package/dist/react/components/EditorIcon.js +17 -14
- package/dist/react/components/Loading.js +2 -1
- package/dist/react/components/OnboardingChipField.js +5 -1
- package/dist/react/components/OnboardingDropdown.js +6 -4
- package/dist/react/components/PaletteTweaks.js +7 -6
- package/dist/react/components/PillButton.js +2 -1
- package/dist/react/components/PopoverMenu.js +2 -1
- package/dist/react/components/RemixIcon.js +2 -1
- package/dist/react/components/SecretInput.hooks.d.ts +2 -25
- package/dist/react/components/SecretInput.hooks.js +2 -24
- package/dist/react/components/SecretInput.js +5 -4
- package/dist/react/components/Toast.js +4 -2
- package/dist/react/components/TooltipLayer.js +4 -1
- package/dist/react/components/WorkingDirPicker.js +5 -4
- package/dist/react/components/remixicon-font-recovery.js +9 -1
- package/dist/react/components/select-popover.js +2 -2
- package/dist/react/hooks/useBrandFonts.js +1 -1
- package/dist/react/hooks/useEdgeAutoScroll.js +1 -1
- package/dist/react/hooks/useInView.js +9 -9
- package/dist/react/hooks/useResizableSplitPane.js +12 -20
- package/dist/react/mcp-ui/useHostSurfaceTokens.js +1 -1
- package/dist/renderers/annotation-canvas/react/components/AnnotationCanvas.js +7 -1
- package/dist/renderers/annotation-canvas/react/hooks/useAnnotationCanvas.controller.js +4 -2
- package/dist/renderers/annotation-canvas/react/hooks/useAnnotationCanvas.js +9 -5
- package/dist/renderers/annotation-canvas/rules.js +9 -13
- package/dist/renderers/annotation-canvas/theme.js +5 -2
- package/dist/renderers/renderers/index.js +1 -1
- package/dist/renderers/renderers/markdown.js +4 -6
- package/dist/theme/apply.js +7 -3
- package/dist/utils/class-names.d.ts +3 -0
- package/dist/utils/class-names.js +5 -0
- package/dist/utils/design-md.js +3 -3
- package/dist/utils/ime-composing.d.ts +1 -1
- package/dist/utils/ime-composing.js +1 -2
- package/dist/utils/localized-url.js +2 -11
- package/dist/utils/markdown-scroll-sync.js +1 -1
- package/dist/utils/omit-keys.d.ts +3 -0
- package/dist/utils/omit-keys.js +8 -0
- package/dist/utils/polygon-selection.js +1 -1
- package/dist/utils/sse.js +3 -0
- package/dist/utils/trim-chars.d.ts +13 -0
- package/dist/utils/trim-chars.js +30 -0
- package/dist/utils/unhandled-case.d.ts +10 -0
- package/dist/utils/unhandled-case.js +12 -0
- package/dist/utils/unit-bezier.js +1 -3
- package/dist/utils/zip.js +6 -10
- package/package.json +10 -9
|
@@ -25,7 +25,7 @@ export interface ProgressCardData {
|
|
|
25
25
|
* 'indeterminate' (both always compute a percentage) — it's included as a
|
|
26
26
|
* forward-looking capability for Jini's own Run/Agent/Tool dashboards. */
|
|
27
27
|
progress: number | 'indeterminate';
|
|
28
|
-
/** The primary step/
|
|
28
|
+
/** The primary step/to-do checklist. */
|
|
29
29
|
steps: ProgressCardItem[];
|
|
30
30
|
/** An optional secondary list, e.g. "files touched" by an agent run. */
|
|
31
31
|
secondaryItems?: ProgressCardItem[];
|
|
@@ -6,6 +6,11 @@ const DEFAULT_BUILT_IN = {
|
|
|
6
6
|
builtIn: true,
|
|
7
7
|
};
|
|
8
8
|
let nextFakeId = 1;
|
|
9
|
+
function takeFakeId() {
|
|
10
|
+
const id = `fake-location-${nextFakeId}`;
|
|
11
|
+
nextFakeId += 1;
|
|
12
|
+
return id;
|
|
13
|
+
}
|
|
9
14
|
/**
|
|
10
15
|
* An in-memory test/demo double. Per this package's established convention
|
|
11
16
|
* (see `execution/dependencies.ts`, `integrations/dependencies.ts`), ships a
|
|
@@ -30,7 +35,7 @@ export function createFakeProjectLocationsPort(options = {}) {
|
|
|
30
35
|
saveLocations(drafts) {
|
|
31
36
|
const builtIn = locations.filter((location) => location.builtIn);
|
|
32
37
|
const nextExternal = drafts.map((draft) => ({
|
|
33
|
-
id: draft.id ??
|
|
38
|
+
id: draft.id ?? takeFakeId(),
|
|
34
39
|
name: draft.path.split(/[\\/]/).filter(Boolean).pop() || draft.path,
|
|
35
40
|
path: draft.path,
|
|
36
41
|
}));
|
|
@@ -56,7 +56,8 @@ export function ProjectLocationsTab({ port, defaultLocationId, onDefaultLocation
|
|
|
56
56
|
return null;
|
|
57
57
|
}
|
|
58
58
|
})();
|
|
59
|
-
const
|
|
59
|
+
const errorNoticeByStatus = { 'save-error': saveErrorLabel, 'scan-error': scanErrorLabel };
|
|
60
|
+
const errorNotice = errorNoticeByStatus[result.status] ?? null;
|
|
60
61
|
return (_jsxs("section", { className: "jini-settings-section jini-settings-project-locations", children: [_jsx("div", { className: "jini-section-head", children: _jsxs("div", { children: [_jsx("h4", { children: title }), _jsx("p", { className: "jini-hint", children: description })] }) }), builtIn ? (_jsxs("div", { className: "jini-project-location-card jini-project-location-card-built-in", children: [_jsxs("div", { className: "jini-project-location-card-main", children: [_jsx("strong", { children: builtInLabel }), _jsx("code", { children: builtIn.path })] }), _jsxs("label", { className: "jini-project-location-default-control", children: [_jsx("input", { type: "radio", name: "jini-project-location-default", checked: effectiveDefaultLocationId === builtIn.id, onChange: () => setDefaultLocationId(builtIn.id) }), _jsx("span", { children: defaultControlLabel(effectiveDefaultLocationId === builtIn.id) })] })] })) : null, _jsx("div", { className: "jini-project-location-list", children: drafts.map((draft, index) => (_jsxs("div", { className: "jini-project-location-card", children: [_jsxs("div", { className: "jini-project-location-card-main", children: [_jsx("strong", { children: locationLabel(draft.path) }), _jsx("code", { children: draft.path }), _jsx("small", { className: "jini-hint", children: rowHint })] }), draft.id ? (_jsxs("label", { className: "jini-project-location-default-control", children: [_jsx("input", { type: "radio", name: "jini-project-location-default", checked: effectiveDefaultLocationId === draft.id, onChange: () => setDefaultLocationId(draft.id) }), _jsx("span", { children: defaultControlLabel(effectiveDefaultLocationId === draft.id) })] })) : null, _jsxs("button", { type: "button", className: "jini-button jini-button-ghost", onClick: () => removeDraft(index), disabled: saving, children: [_jsx(Icon, { name: "trash", size: 13 }), _jsx("span", { children: deleteLabel })] })] }, `${draft.id ?? 'new'}-${index}`))) }), _jsxs("button", { type: "button", className: "jini-button jini-button-ghost", onClick: addFolder, disabled: saving, children: [_jsx(Icon, { name: "plus", size: 12 }), _jsx("span", { children: addFolderLabel })] }), notice ? (_jsx("p", { className: "jini-hint", role: "status", children: notice })) : null, errorNotice ? (_jsx("p", { className: "jini-hint jini-hint-error", role: "alert", children: errorNotice })) : null] }));
|
|
61
62
|
}
|
|
62
63
|
//# sourceMappingURL=ProjectLocationsTab.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { trimTrailingChars } from '../../utils/trim-chars.js';
|
|
1
2
|
/**
|
|
2
3
|
* The id meaning "the host's own default root".
|
|
3
4
|
*
|
|
@@ -77,6 +78,6 @@ function normalizePathForCompare(value) {
|
|
|
77
78
|
const trimmed = value.trim();
|
|
78
79
|
if (trimmed.length <= 1)
|
|
79
80
|
return trimmed;
|
|
80
|
-
return trimmed
|
|
81
|
+
return trimTrailingChars(trimmed, '\\/') || trimmed;
|
|
81
82
|
}
|
|
82
83
|
//# sourceMappingURL=rules.js.map
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** The select-mode bar while selecting, otherwise the button that enters select mode. */
|
|
3
|
+
function ResourceBoardSelectControls({ selectMode, selectedCount, bulkDeleteBusy, onEnterSelectMode, onExitSelectMode, onBulkDelete, selectModeLabel, selectedCountLabel, deleteSelectedLabel, cancelSelectLabel, }) {
|
|
4
|
+
if (!selectMode) {
|
|
5
|
+
return (_jsx("button", { type: "button", className: "resource-board-select-toggle", onClick: onEnterSelectMode, children: selectModeLabel }));
|
|
6
|
+
}
|
|
7
|
+
return (_jsxs("div", { className: "resource-board-select-bar", role: "group", children: [_jsx("span", { className: "resource-board-select-count", children: selectedCountLabel(selectedCount) }), _jsx("button", { type: "button", disabled: selectedCount === 0 || bulkDeleteBusy, onClick: onBulkDelete, children: deleteSelectedLabel }), _jsx("button", { type: "button", onClick: onExitSelectMode, children: cancelSelectLabel })] }));
|
|
8
|
+
}
|
|
2
9
|
/**
|
|
3
10
|
* DesignsTab's toolbar: sub-tab sort pills + a create button + search +
|
|
4
11
|
* select-mode/bulk-delete bar (grid view only) + the grid/kanban view
|
|
@@ -9,6 +16,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
9
16
|
*/
|
|
10
17
|
export function ResourceBoardToolbar({ sortOptions, activeSort, onSortChange, sortAriaLabel, query, onQueryChange, searchPlaceholder, viewMode, onViewModeChange, viewToggleAriaLabel, gridViewLabel, kanbanViewLabel, enableBulkDelete, selectMode, selectedCount, bulkDeleteBusy, onEnterSelectMode, onExitSelectMode, onBulkDelete, selectModeLabel, selectedCountLabel, deleteSelectedLabel, cancelSelectLabel, createLabel, onCreate, }) {
|
|
11
18
|
const showSelectControls = enableBulkDelete && viewMode === 'grid';
|
|
12
|
-
return (_jsxs("div", { className: "resource-board-toolbar", children: [_jsx("div", { className: "resource-board-toolbar-left", children: sortOptions.length > 0 ? (_jsx("div", { className: "resource-board-sort-pill", role: "group", "aria-label": sortAriaLabel, children: sortOptions.map((option) => (_jsx("button", { type: "button", "aria-pressed": activeSort === option.value, className: activeSort === option.value ? 'active' : '', onClick: () => onSortChange(option.value), children: option.label }, option.value))) })) : null }), _jsxs("div", { className: "resource-board-toolbar-right", children: [onCreate && createLabel ? (_jsx("button", { type: "button", className: "resource-board-create-button", onClick: onCreate, children: createLabel })) : null, _jsx("div", { className: "resource-board-search", children: _jsx("input", { placeholder: searchPlaceholder, value: query, onChange: (event) => onQueryChange(event.target.value) }) }), showSelectControls ? (
|
|
19
|
+
return (_jsxs("div", { className: "resource-board-toolbar", children: [_jsx("div", { className: "resource-board-toolbar-left", children: sortOptions.length > 0 ? (_jsx("div", { className: "resource-board-sort-pill", role: "group", "aria-label": sortAriaLabel, children: sortOptions.map((option) => (_jsx("button", { type: "button", "aria-pressed": activeSort === option.value, className: activeSort === option.value ? 'active' : '', onClick: () => onSortChange(option.value), children: option.label }, option.value))) })) : null }), _jsxs("div", { className: "resource-board-toolbar-right", children: [onCreate && createLabel ? (_jsx("button", { type: "button", className: "resource-board-create-button", onClick: onCreate, children: createLabel })) : null, _jsx("div", { className: "resource-board-search", children: _jsx("input", { placeholder: searchPlaceholder, value: query, onChange: (event) => onQueryChange(event.target.value) }) }), showSelectControls ? (_jsx(ResourceBoardSelectControls, { selectMode: selectMode, selectedCount: selectedCount, bulkDeleteBusy: bulkDeleteBusy, onEnterSelectMode: onEnterSelectMode, onExitSelectMode: onExitSelectMode, onBulkDelete: onBulkDelete, selectModeLabel: selectModeLabel, selectedCountLabel: selectedCountLabel, deleteSelectedLabel: deleteSelectedLabel, cancelSelectLabel: cancelSelectLabel })) : null, _jsxs("div", { className: "resource-board-view-pill", role: "group", "aria-label": viewToggleAriaLabel, children: [_jsx("button", { "aria-pressed": viewMode === 'grid', className: viewMode === 'grid' ? 'active' : '', title: gridViewLabel, onClick: () => onViewModeChange('grid'), children: gridViewLabel }), _jsx("button", { "aria-pressed": viewMode === 'kanban', className: viewMode === 'kanban' ? 'active' : '', title: kanbanViewLabel, onClick: () => onViewModeChange('kanban'), children: kanbanViewLabel })] })] })] }));
|
|
13
20
|
}
|
|
14
21
|
//# sourceMappingURL=ResourceBoardToolbar.js.map
|
|
@@ -29,6 +29,7 @@ export function ResourceCardMenu({ menuActions, menuOpen, busy, moreLabel, menuC
|
|
|
29
29
|
}
|
|
30
30
|
/** Title, optional subtitle, and the status badge (only when the item has a status AND a pre-translated label). */
|
|
31
31
|
export function ResourceCardMeta({ item, statusLabel, toneMap, }) {
|
|
32
|
-
|
|
32
|
+
const toneMapProps = toneMap ? { toneMap } : {};
|
|
33
|
+
return (_jsxs("div", { className: "resource-board-card-meta", children: [_jsx("div", { className: "resource-board-card-title", title: item.title, children: item.title }), item.subtitle ? _jsx("div", { className: "resource-board-card-subtitle", children: item.subtitle }) : null, item.status && statusLabel ? _jsx(StatusPill, { status: item.status, label: statusLabel, ...toneMapProps }) : null] }));
|
|
33
34
|
}
|
|
34
35
|
//# sourceMappingURL=ResourceCardParts.js.map
|
|
@@ -9,6 +9,8 @@ import { ResourceRunHistoryList } from './ResourceRunHistoryList.js';
|
|
|
9
9
|
* `ResourceRunHistoryList` sublist.
|
|
10
10
|
*/
|
|
11
11
|
export function ResourceRowListItem({ row, busy, statusLabel, toneMap, canExpandHistory, expanded, showHistoryLabel, hideHistoryLabel, historyItems, historyLoading, historyTitleLabel, historyLoadingLabel, historyEmptyLabel, onToggleExpand, onAction, onHistoryItemAction, }) {
|
|
12
|
-
|
|
12
|
+
const toneMapProps = toneMap ? { toneMap } : {};
|
|
13
|
+
const historyActionProps = onHistoryItemAction ? { onAction: onHistoryItemAction } : {};
|
|
14
|
+
return (_jsxs("li", { className: `resource-row-list-item${row.paused ? ' is-paused' : ''}`, "data-testid": "resource-row-list-item", children: [_jsx("div", { className: "resource-row-list-item-main", children: _jsx(ResourceRowListItemContent, { row: row, statusLabel: statusLabel, toneMap: toneMap }) }), _jsx(ResourceRowListItemActions, { row: row, busy: busy, canExpandHistory: canExpandHistory, expanded: expanded, showHistoryLabel: showHistoryLabel, hideHistoryLabel: hideHistoryLabel, onToggleExpand: onToggleExpand, onAction: onAction }), expanded ? (_jsx(ResourceRunHistoryList, { items: historyItems, loading: historyLoading, titleLabel: historyTitleLabel, loadingLabel: historyLoadingLabel, emptyLabel: historyEmptyLabel, statusLabel: statusLabel, ...toneMapProps, ...historyActionProps })) : null] }));
|
|
13
15
|
}
|
|
14
16
|
//# sourceMappingURL=ResourceRowListItem.js.map
|
|
@@ -2,7 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { StatusPill } from './StatusPill.js';
|
|
3
3
|
/** Title/meta/detail lines plus the last-run `StatusPill` + label of one `ResourceRowListItem`. */
|
|
4
4
|
export function ResourceRowListItemContent({ row, statusLabel, toneMap, }) {
|
|
5
|
-
|
|
5
|
+
const toneMapProps = toneMap ? { toneMap } : {};
|
|
6
|
+
return (_jsxs("div", { className: "resource-row-list-item-content", children: [_jsx("span", { className: "resource-row-list-item-title", children: row.title }), row.metaLine ? _jsx("span", { className: "resource-row-list-item-meta", children: row.metaLine }) : null, row.detailLine ? _jsx("span", { className: "resource-row-list-item-detail", children: row.detailLine }) : null, row.lastRunStatus ? (_jsxs("span", { className: "resource-row-list-item-last-run", children: [_jsx(StatusPill, { status: row.lastRunStatus, label: statusLabel(row.lastRunStatus), ...toneMapProps }), row.lastRunLabel ? _jsx("span", { children: row.lastRunLabel }) : null] })) : null] }));
|
|
6
7
|
}
|
|
7
8
|
/** Always-visible inline action buttons (never a kebab menu, unlike `ResourceCard`) plus the optional history-expand toggle. */
|
|
8
9
|
export function ResourceRowListItemActions({ row, busy, canExpandHistory, expanded, showHistoryLabel, hideHistoryLabel, onToggleExpand, onAction, }) {
|
|
@@ -13,6 +13,6 @@ import { ResourceRowListAlerts, ResourceRowListEmpty, ResourceRowListHero, Resou
|
|
|
13
13
|
export function ResourceRowListView(props) {
|
|
14
14
|
const { loading, rows, sectionLabel, loadingLabel } = props;
|
|
15
15
|
const isEmpty = !loading && rows.length === 0;
|
|
16
|
-
return (_jsxs("section", { className: "resource-row-list", children: [_jsx(ResourceRowListHero, { ...props }), _jsx(ResourceRowListAlerts, { ...props }), _jsxs("section", { className: "resource-row-list-saved", "aria-label": sectionLabel, children: [_jsxs("div", { className: "resource-row-list-section-head", children: [_jsx("h2", { children: sectionLabel }), loading ? _jsx("span", { className: "resource-row-list-section-meta", children: loadingLabel }) : null] }), isEmpty ? _jsx(ResourceRowListEmpty, { ...props }) : rows.length > 0 ? _jsx(ResourceRowListRows, { ...props }) : null] })] }));
|
|
16
|
+
return (_jsxs("section", { className: "resource-row-list", children: [_jsx(ResourceRowListHero, { ...props }), _jsx(ResourceRowListAlerts, { ...props }), _jsxs("section", { className: "resource-row-list-saved", "aria-label": sectionLabel, children: [_jsxs("div", { className: "resource-row-list-section-head", children: [_jsx("h2", { children: sectionLabel }), loading ? _jsx("span", { className: "resource-row-list-section-meta", children: loadingLabel }) : null] }), isEmpty ? _jsx(ResourceRowListEmpty, { ...props }) : null, rows.length > 0 ? _jsx(ResourceRowListRows, { ...props }) : null] })] }));
|
|
17
17
|
}
|
|
18
18
|
//# sourceMappingURL=ResourceRowListView.js.map
|
|
@@ -76,7 +76,7 @@ export function useResourceBoard(params) {
|
|
|
76
76
|
// same guard DesignsTab's own `menuContainerRef`-based effect uses.
|
|
77
77
|
useEffect(() => {
|
|
78
78
|
if (!openMenuId)
|
|
79
|
-
return;
|
|
79
|
+
return undefined;
|
|
80
80
|
const onKey = (event) => {
|
|
81
81
|
if (event.key === 'Escape')
|
|
82
82
|
setOpenMenuId(null);
|
|
@@ -23,8 +23,12 @@ export function formatTime12h(time) {
|
|
|
23
23
|
const h = Number(m[1]);
|
|
24
24
|
const mm = m[2];
|
|
25
25
|
const suffix = h >= 12 ? 'PM' : 'AM';
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
return `${to12Hour(h)}:${mm} ${suffix}`;
|
|
27
|
+
}
|
|
28
|
+
function to12Hour(h) {
|
|
29
|
+
if (h === 0)
|
|
30
|
+
return 12;
|
|
31
|
+
return h > 12 ? h - 12 : h;
|
|
28
32
|
}
|
|
29
33
|
function weekdayLongName(weekday, weekdays) {
|
|
30
34
|
return weekdays.find((w) => w.value === weekday)?.long ?? weekdays[0]?.long ?? 'Sunday';
|
|
@@ -39,11 +43,13 @@ export function decomposeSchedule(schedule, weekdays = DEFAULT_WEEKDAYS) {
|
|
|
39
43
|
if (schedule.kind === 'hourly') {
|
|
40
44
|
return { kind: 'hourly', minute: String(schedule.minute).padStart(2, '0') };
|
|
41
45
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
let freq;
|
|
47
|
+
if (schedule.kind === 'daily')
|
|
48
|
+
freq = 'Daily';
|
|
49
|
+
else if (schedule.kind === 'weekdays')
|
|
50
|
+
freq = 'Weekdays';
|
|
51
|
+
else
|
|
52
|
+
freq = weekdayLongName(schedule.weekday, weekdays);
|
|
47
53
|
return { kind: 'timed', freq, time: formatTime12h(schedule.time), tz: schedule.timezone };
|
|
48
54
|
}
|
|
49
55
|
/** Plain-English one-line summary, e.g. `'Hourly at :05'` or
|
|
@@ -2,12 +2,6 @@ import type { SketchTooltipTarget } from './types.js';
|
|
|
2
2
|
export declare const SAVED_VISIBLE_MS = 2000;
|
|
3
3
|
export declare const EXPORTED_IMAGE_MIME_TYPE = "image/png";
|
|
4
4
|
export declare const SKETCH_CONTEXT_MENU_MARGIN = 8;
|
|
5
|
-
/**
|
|
6
|
-
* Default tool/menu tooltip targets — these selectors and `data-testid`
|
|
7
|
-
* values are Excalidraw's own toolbar markup, not host-product content.
|
|
8
|
-
* Host-overridable via `SketchEditorProps.tooltipTargets` for a forked or
|
|
9
|
-
* newer Excalidraw build with different markup.
|
|
10
|
-
*/
|
|
11
5
|
export declare const DEFAULT_SKETCH_TOOLTIP_TARGETS: readonly SketchTooltipTarget[];
|
|
12
6
|
/**
|
|
13
7
|
* Default context-menu action allow-list + order. These are Excalidraw's
|
|
@@ -7,23 +7,25 @@ export const SKETCH_CONTEXT_MENU_MARGIN = 8;
|
|
|
7
7
|
* Host-overridable via `SketchEditorProps.tooltipTargets` for a forked or
|
|
8
8
|
* newer Excalidraw build with different markup.
|
|
9
9
|
*/
|
|
10
|
+
/** Anchor the tooltip on the toolbar button's wrapping `<label>`. */
|
|
11
|
+
const CLOSEST_LABEL = 'closest-label';
|
|
10
12
|
export const DEFAULT_SKETCH_TOOLTIP_TARGETS = [
|
|
11
13
|
{ selector: '[data-testid="main-menu-trigger"]', label: 'mainMenu', placement: 'bottom' },
|
|
12
|
-
{ selector: '[data-testid="toolbar-lock"]', target:
|
|
13
|
-
{ selector: '[data-testid="toolbar-hand"]', target:
|
|
14
|
-
{ selector: '[data-testid="toolbar-selection"]', target:
|
|
15
|
-
{ selector: '[data-testid="toolbar-rectangle"]', target:
|
|
16
|
-
{ selector: '[data-testid="toolbar-diamond"]', target:
|
|
17
|
-
{ selector: '[data-testid="toolbar-ellipse"]', target:
|
|
18
|
-
{ selector: '[data-testid="toolbar-arrow"]', target:
|
|
19
|
-
{ selector: '[data-testid="toolbar-line"]', target:
|
|
20
|
-
{ selector: '[data-testid="toolbar-freedraw"]', target:
|
|
21
|
-
{ selector: '[data-testid="toolbar-text"]', target:
|
|
22
|
-
{ selector: '[data-testid="toolbar-image"]', target:
|
|
23
|
-
{ selector: '[data-testid="toolbar-eraser"]', target:
|
|
24
|
-
{ selector: '[data-testid="toolbar-frame"]', target:
|
|
25
|
-
{ selector: '[data-testid="toolbar-embeddable"]', target:
|
|
26
|
-
{ selector: '[data-testid="toolbar-laser"]', target:
|
|
14
|
+
{ selector: '[data-testid="toolbar-lock"]', target: CLOSEST_LABEL, label: 'lock', placement: 'bottom' },
|
|
15
|
+
{ selector: '[data-testid="toolbar-hand"]', target: CLOSEST_LABEL, label: 'hand', placement: 'bottom' },
|
|
16
|
+
{ selector: '[data-testid="toolbar-selection"]', target: CLOSEST_LABEL, label: 'selection', placement: 'bottom' },
|
|
17
|
+
{ selector: '[data-testid="toolbar-rectangle"]', target: CLOSEST_LABEL, label: 'rectangle', placement: 'bottom' },
|
|
18
|
+
{ selector: '[data-testid="toolbar-diamond"]', target: CLOSEST_LABEL, label: 'diamond', placement: 'bottom' },
|
|
19
|
+
{ selector: '[data-testid="toolbar-ellipse"]', target: CLOSEST_LABEL, label: 'ellipse', placement: 'bottom' },
|
|
20
|
+
{ selector: '[data-testid="toolbar-arrow"]', target: CLOSEST_LABEL, label: 'arrow', placement: 'bottom' },
|
|
21
|
+
{ selector: '[data-testid="toolbar-line"]', target: CLOSEST_LABEL, label: 'line', placement: 'bottom' },
|
|
22
|
+
{ selector: '[data-testid="toolbar-freedraw"]', target: CLOSEST_LABEL, label: 'freedraw', placement: 'bottom' },
|
|
23
|
+
{ selector: '[data-testid="toolbar-text"]', target: CLOSEST_LABEL, label: 'text', placement: 'bottom' },
|
|
24
|
+
{ selector: '[data-testid="toolbar-image"]', target: CLOSEST_LABEL, label: 'image', placement: 'bottom' },
|
|
25
|
+
{ selector: '[data-testid="toolbar-eraser"]', target: CLOSEST_LABEL, label: 'eraser', placement: 'bottom' },
|
|
26
|
+
{ selector: '[data-testid="toolbar-frame"]', target: CLOSEST_LABEL, label: 'frame', placement: 'bottom' },
|
|
27
|
+
{ selector: '[data-testid="toolbar-embeddable"]', target: CLOSEST_LABEL, label: 'embeddable', placement: 'bottom' },
|
|
28
|
+
{ selector: '[data-testid="toolbar-laser"]', target: CLOSEST_LABEL, label: 'laser', placement: 'bottom' },
|
|
27
29
|
{ selector: '.App-toolbar__extra-tools-trigger', label: 'moreTools', placement: 'bottom' },
|
|
28
30
|
];
|
|
29
31
|
/**
|
|
@@ -109,18 +109,15 @@ function hasRecognizedContextMenuAction(menu, recognized) {
|
|
|
109
109
|
function pruneContextMenuItems(menu, allowed) {
|
|
110
110
|
const byAction = new Map();
|
|
111
111
|
for (const child of Array.from(menu.children)) {
|
|
112
|
-
if (child instanceof HTMLHRElement)
|
|
112
|
+
if (child instanceof HTMLHRElement)
|
|
113
113
|
child.remove();
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
114
|
if (!(child instanceof HTMLLIElement))
|
|
117
115
|
continue;
|
|
118
116
|
const actionName = child.getAttribute('data-testid') ?? '';
|
|
119
|
-
if (
|
|
117
|
+
if (allowed.has(actionName))
|
|
118
|
+
byAction.set(actionName, child);
|
|
119
|
+
else
|
|
120
120
|
child.remove();
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
byAction.set(actionName, child);
|
|
124
121
|
}
|
|
125
122
|
return byAction;
|
|
126
123
|
}
|
|
@@ -2,7 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Icon } from '../../../../react/components/Icon.js';
|
|
3
3
|
/** The composed `<MainMenu>` Excalidraw renders inside its own menu popover. */
|
|
4
4
|
export function SketchMainMenu({ MainMenu, t, saving, showSaved, canSave, onSave, exportAvailable, exporting, canExport, onExportImage, canClear, onClear, }) {
|
|
5
|
-
const
|
|
5
|
+
const idleSaveLabel = showSaved ? t('Saved') : t('Save');
|
|
6
|
+
const saveLabel = saving ? t('Saving…') : idleSaveLabel;
|
|
6
7
|
const exportLabel = exporting ? t('Exporting image…') : t('Export image');
|
|
7
8
|
return (_jsxs(MainMenu, { children: [_jsx(MainMenu.Item, { "data-testid": "sketch-menu-save", icon: showSaved ? _jsx(Icon, { name: "check", size: 16 }) : undefined, onClick: onSave, disabled: saving || !canSave, "aria-label": saveLabel, children: saveLabel }), exportAvailable ? (_jsx(MainMenu.Item, { "data-testid": "sketch-menu-export-image", icon: _jsx(Icon, { name: "download", size: 16 }), onClick: onExportImage, disabled: exporting || !canExport, "aria-label": exportLabel, children: exportLabel })) : null, _jsx(MainMenu.Separator, {}), _jsx(MainMenu.DefaultItems.SearchMenu, {}), _jsx(MainMenu.DefaultItems.Help, {}), _jsx(MainMenu.Item, { "data-testid": "sketch-menu-clear", icon: _jsx(Icon, { name: "trash", size: 16 }), onClick: onClear, disabled: !canClear, children: t('Clear canvas') }), _jsx(MainMenu.Separator, {}), _jsx(MainMenu.DefaultItems.ChangeCanvasBackground, {})] }));
|
|
8
9
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Icon } from '../../../../react/components/Icon.js';
|
|
3
|
+
const STATE_ICONS = { saving: 'spinner', dirty: 'alert-triangle' };
|
|
3
4
|
/** The small save-state indicator rendered in Excalidraw's own top-right UI slot. */
|
|
4
5
|
export function SketchSaveStateBadge({ state, label }) {
|
|
5
|
-
return (_jsx("div", { className: "sketch-excalidraw-actions", "data-testid": "sketch-save-state", children: _jsxs("span", { className: `sketch-save-state is-${state}`, role: "status", "aria-live": "polite", children: [_jsx(Icon, { name: state
|
|
6
|
+
return (_jsx("div", { className: "sketch-excalidraw-actions", "data-testid": "sketch-save-state", children: _jsxs("span", { className: `sketch-save-state is-${state}`, role: "status", "aria-live": "polite", children: [_jsx(Icon, { name: STATE_ICONS[state] ?? 'check', size: 12, className: state === 'saving' ? 'icon-spin' : undefined }), _jsx("span", { children: label })] }) }));
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=SketchSaveStateBadge.js.map
|
|
@@ -16,7 +16,7 @@ export function useSketchDomEnhancements({ containerRef, t, domTextOverrides, to
|
|
|
16
16
|
useEffect(() => {
|
|
17
17
|
const root = containerRef.current;
|
|
18
18
|
if (!root)
|
|
19
|
-
return;
|
|
19
|
+
return undefined;
|
|
20
20
|
let frame = null;
|
|
21
21
|
const applyEnhancements = () => {
|
|
22
22
|
frame = null;
|
|
@@ -136,12 +136,15 @@ export function exportedImageFileName(fileName, sourceExtension) {
|
|
|
136
136
|
const slash = fileName.lastIndexOf('/');
|
|
137
137
|
const baseName = slash >= 0 ? fileName.slice(slash + 1) : fileName;
|
|
138
138
|
const stem = typeof sourceExtension === 'string'
|
|
139
|
-
? baseName
|
|
140
|
-
? baseName.slice(0, baseName.length - sourceExtension.length)
|
|
141
|
-
: baseName
|
|
139
|
+
? stripKnownExtension(baseName, sourceExtension)
|
|
142
140
|
: baseName.replace(/\.[^./]+$/, '');
|
|
143
141
|
return `${stem || 'sketch'}.png`;
|
|
144
142
|
}
|
|
143
|
+
function stripKnownExtension(baseName, extension) {
|
|
144
|
+
return baseName.toLowerCase().endsWith(extension.toLowerCase())
|
|
145
|
+
? baseName.slice(0, baseName.length - extension.length)
|
|
146
|
+
: baseName;
|
|
147
|
+
}
|
|
145
148
|
export function exportedImageResultFileName(result, fallback) {
|
|
146
149
|
if (result && typeof result === 'object' && typeof result.fileName === 'string') {
|
|
147
150
|
return result.fileName;
|
|
@@ -197,15 +200,13 @@ export function buildSketchTooltipLabels(t) {
|
|
|
197
200
|
* in `overrides` matches (caller should leave the node untouched).
|
|
198
201
|
*/
|
|
199
202
|
export function translateDomTextValue(value, overrides) {
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
const
|
|
207
|
-
const core = match[2];
|
|
208
|
-
const trailing = match[3];
|
|
203
|
+
// Split into leading whitespace, core, trailing whitespace (an all-whitespace
|
|
204
|
+
// value is all leading). `trimStart`/`trimEnd` strip exactly regex `\s`.
|
|
205
|
+
const coreStart = value.length - value.trimStart().length;
|
|
206
|
+
const leading = value.slice(0, coreStart);
|
|
207
|
+
const rest = value.slice(coreStart);
|
|
208
|
+
const core = rest.trimEnd();
|
|
209
|
+
const trailing = rest.slice(core.length);
|
|
209
210
|
const normalized = core.replace(/\s+/g, ' ').trim();
|
|
210
211
|
if (!normalized)
|
|
211
212
|
return null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { omitKeys } from '../../utils/omit-keys.js';
|
|
1
2
|
const DEFAULT_FAKE_SKILLS = [
|
|
2
3
|
{
|
|
3
4
|
id: 'skill-summarize',
|
|
@@ -10,9 +11,13 @@ const DEFAULT_FAKE_SKILLS = [
|
|
|
10
11
|
},
|
|
11
12
|
];
|
|
12
13
|
let nextFakeId = 1;
|
|
14
|
+
function takeFakeSkillId() {
|
|
15
|
+
const id = `fake-skill-${nextFakeId}`;
|
|
16
|
+
nextFakeId += 1;
|
|
17
|
+
return id;
|
|
18
|
+
}
|
|
13
19
|
function toSummary(detail) {
|
|
14
|
-
|
|
15
|
-
return summary;
|
|
20
|
+
return omitKeys(detail, ['body']);
|
|
16
21
|
}
|
|
17
22
|
/**
|
|
18
23
|
* An in-memory test/demo double. Per this package's established convention
|
|
@@ -39,7 +44,7 @@ export function createFakeSkillsPort(options = {}) {
|
|
|
39
44
|
return delay([...(files.get(id) ?? [])]);
|
|
40
45
|
},
|
|
41
46
|
createSkill(payload) {
|
|
42
|
-
const id =
|
|
47
|
+
const id = takeFakeSkillId();
|
|
43
48
|
const detail = {
|
|
44
49
|
id,
|
|
45
50
|
name: payload.name,
|
|
@@ -58,7 +63,7 @@ export function createFakeSkillsPort(options = {}) {
|
|
|
58
63
|
return Promise.reject(new Error(`Unknown skill: ${id}`));
|
|
59
64
|
// A built-in edit writes a NEW user-owned shadow copy, same as the
|
|
60
65
|
// origin — the requested id is never mutated in place.
|
|
61
|
-
const targetId = existing.source === 'user' ? id :
|
|
66
|
+
const targetId = existing.source === 'user' ? id : takeFakeSkillId();
|
|
62
67
|
const detail = {
|
|
63
68
|
...existing,
|
|
64
69
|
id: targetId,
|
|
@@ -18,7 +18,8 @@ export function SkillRow({ skill, locale, enabled, expanded, editing, body, body
|
|
|
18
18
|
// Built-in skills are never edited in place — "editing" one creates a
|
|
19
19
|
// user-owned override, so every edit affordance says so.
|
|
20
20
|
const editActionLabel = builtIn ? l.overrideCreateLabel : l.editLabel;
|
|
21
|
-
|
|
21
|
+
const editFormHandleProps = agentHandle ? { agentHandle: agentSubHandle({ base: agentHandle, action: 'edit-form' }) } : {};
|
|
22
|
+
return (_jsxs("div", { className: skillRowClassName({ enabled, expanded }), "data-testid": `skill-row-${skill.id}`, children: [_jsxs("div", { className: "jini-skills-row-head", children: [_jsx(SkillRowSummaryButton, { skill: skill, locale: locale, expanded: expanded, onToggleExpanded: onToggleExpanded, labels: l, agentHandle: agentHandle }), _jsxs("div", { className: "jini-skills-row-actions", children: [isDeletableSkill(skill) && confirmDelete ? (_jsx(SkillRowDeleteConfirm, { onCommitDelete: onCommitDelete, onCancelDelete: onCancelDelete, labels: l, agentHandle: agentHandle })) : (_jsx(SkillRowEditDeleteActions, { skill: skill, editActionLabel: editActionLabel, onStartEdit: onStartEdit, onArmDelete: onArmDelete, labels: l, agentHandle: agentHandle })), _jsxs("label", { className: "toggle-switch toggle-switch-sm jini-skills-row-enable", title: l.enableToggleLabel, children: [_jsx("input", { type: "checkbox", checked: enabled, onChange: (event) => onToggleEnabled(event.target.checked), "aria-label": l.enableToggleLabel, ...agentHandleProps({}, { base: agentHandle, action: 'enabled', role: 'checkbox', label: l.enableToggleLabel }) }), _jsx("span", { className: "toggle-slider" })] })] })] }), confirmBuiltInEdit ? (_jsx(SkillRowBuiltInEditWarning, { onCancelBuiltInEdit: onCancelBuiltInEdit, onConfirmBuiltInEdit: onConfirmBuiltInEdit, labels: l, agentHandle: agentHandle })) : null, expanded && !editing ? (_jsx(SkillRowDetail, { body: body, bodyLoading: bodyLoading, files: files, filesLoading: filesLoading, labels: l })) : null, editing && draft ? (_jsx(SkillDraftForm, { heading: editActionLabel, subheading: skill.id, draft: draft, onDraftChange: onDraftChange, error: draftError, saving: draftSaving, isEdit: true, isBuiltInOverride: builtIn, onCancel: onCancelEdit, onSubmit: onSubmitEdit, labels: labels, ...editFormHandleProps })) : null] }));
|
|
22
23
|
}
|
|
23
24
|
function skillRowClassName({ enabled, expanded }) {
|
|
24
25
|
return `jini-skills-row${enabled ? '' : ' jini-skills-row-disabled'}${expanded ? ' jini-skills-row-expanded' : ''}`;
|
|
@@ -21,7 +21,8 @@ export function SkillsTab({ port, disabledSkillIds, onToggleEnabled, locale = 'e
|
|
|
21
21
|
const tab = useSkillsTab({ port, locale });
|
|
22
22
|
const l = resolveLabels({ defaults: DEFAULT_SKILLS_TAB_LABELS, t }, { labels });
|
|
23
23
|
const loadErrorLabel = labels?.loadErrorLabel ?? t('Could not load skills: {error}', { error: tab.loadError ?? '' });
|
|
24
|
-
|
|
24
|
+
const createFormHandleProps = agentHandle ? { agentHandle: agentSubHandle({ base: agentHandle, action: 'create-form' }) } : {};
|
|
25
|
+
return (_jsxs("section", { className: "jini-settings-section jini-settings-skills", children: [_jsx(SkillsTabToolbar, { tab: tab, labels: l, agentHandle: agentHandle }), tab.loadError ? (_jsx("div", { className: "jini-empty-card jini-empty-card-error", children: _jsx("strong", { children: loadErrorLabel }) })) : null, tab.creating ? (_jsx(SkillDraftForm, { heading: l.newSkillLabel, draft: tab.draft, onDraftChange: tab.setDraft, error: tab.draftError, saving: tab.draftSaving, isEdit: false, onCancel: tab.cancelDraft, onSubmit: tab.submitDraft, labels: labels, ...createFormHandleProps })) : null, !tab.loading && tab.filteredSkills.length === 0 ? (_jsx("div", { className: "jini-empty-card", children: _jsx("strong", { children: l.noResultsLabel }) })) : (_jsx(SkillsTabRows, { tab: tab, disabledSkillIds: disabledSkillIds, onToggleEnabled: onToggleEnabled, locale: locale, labels: labels, agentHandle: agentHandle }))] }));
|
|
25
26
|
}
|
|
26
27
|
/** Search box, "New skill" button, and the source/mode/(category) selects. */
|
|
27
28
|
function SkillsTabToolbar({ tab, labels: l, agentHandle, }) {
|
|
@@ -146,16 +146,16 @@ const modeValue = (skill) => skill.mode;
|
|
|
146
146
|
const categoryValue = (skill) => typeof skill.category === 'string' && skill.category ? skill.category : null;
|
|
147
147
|
/** The data-derived pills (`mode`, `category`): option SET from every skill,
|
|
148
148
|
* COUNTS from `matching` — see `skillFilterOptions`. */
|
|
149
|
-
function valueFilterOptions({ skills, matching, valueOf, }) {
|
|
149
|
+
function valueFilterOptions({ skills, matching, valueOf: valueFor, }) {
|
|
150
150
|
const values = new Set();
|
|
151
151
|
for (const skill of skills) {
|
|
152
|
-
const value =
|
|
152
|
+
const value = valueFor(skill);
|
|
153
153
|
if (value !== null)
|
|
154
154
|
values.add(value);
|
|
155
155
|
}
|
|
156
156
|
const counts = new Map();
|
|
157
157
|
for (const skill of matching) {
|
|
158
|
-
const value =
|
|
158
|
+
const value = valueFor(skill);
|
|
159
159
|
if (value === null)
|
|
160
160
|
continue;
|
|
161
161
|
counts.set(value, (counts.get(value) ?? 0) + 1);
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
* why cards are keyed by id rather than list position.
|
|
40
40
|
*/
|
|
41
41
|
import { agentHandle, buildAgentListHandles } from '@jini-ai/agentic';
|
|
42
|
+
import { trimChars } from '../../utils/trim-chars.js';
|
|
42
43
|
/** Segments of a derived handle: `<base>-field-<key>` and `<base>-<action>` share one joiner. */
|
|
43
44
|
const HANDLE_SEPARATOR = '-';
|
|
44
45
|
/** The namespace every host-described field sits under — see this module's doc for why. */
|
|
@@ -65,11 +66,11 @@ const LIST_ITEM_NAMESPACE = 'item';
|
|
|
65
66
|
* @complexity O(n) in `segment.length`.
|
|
66
67
|
*/
|
|
67
68
|
function sanitizeHandleSegment(segment) {
|
|
68
|
-
|
|
69
|
+
const separated = segment
|
|
69
70
|
.replace(/([a-z0-9])([A-Z])/g, `$1${HANDLE_SEPARATOR}$2`)
|
|
70
71
|
.toLowerCase()
|
|
71
|
-
.replace(/[^a-z0-9]+/g, HANDLE_SEPARATOR)
|
|
72
|
-
|
|
72
|
+
.replace(/[^a-z0-9]+/g, HANDLE_SEPARATOR);
|
|
73
|
+
return trimChars(separated, '-');
|
|
73
74
|
}
|
|
74
75
|
/**
|
|
75
76
|
* The handle for one action or sub-control published under `base`.
|
|
@@ -122,7 +122,9 @@ function useItemCardEdit({ source, fieldSpecs, onUpdate }) {
|
|
|
122
122
|
/** The expanded body: the Edit/Save/Cancel toggle, the editable or read-only fields, and the test control. */
|
|
123
123
|
function ItemCardBody(props) {
|
|
124
124
|
const { capabilities, testing, testResult, onTest, agentHandle, edit } = props;
|
|
125
|
-
|
|
125
|
+
const testResultProps = testResult ? { result: testResult } : {};
|
|
126
|
+
const testHandleProps = agentHandle ? { agentHandle: sourceConfigActionHandle(agentHandle, 'test') } : {};
|
|
127
|
+
return (_jsxs("div", { className: "source-config-item-card-body", children: [capabilities.canUpdate ? _jsx(ItemCardEditToggle, { ...props, edit: edit }) : null, edit.editing ? _jsx(ItemCardEditFields, { ...props, edit: edit }) : _jsx(ItemCardReadOnlyFields, { ...props }), capabilities.canTest ? (_jsx(SourceConfigTestControl, { running: testing, disabled: isAnyActionPending(props), onTest: onTest, ...testResultProps, ...testHandleProps })) : null] }));
|
|
126
128
|
}
|
|
127
129
|
function ItemCardEditToggle(props) {
|
|
128
130
|
const { updating, agentHandle, edit } = props;
|
|
@@ -138,9 +138,11 @@ export function useActiveTabInView({ activeId }, _optional = {}) {
|
|
|
138
138
|
const tabBox = tab.getBoundingClientRect();
|
|
139
139
|
// A host's end padding (e.g. room for an edge fade) counts as off-screen.
|
|
140
140
|
const visibleRight = stripBox.right - (parseFloat(getComputedStyle(strip).paddingRight) || 0);
|
|
141
|
-
if (tabBox.left < stripBox.left)
|
|
141
|
+
if (tabBox.left < stripBox.left) {
|
|
142
142
|
strip.scrollLeft += tabBox.left - stripBox.left;
|
|
143
|
-
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (tabBox.right > visibleRight)
|
|
144
146
|
strip.scrollLeft += tabBox.right - visibleRight;
|
|
145
147
|
}
|
|
146
148
|
scrollActiveTabIntoView();
|
|
@@ -11,6 +11,9 @@ export function VersionPreviewFrame({ previewDocument, frameReady, onFrameLoad,
|
|
|
11
11
|
const [frameRef, canvasSize] = usePreviewCanvasSize();
|
|
12
12
|
const preset = findViewportPreset(viewportPresets, viewport);
|
|
13
13
|
const scale = effectivePreviewScale(preset, 1, canvasSize, DEFAULT_PREVIEW_CANVAS_PADDING);
|
|
14
|
-
|
|
14
|
+
const showEmpty = !previewDocument && !loading && !loadingContent;
|
|
15
|
+
const showLoading = loading || loadingContent || (previewDocument && !frameReady);
|
|
16
|
+
const emptyState = showEmpty ? _jsx("div", { className: "jini-viewer-empty", children: t('No preview available.') }) : null;
|
|
17
|
+
return (_jsx("div", { className: "jini-version-preview", ref: frameRef, children: error ? (_jsx("div", { className: "jini-viewer-empty", role: "alert", children: error })) : (_jsxs(_Fragment, { children: [previewDocument ? (_jsx("div", { className: "jini-preview-viewport", style: previewViewportStyle(preset, scale, 1), children: _jsx("div", { className: "jini-preview-frame-clip", children: _jsx("div", { style: previewScaleShellStyle(preset, 1), children: _jsx("iframe", { title: title, sandbox: "allow-scripts allow-downloads", srcDoc: previewDocument, onLoad: onFrameLoad }) }) }) })) : null, emptyState, showLoading ? (_jsx("div", { className: "jini-version-preview-overlay", role: "status", "aria-label": t('Loading preview…'), children: _jsx("span", { className: "jini-version-preview-spinner", "aria-hidden": "true" }) })) : null] })) }));
|
|
15
18
|
}
|
|
16
19
|
//# sourceMappingURL=VersionPreviewFrame.js.map
|
|
@@ -4,11 +4,13 @@ import { useT } from '../../../i18n/index.js';
|
|
|
4
4
|
* independent of whatever the preview pane is doing. */
|
|
5
5
|
export function VersionSidebar({ countLabel, search, onSearchChange, showSearch, loading, versions, visibleVersions, selectedVersionId, onSelect, onPrefetch, formatDate, sourceLabel, sourceClassName, restoredFrom, }) {
|
|
6
6
|
const t = useT();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
const noResultsMessage = visibleVersions.length === 0 ? t('No results for “{query}”.', { query: search.trim() }) : null;
|
|
8
|
+
const emptyMessage = versions.length === 0 ? t('No versions yet.') : noResultsMessage;
|
|
9
|
+
return (_jsxs("div", { className: "jini-version-sidebar", children: [_jsx("div", { className: "jini-version-sidebar-head", children: _jsx("span", { className: "jini-version-count", children: countLabel }) }), showSearch ? (_jsxs("div", { className: "jini-version-search", children: [_jsx("input", { type: "search", value: search, onChange: (event) => onSearchChange(event.target.value), placeholder: t('Search…'), "aria-label": t('Search…') }), search ? (_jsx("button", { type: "button", className: "jini-version-search-clear", "aria-label": t('Clear'), onClick: () => onSearchChange(''), children: t('Clear') })) : null] })) : null, _jsxs("div", { className: "jini-version-list", role: "listbox", "aria-label": t('Version history'), children: [loading ? (_jsx("div", { className: "jini-version-skeleton-list", role: "status", "aria-label": t('Loading versions…'), children: [0, 1, 2, 3].map((row) => (_jsx("div", { className: "jini-version-skeleton-item", "aria-hidden": "true" }, row))) })) : null, !loading && emptyMessage ? _jsx("div", { className: "jini-version-empty", children: emptyMessage }) : null, !loading && !emptyMessage ? (visibleVersions.map((version) => {
|
|
10
|
+
const selected = version.id === selectedVersionId;
|
|
11
|
+
const itemRestoredFrom = restoredFrom(version);
|
|
12
|
+
const prefetch = () => onPrefetch(version.id);
|
|
13
|
+
return (_jsxs("button", { type: "button", className: `jini-version-item${selected ? ' active' : ''}`, role: "option", "aria-selected": selected, onClick: () => onSelect(version.id), onMouseEnter: prefetch, onFocus: prefetch, children: [_jsxs("span", { className: "jini-version-item-top", children: [version.current ? _jsx("span", { className: "jini-version-current-badge", children: t('Current') }) : null, _jsx("span", { className: `jini-version-source-badge ${sourceClassName(version)}`, children: sourceLabel(version) }), _jsx("span", { className: "jini-version-time", children: formatDate(version) })] }), _jsx("span", { className: "jini-version-item-title", children: version.prompt || version.label || t('Version {version}', { version: version.version }) }), _jsxs("span", { className: "jini-version-item-meta", children: [t('Version {version}', { version: version.version }), itemRestoredFrom ? (_jsx("span", { className: "jini-version-item-restored", children: t('Restored from v{version}', { version: itemRestoredFrom.version }) })) : null] })] }, version.id));
|
|
14
|
+
})) : null] })] }));
|
|
13
15
|
}
|
|
14
16
|
//# sourceMappingURL=VersionSidebar.js.map
|
|
@@ -16,7 +16,7 @@ export function usePreviewCanvasSize() {
|
|
|
16
16
|
// dead-branch-gets-refactored-away rule.
|
|
17
17
|
const el = ref.current;
|
|
18
18
|
if (!el)
|
|
19
|
-
return;
|
|
19
|
+
return undefined;
|
|
20
20
|
const measure = () => {
|
|
21
21
|
const rect = el.getBoundingClientRect();
|
|
22
22
|
setSize({ width: rect.width, height: rect.height });
|
|
@@ -108,10 +108,8 @@ export function useVersionManager(dependencies, options) {
|
|
|
108
108
|
setVersions(nextVersions);
|
|
109
109
|
const currentVersion = nextVersions.find((version) => version.current);
|
|
110
110
|
seedCurrentVersionContent({ currentVersion, currentContent, contentCache: contentCacheRef.current });
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
nextVersions[0] ??
|
|
114
|
-
null;
|
|
111
|
+
const preferredVersion = preferredId ? nextVersions.find((version) => version.id === preferredId) : null;
|
|
112
|
+
const nextSelected = preferredVersion ?? currentVersion ?? nextVersions[0] ?? null;
|
|
115
113
|
setSelectedId(nextSelected?.id ?? null);
|
|
116
114
|
setLoading(false);
|
|
117
115
|
}, [port, fileRef, currentContent]);
|
|
@@ -125,7 +123,7 @@ export function useVersionManager(dependencies, options) {
|
|
|
125
123
|
if (!selectedId) {
|
|
126
124
|
setSelectedContent(null);
|
|
127
125
|
setSelectedContentVersionId(null);
|
|
128
|
-
return;
|
|
126
|
+
return undefined;
|
|
129
127
|
}
|
|
130
128
|
const cached = contentCacheRef.current.get(selectedId);
|
|
131
129
|
if (cached !== undefined) {
|
|
@@ -138,7 +136,7 @@ export function useVersionManager(dependencies, options) {
|
|
|
138
136
|
else {
|
|
139
137
|
setError(null);
|
|
140
138
|
}
|
|
141
|
-
return;
|
|
139
|
+
return undefined;
|
|
142
140
|
}
|
|
143
141
|
// Cache miss: keep the previous preview mounted (don't clear
|
|
144
142
|
// `selectedContent`) so switching versions never blanks to empty while
|
|
@@ -177,7 +175,7 @@ export function useVersionManager(dependencies, options) {
|
|
|
177
175
|
// is ever missed.
|
|
178
176
|
useEffect(() => {
|
|
179
177
|
if (!previewDocument || loadedPreviewDocument === previewDocument)
|
|
180
|
-
return;
|
|
178
|
+
return undefined;
|
|
181
179
|
const fallback = setTimeout(() => setLoadedPreviewDocument(previewDocument), PREVIEW_LOAD_FALLBACK_MS);
|
|
182
180
|
return () => clearTimeout(fallback);
|
|
183
181
|
}, [previewDocument, loadedPreviewDocument]);
|