@jini-ai/ui 0.6.15-rc.2 → 0.6.16
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/CHANGELOG.md +12 -0
- 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/core.d.ts +1 -1
- package/dist/core.js +1 -1
- 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/appearance/constants.d.ts +28 -1
- package/dist/features/appearance/constants.js +12 -9
- package/dist/features/appearance/react/components/AppearanceTab.js +4 -4
- 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/contract.d.ts +4 -4
- package/dist/features/charts/react.js +5 -3
- package/dist/features/charts/wire.d.ts +19 -0
- package/dist/features/charts/wire.js +20 -2
- 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/constants.js +0 -1
- 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/folder-path-drop/rules.d.ts +2 -3
- package/dist/features/folder-path-drop/rules.js +3 -4
- 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/i18n/dictionaries/settings-dialog.ar.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.bn.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.de.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.en.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.es.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fa.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fr.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hi.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hu.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.id.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.it.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ko.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pl.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ru.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.th.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.tr.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.uk.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ur.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +8 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +8 -0
- 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/checkbox.d.ts +2 -0
- package/dist/features/mcp-ui/surfaces/choice-group.d.ts +2 -0
- package/dist/features/mcp-ui/surfaces/choice-group.js +2 -2
- 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 +14 -16
- package/dist/features/mcp-ui/surfaces/document.js +46 -7
- package/dist/features/mcp-ui/surfaces/fields.d.ts +7 -1
- package/dist/features/mcp-ui/surfaces/fields.js +14 -11
- package/dist/features/mcp-ui/surfaces/form.js +6 -1
- 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.d.ts +2 -0
- 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.d.ts +2 -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 +42 -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/AgentIcon.js +0 -1
- 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/agent-icon-data-uris.generated.js +0 -1
- 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/renderers/shiki.js +7 -1
- 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 +32 -29
|
@@ -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]);
|
|
@@ -89,11 +89,9 @@ export function filterVersionsBySearch(versions, search, describe) {
|
|
|
89
89
|
* current, no restoring mid-fetch, no restoring stale/mismatched content). */
|
|
90
90
|
export function isRestoreDisabled(input) {
|
|
91
91
|
const { selectedVersion, restoring, loadingContent, selectedContentMatchesVersion } = input;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
loadingContent ||
|
|
96
|
-
!selectedContentMatchesVersion);
|
|
92
|
+
if (!selectedVersion || selectedVersion.current)
|
|
93
|
+
return true;
|
|
94
|
+
return restoring || loadingContent || !selectedContentMatchesVersion;
|
|
97
95
|
}
|
|
98
96
|
/** Whether the currently-loaded preview content actually corresponds to the
|
|
99
97
|
* currently-selected version (guards against acting on stale content
|
|
@@ -113,7 +113,8 @@ function CommentSideSelectBar({ selectedCount, sending, sendDisabled, queueOnSen
|
|
|
113
113
|
const t = useT();
|
|
114
114
|
if (selectedCount === 0)
|
|
115
115
|
return null;
|
|
116
|
-
|
|
116
|
+
const idleSendLabel = queueOnSend ? t('Queue') : t('Send to chat');
|
|
117
|
+
return (_jsxs("div", { className: "comment-side-selectbar", "data-testid": "comment-side-selectbar", children: [_jsx("span", { className: "comment-side-selectcount", children: t('{n} selected', { n: selectedCount }) }), _jsx("button", { type: "button", className: "comment-side-clear", onClick: onClearSelection, children: t('Clear') }), _jsx("button", { type: "button", className: "comment-side-send", "data-testid": "comment-side-send-claude", disabled: sending || sendDisabled, onClick: () => void onSendSelected(), children: sending ? t('Sending…') : idleSendLabel })] }));
|
|
117
118
|
}
|
|
118
119
|
function CommentSideCreateForm({ renderCreateForm, draft, onDraftChange, onCreateComment, sending, sendDisabled, }) {
|
|
119
120
|
const t = useT();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { RemixIcon } from '../../../../react/components/RemixIcon.js';
|
|
3
|
+
import { withClassName } from '../../../../utils/class-names.js';
|
|
3
4
|
/**
|
|
4
5
|
* A small, always-visible group of toggle buttons, one active at a time.
|
|
5
6
|
* This is the shared primitive behind two call sites that turned out to be
|
|
@@ -14,7 +15,7 @@ import { RemixIcon } from '../../../../react/components/RemixIcon.js';
|
|
|
14
15
|
* primitives for a minor ARIA-pattern difference.
|
|
15
16
|
*/
|
|
16
17
|
export function SegmentedToggle({ options, value, onChange, ariaLabel, className, }) {
|
|
17
|
-
return (_jsx("div", { className:
|
|
18
|
+
return (_jsx("div", { className: withClassName('viewer-segmented-toggle', className), role: "group", "aria-label": ariaLabel, children: options.map((option) => {
|
|
18
19
|
const selected = option.value === value;
|
|
19
20
|
const label = option.title ?? option.label;
|
|
20
21
|
return (_jsxs("button", { type: "button", className: `viewer-segmented-toggle-button${selected ? ' active' : ''}`, "aria-pressed": selected, "aria-label": label, title: label, onClick: () => onChange(option.value), children: [option.icon ? _jsx(RemixIcon, { name: option.icon, size: 14 }) : null, _jsx("span", { children: option.label })] }, option.value));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { withClassName } from '../../../../utils/class-names.js';
|
|
2
3
|
/**
|
|
3
4
|
* The "viewer-toolbar + viewer-body" chrome independently repeated across
|
|
4
5
|
* 8 media-viewer components in the source file (`BinaryViewer`,
|
|
@@ -9,7 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
9
10
|
* layout wrapper.
|
|
10
11
|
*/
|
|
11
12
|
export function ViewerShell({ kindClassName, toolbarLeft, toolbarActions, bodyClassName, children }) {
|
|
12
|
-
return (_jsxs("div", { className:
|
|
13
|
+
return (_jsxs("div", { className: withClassName('viewer', kindClassName), children: [_jsxs("div", { className: "viewer-toolbar", children: [_jsx("div", { className: "viewer-toolbar-left", children: toolbarLeft }), toolbarActions ? _jsx("div", { className: "viewer-toolbar-actions", children: toolbarActions }) : null] }), _jsx("div", { className: withClassName('viewer-body', bodyClassName), children: children })] }));
|
|
13
14
|
}
|
|
14
15
|
/** Trivial "nothing to show" placeholder shared by every viewer body. */
|
|
15
16
|
export function ViewerEmptyState({ children }) {
|
|
@@ -97,13 +97,14 @@ export function hasPrecisionSensitiveJsonNumberText(text) {
|
|
|
97
97
|
}
|
|
98
98
|
numberTokenPattern.lastIndex = i;
|
|
99
99
|
const match = numberTokenPattern.exec(text);
|
|
100
|
-
if (
|
|
100
|
+
if (match) {
|
|
101
|
+
if (isPrecisionSensitiveNumberLiteral(match[0]))
|
|
102
|
+
return true;
|
|
103
|
+
i = numberTokenPattern.lastIndex;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
101
106
|
i += 1;
|
|
102
|
-
continue;
|
|
103
107
|
}
|
|
104
|
-
if (isPrecisionSensitiveNumberLiteral(match[0]))
|
|
105
|
-
return true;
|
|
106
|
-
i = numberTokenPattern.lastIndex;
|
|
107
108
|
}
|
|
108
109
|
return false;
|
|
109
110
|
}
|
|
@@ -111,10 +112,10 @@ export function hasPrecisionSensitiveJsonNumberText(text) {
|
|
|
111
112
|
* `start` (honouring `\` escapes), or `text.length` when it is unterminated. */
|
|
112
113
|
function indexAfterJsonString(text, start) {
|
|
113
114
|
for (let i = start; i < text.length; i += 1) {
|
|
115
|
+
if (text[i] === '"')
|
|
116
|
+
return i + 1;
|
|
114
117
|
if (text[i] === '\\')
|
|
115
118
|
i += 1;
|
|
116
|
-
else if (text[i] === '"')
|
|
117
|
-
return i + 1;
|
|
118
119
|
}
|
|
119
120
|
return text.length;
|
|
120
121
|
}
|
|
@@ -18,12 +18,20 @@ export function brandMonogram(name) {
|
|
|
18
18
|
}
|
|
19
19
|
/** The stage to start at, given which sources are available. */
|
|
20
20
|
export function firstLogoStage(opts) {
|
|
21
|
-
|
|
21
|
+
if (opts.canUseBrandStage)
|
|
22
|
+
return 'brand';
|
|
23
|
+
return fallbackLogoStage(opts);
|
|
24
|
+
}
|
|
25
|
+
/** The first non-brand stage whose source is available. */
|
|
26
|
+
function fallbackLogoStage(opts) {
|
|
27
|
+
if (opts.logoSrc)
|
|
28
|
+
return 'custom';
|
|
29
|
+
return opts.host ? 'favicon' : 'letter';
|
|
22
30
|
}
|
|
23
31
|
/** The next stage to try after the current one fails to load. */
|
|
24
32
|
export function advanceLogoStage(stage, opts) {
|
|
25
33
|
if (stage === 'brand')
|
|
26
|
-
return opts
|
|
34
|
+
return fallbackLogoStage(opts);
|
|
27
35
|
if (stage === 'custom')
|
|
28
36
|
return 'favicon';
|
|
29
37
|
return 'letter';
|
|
@@ -233,7 +233,7 @@ export function useCustomSelectOriginTheme({ buttonRef, open, portal }, _optiona
|
|
|
233
233
|
const [attributes, setAttributes] = useState({});
|
|
234
234
|
useLayoutEffect(() => {
|
|
235
235
|
if (!open || !portal)
|
|
236
|
-
return;
|
|
236
|
+
return undefined;
|
|
237
237
|
const update = () => {
|
|
238
238
|
const next = resolveCustomSelectOriginTheme({ trigger: buttonRef.current });
|
|
239
239
|
setAttributes((current) => current['data-admin-theme'] === next['data-admin-theme']
|
|
@@ -36,21 +36,24 @@ const xcodePath = 'M19.06 5.3327c.4517-.1936.7744-.2581 1.097-.1936.5163.1291.77
|
|
|
36
36
|
const webstormPath = 'M0 0v24h24V0H0zm17.889 2.889c1.444 0 2.667.444 3.667 1.278l-1.111 1.667c-.889-.611-1.722-1-2.556-1s-1.278.389-1.278.889v.056c0 .667.444.889 2.111 1.333 2 .556 3.111 1.278 3.111 3v.056c0 2-1.5 3.111-3.611 3.111-1.5-.056-3-.611-4.167-1.667l1.278-1.556c.889.722 1.833 1.222 2.944 1.222.889 0 1.389-.333 1.389-.944v-.056c0-.556-.333-.833-2-1.278-2-.5-3.222-1.056-3.222-3.056v-.056c0-1.833 1.444-3 3.444-3zm-16.111.222h2.278l1.5 5.778 1.722-5.778h1.667l1.667 5.778 1.5-5.778h2.333l-2.833 9.944H9.723L8.112 7.277l-1.667 5.778H4.612L1.779 3.111zm.5 16.389h9V21h-9v-1.5z';
|
|
37
37
|
const ideaPath = 'M0 0v24h24V0zm3.723 3.111h5v1.834h-1.39v6.277h1.39v1.834h-5v-1.834h1.444V4.945H3.723zm11.055 0H17v6.5c0 .612-.055 1.111-.222 1.556-.167.444-.39.777-.723 1.11-.277.279-.666.557-1.11.668a3.933 3.933 0 0 1-1.445.278c-.778 0-1.444-.167-1.944-.445a4.81 4.81 0 0 1-1.279-1.056l1.39-1.555c.277.334.555.555.833.722.277.167.611.278.945.278.389 0 .721-.111 1-.389.221-.278.333-.667.333-1.278zM2.222 19.5h9V21h-9z';
|
|
38
38
|
const warpPath = 'M12.035 2.723h9.253A2.712 2.712 0 0 1 24 5.435v10.529a2.712 2.712 0 0 1-2.712 2.713H8.047Zm-1.681 2.6L6.766 19.677h5.598l-.399 1.6H2.712A2.712 2.712 0 0 1 0 18.565V8.036a2.712 2.712 0 0 1 2.712-2.712Z';
|
|
39
|
+
const PRIMARY = 'var(--jini-primary)';
|
|
40
|
+
const BG = 'var(--jini-bg)';
|
|
41
|
+
const TEXT = 'var(--jini-text)';
|
|
39
42
|
const EDITORS = {
|
|
40
|
-
vscode: { bg:
|
|
41
|
-
cursor: { bg:
|
|
42
|
-
windsurf: { bg:
|
|
43
|
-
zed: { bg:
|
|
44
|
-
qoder: { bg: 'var(--jini-warning)', fg:
|
|
45
|
-
antigravity: { bg:
|
|
46
|
-
webstorm: { bg:
|
|
47
|
-
idea: { bg:
|
|
48
|
-
xcode: { bg:
|
|
49
|
-
finder: { bg:
|
|
50
|
-
explorer: { bg: 'var(--jini-warning)', fg:
|
|
51
|
-
'file-manager': { bg: 'var(--jini-muted)', fg:
|
|
52
|
-
terminal: { bg:
|
|
53
|
-
warp: { bg:
|
|
43
|
+
vscode: { bg: PRIMARY, fg: BG, glyph: vscodeLogo },
|
|
44
|
+
cursor: { bg: TEXT, fg: BG, glyph: simplePath(cursorPath) },
|
|
45
|
+
windsurf: { bg: BG, fg: TEXT, glyph: simplePath(windsurfPath) },
|
|
46
|
+
zed: { bg: PRIMARY, fg: BG, glyph: simplePath(zedPath) },
|
|
47
|
+
qoder: { bg: 'var(--jini-warning)', fg: TEXT, glyph: qoderLogo },
|
|
48
|
+
antigravity: { bg: BG, fg: TEXT, glyph: antigravityLogo },
|
|
49
|
+
webstorm: { bg: TEXT, fg: BG, glyph: simplePath(webstormPath) },
|
|
50
|
+
idea: { bg: TEXT, fg: BG, glyph: simplePath(ideaPath) },
|
|
51
|
+
xcode: { bg: PRIMARY, fg: BG, glyph: simplePath(xcodePath) },
|
|
52
|
+
finder: { bg: PRIMARY, fg: BG, glyph: finderLogo },
|
|
53
|
+
explorer: { bg: 'var(--jini-warning)', fg: TEXT, glyph: folderLogo },
|
|
54
|
+
'file-manager': { bg: 'var(--jini-muted)', fg: BG, glyph: folderLogo },
|
|
55
|
+
terminal: { bg: TEXT, fg: 'var(--jini-success)', glyph: terminalLogo },
|
|
56
|
+
warp: { bg: PRIMARY, fg: BG, glyph: simplePath(warpPath) },
|
|
54
57
|
};
|
|
55
58
|
/**
|
|
56
59
|
* Renders an editor/target glyph by string key using the host's theme, with a
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Icon } from './Icon.js';
|
|
3
|
+
import { withClassName } from '../../utils/class-names.js';
|
|
3
4
|
export function Spinner({ size = 14, label }) {
|
|
4
5
|
return (_jsxs("span", { className: "loading-spinner", role: "status", "aria-live": "polite", children: [_jsx(Icon, { name: "spinner", size: size }), label ? _jsx("span", { className: "loading-spinner-label", children: label }) : null] }));
|
|
5
6
|
}
|
|
6
7
|
export function Skeleton({ width, height = 14, radius = 6, className }) {
|
|
7
|
-
return (_jsx("span", { className:
|
|
8
|
+
return (_jsx("span", { className: withClassName('skeleton-block', className), style: { width, height, borderRadius: radius }, "aria-hidden": true }));
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* Card-shaped skeleton for grid layouts (thumbnail area over a row of meta
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** A single-select value as a selection list; an empty string selects nothing. */
|
|
3
|
+
function singleSelection(value) {
|
|
4
|
+
return value ? [value] : [];
|
|
5
|
+
}
|
|
2
6
|
export function OnboardingChipField(props) {
|
|
3
7
|
const { label, options, className } = props;
|
|
4
|
-
const selected = props.multiple ? props.value : props.value
|
|
8
|
+
const selected = props.multiple ? props.value : singleSelection(props.value);
|
|
5
9
|
return (_jsxs("div", { className: ['onboarding-chip-field', className].filter(Boolean).join(' '), children: [_jsx("span", { className: "onboarding-chip-field__label", children: label }), _jsx("div", { className: "onboarding-chip-field__chips", children: options.map((option) => {
|
|
6
10
|
const active = selected.includes(option.value);
|
|
7
11
|
return (_jsx("button", { type: "button", className: `onboarding-chip${active ? ' is-selected' : ''}`, "aria-pressed": active, onClick: () => {
|
|
@@ -51,7 +51,9 @@ export const ONBOARDING_MENU_FALLBACK_VIEWPORT = 720;
|
|
|
51
51
|
* string (or otherwise falsy value) becomes an empty selection.
|
|
52
52
|
*/
|
|
53
53
|
export function resolveOnboardingSelectedValues(value) {
|
|
54
|
-
|
|
54
|
+
if (Array.isArray(value))
|
|
55
|
+
return value;
|
|
56
|
+
return value ? [value] : [];
|
|
55
57
|
}
|
|
56
58
|
/**
|
|
57
59
|
* Compute the trigger's visible label. In multiple mode it joins every
|
|
@@ -121,7 +123,7 @@ export function useOnboardingDropdownPlacement(rootRef, open, placement, optionC
|
|
|
121
123
|
});
|
|
122
124
|
useLayoutEffect(() => {
|
|
123
125
|
if (!open)
|
|
124
|
-
return;
|
|
126
|
+
return undefined;
|
|
125
127
|
function measureMenu() {
|
|
126
128
|
const node = rootRef.current;
|
|
127
129
|
if (!node)
|
|
@@ -153,11 +155,11 @@ export function useOnboardingDropdown(props) {
|
|
|
153
155
|
const [open, setOpen] = useState(false);
|
|
154
156
|
const [query, setQuery] = useState('');
|
|
155
157
|
const rootRef = useRef(null);
|
|
156
|
-
const dropdownIdRef = useRef(`onboarding-dropdown-${
|
|
158
|
+
const dropdownIdRef = useRef(`onboarding-dropdown-${globalThis.crypto.getRandomValues(new Uint32Array(1))[0].toString(36)}`);
|
|
157
159
|
const { placement: resolvedPlacement, maxHeight: menuMaxHeight } = useOnboardingDropdownPlacement(rootRef, open, placement, options.length);
|
|
158
160
|
useEffect(() => {
|
|
159
161
|
if (!open)
|
|
160
|
-
return;
|
|
162
|
+
return undefined;
|
|
161
163
|
function handlePointerDown(event) {
|
|
162
164
|
if (!rootRef.current?.contains(event.target)) {
|
|
163
165
|
setOpen(false);
|
|
@@ -10,12 +10,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
// hook-testable in isolation.
|
|
11
11
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
12
12
|
import { Icon } from './Icon.js';
|
|
13
|
+
const PRIMARY = 'var(--jini-primary)';
|
|
13
14
|
export const PALETTE_TWEAKS_SWATCHES = [
|
|
14
|
-
{ id: 'coral', label: 'Coral - default', stripe: [
|
|
15
|
-
{ id: 'electric', label: 'Electric', stripe: [
|
|
16
|
-
{ id: 'acid-forest', label: 'Acid forest', stripe: [
|
|
17
|
-
{ id: 'risograph', label: 'Risograph', stripe: [
|
|
18
|
-
{ id: 'mono-noir', label: 'Mono noir', stripe: ['var(--jini-text)',
|
|
15
|
+
{ id: 'coral', label: 'Coral - default', stripe: [PRIMARY, PRIMARY, PRIMARY, PRIMARY] },
|
|
16
|
+
{ id: 'electric', label: 'Electric', stripe: [PRIMARY, PRIMARY, PRIMARY, PRIMARY] },
|
|
17
|
+
{ id: 'acid-forest', label: 'Acid forest', stripe: [PRIMARY, PRIMARY, PRIMARY, PRIMARY] },
|
|
18
|
+
{ id: 'risograph', label: 'Risograph', stripe: [PRIMARY, PRIMARY, PRIMARY, PRIMARY] },
|
|
19
|
+
{ id: 'mono-noir', label: 'Mono noir', stripe: ['var(--jini-text)', PRIMARY, PRIMARY, PRIMARY] },
|
|
19
20
|
];
|
|
20
21
|
// --- Pure derivations (module-level, directly unit-testable) --------------
|
|
21
22
|
/**
|
|
@@ -71,7 +72,7 @@ export function usePaletteDismiss(options) {
|
|
|
71
72
|
const rootRef = useRef(null);
|
|
72
73
|
useEffect(() => {
|
|
73
74
|
if (!open)
|
|
74
|
-
return;
|
|
75
|
+
return undefined;
|
|
75
76
|
function onDoc(ev) {
|
|
76
77
|
if (!rootRef.current)
|
|
77
78
|
return;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { withClassName } from '../../utils/class-names.js';
|
|
2
3
|
/**
|
|
3
4
|
* Generic labeled trigger pill: icon + label (+ optional trailing icon),
|
|
4
5
|
* togglable `active` state, and an optional anchored children slot for a
|
|
@@ -9,6 +10,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
9
10
|
* (recon r6 §1.19) — generic popover-trigger chrome, no product types.
|
|
10
11
|
*/
|
|
11
12
|
export function PillButton({ icon, label, active = false, 'aria-label': ariaLabel, trailingIcon, onClick, disabled = false, className, children, }) {
|
|
12
|
-
return (_jsxs("div", { className:
|
|
13
|
+
return (_jsxs("div", { className: withClassName('jini-pill-wrap', className), children: [_jsxs("button", { type: "button", className: `jini-pill${active ? ' is-active' : ''}`, "aria-label": ariaLabel, "aria-expanded": children ? active : undefined, onClick: onClick, disabled: disabled, children: [icon, _jsx("span", { className: "jini-pill__label", children: label }), trailingIcon] }), children] }));
|
|
13
14
|
}
|
|
14
15
|
//# sourceMappingURL=PillButton.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { withClassName } from '../../utils/class-names.js';
|
|
2
3
|
/**
|
|
3
4
|
* Generic popover panel shell: a plain positioned wrapper around a list of
|
|
4
5
|
* `PopoverItem`s (or any other content). No open/closed state of its own —
|
|
@@ -8,6 +9,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
8
9
|
* (recon r6 §1.19) — generic, no product types.
|
|
9
10
|
*/
|
|
10
11
|
export function PopoverMenu({ children, className }) {
|
|
11
|
-
return _jsx("div", { className:
|
|
12
|
+
return _jsx("div", { className: withClassName('jini-popover', className), children: children });
|
|
12
13
|
}
|
|
13
14
|
//# sourceMappingURL=PopoverMenu.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import { ensureRemixIconStylesheet } from './RemixIcon.stylesheet.js';
|
|
4
|
+
import { withClassName } from '../../utils/class-names.js';
|
|
4
5
|
export { installRemixIconStylesheet, REMIXICON_STYLESHEET_MARKER } from './RemixIcon.stylesheet.js';
|
|
5
6
|
/**
|
|
6
7
|
* Thin wrapper around a RemixIcon webfont glyph (`ri-<name>`). Loads this package's own default
|
|
@@ -12,7 +13,7 @@ export function RemixIcon({ name, size = 14, className, style }) {
|
|
|
12
13
|
useEffect(() => {
|
|
13
14
|
ensureRemixIconStylesheet({});
|
|
14
15
|
}, []);
|
|
15
|
-
return (_jsx("i", { className: `ri-${name}
|
|
16
|
+
return (_jsx("i", { className: withClassName(`ri-${name}`, className), "aria-hidden": "true", style: {
|
|
16
17
|
fontSize: size,
|
|
17
18
|
lineHeight: 1,
|
|
18
19
|
width: size,
|