@jini-ai/ui 0.5.4 → 0.5.6
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 +10 -0
- package/dist/core/theme/validation.js +40 -38
- package/dist/features/a2ui/renderer.js +15 -13
- package/dist/features/about/react/components/AboutTab.js +64 -34
- package/dist/features/about/rules.d.ts +2 -2
- package/dist/features/about/rules.js +156 -129
- package/dist/features/admin-widgets/components/ImagePreviewModal.d.ts +4 -3
- package/dist/features/admin-widgets/components/ImagePreviewModal.js +6 -10
- package/dist/features/admin-widgets/components/InfoTip.d.ts +3 -2
- package/dist/features/admin-widgets/components/InfoTip.hooks.js +2 -0
- package/dist/features/admin-widgets/components/InfoTip.js +34 -7
- package/dist/features/admin-widgets/components/InfoTip.rules.d.ts +13 -0
- package/dist/features/admin-widgets/components/InfoTip.rules.js +43 -10
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.d.ts +30 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.d.ts +40 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.js +128 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.js +18 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.d.ts +14 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.js +12 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.rules.d.ts +20 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.rules.js +21 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.d.ts +18 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.d.ts +16 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.js +45 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.js +18 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.rules.d.ts +32 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.rules.js +26 -0
- package/dist/features/admin-widgets/components/Select/Select.hooks.d.ts +21 -0
- package/dist/features/admin-widgets/components/Select/Select.hooks.js +24 -2
- package/dist/features/admin-widgets/components/Select/Select.js +4 -3
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.js +29 -14
- package/dist/features/admin-widgets/index.d.ts +14 -2
- package/dist/features/admin-widgets/index.js +7 -1
- package/dist/features/admin-widgets/styles/admin-widgets.css +1 -0
- package/dist/features/asset-grid/react/components/AssetCard.js +7 -1
- package/dist/features/asset-grid/react/components/AssetGrid.d.ts +1 -1
- package/dist/features/asset-grid/react/components/AssetGrid.js +38 -18
- package/dist/features/asset-grid/react/components/useAssetGridFilters.d.ts +21 -0
- package/dist/features/asset-grid/react/components/useAssetGridFilters.js +19 -0
- package/dist/features/asset-grid/react/hooks/useAssetGridKeyboardShortcuts.js +16 -11
- package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.d.ts +2 -0
- package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.js +35 -11
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowser.d.ts +6 -6
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowser.js +10 -129
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowserParts.d.ts +50 -0
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowserParts.js +95 -0
- package/dist/features/asset-tree-browser/react/components/useAssetTreeBrowserController.d.ts +56 -0
- package/dist/features/asset-tree-browser/react/components/useAssetTreeBrowserController.js +80 -0
- package/dist/features/asset-tree-browser/rules.js +40 -22
- package/dist/features/browser-chrome/rules.js +74 -70
- package/dist/features/charts/browser.js +11 -5
- package/dist/features/charts/react.js +2 -2
- package/dist/features/charts/table.js +2 -2
- package/dist/features/command-palette/react/hooks/useCommandPalette.js +3 -9
- package/dist/features/connectors/ConnectorsBrowser.d.ts +4 -4
- package/dist/features/connectors/ConnectorsBrowser.js +26 -14
- package/dist/features/connectors/components/ConnectorCard.js +67 -38
- package/dist/features/connectors/components/ConnectorDetailDrawer.js +62 -31
- package/dist/features/connectors/components/ConnectorGrid.js +11 -6
- package/dist/features/connectors/hooks/useConnectorAuthorization.js +6 -0
- package/dist/features/connectors/hooks/useConnectorCatalog.d.ts +2 -0
- package/dist/features/connectors/hooks/useConnectorCatalog.js +32 -13
- package/dist/features/connectors/hooks/useWiredConnectorsBrowser.d.ts +3 -3
- package/dist/features/connectors/rules.d.ts +8 -1
- package/dist/features/connectors/rules.js +42 -20
- package/dist/features/connectors/types.d.ts +11 -0
- package/dist/features/execution/constants.d.ts +4 -10
- package/dist/features/execution/constants.js +9 -94
- package/dist/features/execution/react/components/ByokProviderForm.d.ts +2 -4
- package/dist/features/execution/react/components/ByokProviderForm.js +140 -43
- package/dist/features/execution/react/components/ExecutionTab.d.ts +1 -2
- package/dist/features/execution/react/components/ExecutionTab.js +52 -30
- package/dist/features/execution/react/components/LocalCliAgentCard.js +12 -3
- package/dist/features/execution/react/components/LocalCliAgentList.js +14 -3
- package/dist/features/execution/react/components/LocalCliAgentSettings.js +14 -3
- package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +54 -36
- package/dist/features/execution/react/hooks/useReasoningControl.d.ts +1 -1
- package/dist/features/execution/react/hooks/useReasoningControl.js +116 -75
- package/dist/features/execution/rules.d.ts +13 -2
- package/dist/features/execution/rules.js +51 -11
- package/dist/features/execution/types.d.ts +6 -42
- package/dist/features/execution/types.js +0 -17
- package/dist/features/external-mcp/react/components/ExternalMcpTab.d.ts +6 -2
- package/dist/features/external-mcp/react/components/ExternalMcpTab.js +9 -2
- package/dist/features/file-dropzone/react/components/FileDropzone.js +24 -25
- package/dist/features/file-dropzone/react/components/FileDropzoneLightbox.d.ts +2 -2
- package/dist/features/file-dropzone/react/components/FileDropzoneLightbox.js +35 -30
- package/dist/features/file-dropzone/react/components/FileDropzoneThumbnailGrid.js +30 -24
- package/dist/features/file-dropzone/react/components/FileDropzoneZone.d.ts +14 -0
- package/dist/features/file-dropzone/react/components/FileDropzoneZone.js +26 -0
- package/dist/features/html-editor/canvas-content-wrapper.js +13 -13
- package/dist/features/html-editor/canvas-embed-placeholders.js +46 -37
- package/dist/features/html-editor/css.js +76 -69
- package/dist/features/html-editor/editor-blocks.js +47 -33
- package/dist/features/html-editor/editor-serialization.js +6 -5
- package/dist/features/html-editor/protected-elements.js +39 -28
- package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +4 -4
- package/dist/features/html-editor/source-splice.js +51 -30
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +1 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +1 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +1 -0
- package/dist/features/i18n/locale.js +20 -16
- package/dist/features/iframe-pool/react/dom-sync.js +8 -6
- package/dist/features/integrations/react/components/CodexInstallToggleButton.js +19 -4
- package/dist/features/integrations/react/components/IntegrationsTab.js +60 -14
- package/dist/features/interactive-ui/interactive-ui.css +1 -1
- package/dist/features/interactive-ui/providers/native/data-table.manifest.d.ts +6 -6
- package/dist/features/interactive-ui/providers/shadcn/data-table.js +10 -7
- package/dist/features/interactive-ui/providers/shadcn/data-table.manifest.d.ts +6 -6
- package/dist/features/lexical-rich-text-editor/mention-parser.js +60 -57
- package/dist/features/lexical-rich-text-editor/react/hooks/useKeyboardCommands.js +33 -38
- package/dist/features/lexical-rich-text-editor/rules.js +87 -74
- package/dist/features/lexical-rich-text-editor/serialize.js +27 -25
- package/dist/features/mcp-ui/secret-card.js +111 -61
- package/dist/features/mcp-ui/surfaces/confirmation.js +39 -21
- package/dist/features/mcp-ui/surfaces/document.d.ts +1 -1
- package/dist/features/mcp-ui/surfaces/document.js +10 -2
- package/dist/features/mcp-ui/surfaces/fields.js +30 -50
- package/dist/features/mcp-ui/surfaces/form.d.ts +6 -0
- package/dist/features/mcp-ui/surfaces/form.js +43 -21
- package/dist/features/mcp-ui/surfaces/outcome.js +30 -20
- package/dist/features/mcp-ui/surfaces/text-input.js +33 -21
- package/dist/features/mcp-ui/surfaces/tokens.d.ts +6 -1
- package/dist/features/mcp-ui/surfaces/tokens.js +5 -2
- package/dist/features/media-providers/constants.d.ts +1 -0
- package/dist/features/media-providers/constants.js +2 -81
- package/dist/features/media-providers/index.d.ts +1 -1
- package/dist/features/media-providers/ports.d.ts +2 -0
- package/dist/features/media-providers/react/components/MediaProviderCard.d.ts +22 -0
- package/dist/features/media-providers/react/components/MediaProviderCard.js +50 -0
- package/dist/features/media-providers/react/components/MediaProvidersTab.d.ts +5 -6
- package/dist/features/media-providers/react/components/MediaProvidersTab.js +40 -72
- package/dist/features/media-providers/react/components/media-providers-tab-labels.d.ts +11 -0
- package/dist/features/media-providers/react/components/media-providers-tab-labels.js +57 -0
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.d.ts +4 -2
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +37 -23
- package/dist/features/media-providers/rules.js +17 -10
- package/dist/features/media-providers/types.d.ts +4 -22
- package/dist/features/media-providers/types.js +3 -8
- package/dist/features/memory/formatters.js +127 -92
- package/dist/features/memory/react/components/MemoryConnectedPanel.js +92 -36
- package/dist/features/memory/react/components/MemoryList.js +37 -18
- package/dist/features/memory/react/hooks/useMemoryExtractions.store.js +42 -36
- package/dist/features/notifications/react/components/NotificationsTab.js +28 -28
- package/dist/features/observability/long-task.d.ts +0 -12
- package/dist/features/observability/long-task.js +15 -19
- package/dist/features/observability/resource-error.d.ts +0 -10
- package/dist/features/observability/resource-error.js +18 -13
- package/dist/features/observability/stuck-run.js +10 -6
- package/dist/features/observability/telemetry-url.d.ts +6 -0
- package/dist/features/observability/telemetry-url.js +16 -0
- package/dist/features/observability/white-screen.js +12 -24
- package/dist/features/panel-kit/fetch-query/adapter.react.d.ts +2 -2
- package/dist/features/panel-kit/fetch-query/adapter.react.js +4 -2
- package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +46 -33
- package/dist/features/panel-kit/helpers/standing-draft-local-backup.js +3 -1
- package/dist/features/panel-kit/hooks/use-settings-slice.hooks.js +3 -1
- package/dist/features/privacy/react/components/PrivacyTab.js +24 -13
- package/dist/features/progress-card/components/ProgressCard.js +7 -3
- package/dist/features/progress-card/reference-adapters.js +59 -54
- package/dist/features/project-locations/react/components/ProjectLocationsTab.js +24 -15
- package/dist/features/project-locations/react/hooks/useProjectLocationsTab.d.ts +8 -0
- package/dist/features/project-locations/react/hooks/useProjectLocationsTab.js +31 -23
- package/dist/features/resource-dashboard/react/components/ResourceBoard.js +6 -47
- package/dist/features/resource-dashboard/react/components/ResourceBoardView.d.ts +2 -2
- package/dist/features/resource-dashboard/react/components/ResourceBoardView.js +3 -6
- package/dist/features/resource-dashboard/react/components/ResourceBoardViewParts.d.ts +15 -0
- package/dist/features/resource-dashboard/react/components/ResourceBoardViewParts.js +35 -0
- package/dist/features/resource-dashboard/react/components/ResourceCard.js +5 -16
- package/dist/features/resource-dashboard/react/components/ResourceCardParts.d.ts +34 -0
- package/dist/features/resource-dashboard/react/components/ResourceCardParts.js +34 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowList.js +3 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListItem.js +2 -2
- package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.d.ts +19 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.js +11 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListView.d.ts +1 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListView.js +4 -4
- package/dist/features/resource-dashboard/react/components/ResourceRowListViewParts.d.ts +10 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListViewParts.js +20 -0
- package/dist/features/resource-dashboard/react/components/resourceBoardProps.d.ts +48 -0
- package/dist/features/resource-dashboard/react/components/resourceBoardProps.js +70 -0
- package/dist/features/resource-dashboard/react/components/resourceRowListProps.d.ts +19 -0
- package/dist/features/resource-dashboard/react/components/resourceRowListProps.js +14 -0
- package/dist/features/resource-dashboard/react/components/translatedErrorLabelProps.d.ts +16 -0
- package/dist/features/resource-dashboard/react/components/translatedErrorLabelProps.js +13 -0
- package/dist/features/resource-dashboard/rules.js +2 -8
- package/dist/features/sketch-editor/dom.js +150 -99
- package/dist/features/sketch-editor/react/components/SketchEditor.js +26 -15
- package/dist/features/skills/react/components/SkillDraftForm.js +13 -19
- package/dist/features/skills/react/components/SkillDraftForm.labels.d.ts +31 -0
- package/dist/features/skills/react/components/SkillDraftForm.labels.js +54 -0
- package/dist/features/skills/react/components/SkillRow.js +38 -18
- package/dist/features/skills/react/components/SkillRow.labels.d.ts +7 -0
- package/dist/features/skills/react/components/SkillRow.labels.js +18 -0
- package/dist/features/skills/react/components/SkillsTab.js +24 -14
- package/dist/features/skills/react/components/SkillsTab.labels.d.ts +7 -0
- package/dist/features/skills/react/components/SkillsTab.labels.js +11 -0
- package/dist/features/skills/rules.js +32 -23
- package/dist/features/source-config-list/agent-handles.js +2 -1
- package/dist/features/source-config-list/dependencies.js +53 -49
- package/dist/features/source-config-list/index.d.ts +3 -3
- package/dist/features/source-config-list/react/components/SourceConfigAddForm.d.ts +6 -5
- package/dist/features/source-config-list/react/components/SourceConfigAddForm.js +38 -7
- package/dist/features/source-config-list/react/components/SourceConfigField.js +69 -25
- package/dist/features/source-config-list/react/components/SourceConfigItemCard.d.ts +6 -5
- package/dist/features/source-config-list/react/components/SourceConfigItemCard.js +76 -20
- package/dist/features/source-config-list/react/components/SourceConfigListView.d.ts +5 -3
- package/dist/features/source-config-list/react/components/SourceConfigListView.js +33 -3
- package/dist/features/source-config-list/react/components/SourceConfigTestControl.js +17 -1
- package/dist/features/source-config-list/react/components/SourceConfigTrustOptions.d.ts +11 -0
- package/dist/features/source-config-list/react/components/SourceConfigTrustOptions.js +12 -0
- package/dist/features/source-config-list/types.d.ts +14 -0
- package/dist/features/tab-launcher-menu/react/components/TabLauncherMenu.js +25 -1
- package/dist/features/tab-launcher-menu/react/hooks/useTabLauncherMenu.js +15 -16
- package/dist/features/tab-strip/react/components/TabBar.js +8 -1
- package/dist/features/tabbed-dialog/react/components/TabbedDialog.js +8 -30
- package/dist/features/tabbed-dialog/react/components/TabbedDialogChrome.d.ts +15 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogChrome.js +8 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogHeader.d.ts +12 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogHeader.js +6 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogSidebar.d.ts +27 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogSidebar.js +12 -0
- package/dist/features/tabbed-dialog/react/components/tabbedDialogView.d.ts +43 -0
- package/dist/features/tabbed-dialog/react/components/tabbedDialogView.js +59 -0
- package/dist/features/version-manager/dependencies.d.ts +3 -1
- package/dist/features/version-manager/dependencies.js +3 -2
- package/dist/features/version-manager/react/components/VersionManagerModal.js +10 -6
- package/dist/features/version-manager/react/hooks/useVersionManager.js +7 -4
- package/dist/features/viewer-shell/react/components/CommentSidePanel.js +103 -50
- package/dist/features/viewer-shell/react/components/MarkdownSplitPane.js +28 -8
- package/dist/features/viewer-shell/react/hooks/useCommentReorder.js +22 -16
- package/dist/features/viewer-shell/rules.js +19 -23
- package/dist/react/components/CustomSelect.d.ts +38 -1
- package/dist/react/components/CustomSelect.js +94 -38
- package/dist/react/components/OnboardingDropdown.js +20 -8
- package/dist/react/components/RemixIcon.stylesheet.js +3 -1
- package/dist/react/components/Toast.js +13 -2
- package/dist/react/components/TooltipLayer.js +5 -14
- package/dist/react/components/WorkingDirPicker.js +78 -50
- package/dist/react/components/remixicon-font-recovery.js +38 -30
- package/dist/react/components/select-popover.d.ts +8 -6
- package/dist/react/components/select-popover.js +33 -29
- package/dist/react/mcp-ui/McpUiHost.d.ts +1 -1
- package/dist/react/mcp-ui/McpUiHost.js +10 -11
- package/dist/react/mcp-ui/host-message-source.d.ts +14 -2
- package/dist/react/mcp-ui/host-message-source.js +15 -5
- package/dist/react/mcp-ui/mcp-ui-host-frame.d.ts +41 -0
- package/dist/react/mcp-ui/mcp-ui-host-frame.js +39 -0
- package/dist/renderers/annotation-canvas/react/components/AnnotationCanvas.js +97 -69
- package/dist/renderers/preview-modal-shell/react/components/PreviewModalShell.js +59 -30
- package/dist/renderers/preview-modal-shell/react/components/icons.js +4 -1
- package/dist/renderers/react/components/ArtifactView.js +9 -6
- package/dist/renderers/srcdoc/build.d.ts +4 -1
- package/dist/renderers/srcdoc/build.js +62 -48
- package/dist/styles/admin.css +29 -14
- package/dist/styles/lightbox.css +142 -0
- package/dist/styles/variables.css +128 -0
- package/dist/theme/apply.js +9 -5
- package/dist/utils/auto-open-file.d.ts +2 -1
- package/dist/utils/auto-open-file.js +69 -85
- package/dist/utils/markdown-scroll-sync.js +108 -87
- package/dist/utils/polygon-selection.js +25 -26
- package/dist/utils/smooth-scroll-to-top.d.ts +1 -1
- package/dist/utils/smooth-scroll-to-top.js +2 -32
- package/dist/utils/sse.js +26 -26
- package/dist/utils/unit-bezier.d.ts +7 -0
- package/dist/utils/unit-bezier.js +38 -0
- package/package.json +7 -10
- package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.d.ts +0 -13
- package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.js +0 -46
|
@@ -15,6 +15,10 @@ export function propNameToAttributeName(name) {
|
|
|
15
15
|
return 'srcdoc';
|
|
16
16
|
if (name === 'tabIndex')
|
|
17
17
|
return 'tabindex';
|
|
18
|
+
if (name === 'referrerPolicy')
|
|
19
|
+
return 'referrerpolicy';
|
|
20
|
+
if (name === 'allowFullScreen')
|
|
21
|
+
return 'allowfullscreen';
|
|
18
22
|
if (name.startsWith('data-') || name.startsWith('aria-'))
|
|
19
23
|
return name;
|
|
20
24
|
return name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`).toLowerCase();
|
|
@@ -74,15 +78,13 @@ export function syncStyle(frame, style, appliedStyleKeys) {
|
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
}
|
|
81
|
+
const NON_ATTRIBUTE_PROPS = new Set([
|
|
82
|
+
'cacheKey', 'src', 'style', 'children', 'dangerouslySetInnerHTML',
|
|
83
|
+
]);
|
|
77
84
|
export function syncIframeProps(frame, props, appliedAttributes, appliedStyleKeys) {
|
|
78
85
|
const nextAttributes = new Set();
|
|
79
86
|
for (const [name, value] of Object.entries(props)) {
|
|
80
|
-
if (name
|
|
81
|
-
|| name === 'src'
|
|
82
|
-
|| name === 'style'
|
|
83
|
-
|| name === 'children'
|
|
84
|
-
|| name === 'dangerouslySetInnerHTML'
|
|
85
|
-
|| name.startsWith('on')) {
|
|
87
|
+
if (NON_ATTRIBUTE_PROPS.has(name) || name.startsWith('on')) {
|
|
86
88
|
continue;
|
|
87
89
|
}
|
|
88
90
|
const attributeName = propNameToAttributeName(name);
|
|
@@ -13,10 +13,25 @@ export function CodexInstallToggleButton({ port, agentHandle }) {
|
|
|
13
13
|
const { available, installed, busy, error, successKind, toggle } = useCodexInstallToggle(port);
|
|
14
14
|
if (available === null)
|
|
15
15
|
return null;
|
|
16
|
-
if (!available)
|
|
17
|
-
return
|
|
18
|
-
}
|
|
16
|
+
if (!available)
|
|
17
|
+
return _jsx(CodexInstallUnavailableRow, {});
|
|
19
18
|
const label = installed ? t('Uninstall') : t('One-click install');
|
|
20
|
-
return (_jsxs("div", { className: "jini-codex-install-row", children: [_jsx("button", { type: "button", className: installed ? 'jini-button' : 'jini-button jini-button-primary', disabled: busy, onClick: toggle, ...agentHandleProps({}, { base: agentHandle,
|
|
19
|
+
return (_jsxs("div", { className: "jini-codex-install-row", children: [_jsx("button", { type: "button", className: installed ? 'jini-button' : 'jini-button jini-button-primary', disabled: busy, onClick: toggle, ...agentHandleProps({}, { base: agentHandle, role: 'button', label }), children: busy ? t('Working…') : label }), _jsx(CodexInstallStatusHint, { error: error, successKind: successKind })] }));
|
|
20
|
+
}
|
|
21
|
+
/** The row shown when the host's port has no Codex one-click install support. */
|
|
22
|
+
function CodexInstallUnavailableRow() {
|
|
23
|
+
const t = useT();
|
|
24
|
+
return (_jsxs("div", { className: "jini-codex-install-row", children: [_jsx("button", { type: "button", className: "jini-button", disabled: true, children: t('One-click install') }), _jsx("span", { className: "jini-hint", children: t('Not available for this daemon.') })] }));
|
|
25
|
+
}
|
|
26
|
+
/** The hint after the last toggle: its error if it failed, else which success it reached, else nothing. */
|
|
27
|
+
function CodexInstallStatusHint({ error, successKind }) {
|
|
28
|
+
const t = useT();
|
|
29
|
+
if (error)
|
|
30
|
+
return _jsx("span", { className: "jini-hint jini-hint-error", children: t('Install failed: {error}', { error }) });
|
|
31
|
+
if (successKind === 'installed')
|
|
32
|
+
return _jsx("span", { className: "jini-hint", children: t('MCP server installed.') });
|
|
33
|
+
if (successKind === 'uninstalled')
|
|
34
|
+
return _jsx("span", { className: "jini-hint", children: t('MCP server uninstalled.') });
|
|
35
|
+
return null;
|
|
21
36
|
}
|
|
22
37
|
//# sourceMappingURL=CodexInstallToggleButton.js.map
|
|
@@ -23,6 +23,14 @@ export function IntegrationsTab({ serverName = DEFAULT_MCP_SERVER_NAME, clients
|
|
|
23
23
|
const resolvedPort = useMemo(() => port ?? createFakeMcpIntegrationsPort(), [port]);
|
|
24
24
|
const [clientId, setClientId] = useState(initialClientId);
|
|
25
25
|
const { info, error, loading } = useMcpInstallInfo(resolvedPort);
|
|
26
|
+
const { client, resolved } = resolveClientSnippet({ clients, clientId, serverName, info });
|
|
27
|
+
return (_jsxs("section", { className: "jini-settings-section jini-settings-integrations", children: [_jsx(DaemonErrorCard, { error: error }), _jsx(CapabilitiesCard, { title: capabilitiesTitle, lines: capabilities }), _jsxs("div", { className: "jini-mcp-setup-card", children: [_jsx(ClientPicker, { clients: clients, selectedClientId: clientId, onSelect: setClientId, ...methodLabelProps({ resolved, info, clients, t }), ...childHandleProps({ agentHandle, action: 'client' }) }), resolved ? _jsx("p", { className: "jini-mcp-instruction", children: t(resolved.instructionTemplate, resolved.instructionVars) }) : null, client?.id === 'codex' ? (_jsx(CodexInstallToggleButton, { port: resolvedPort, ...childHandleProps({ agentHandle, action: 'codex-toggle' }) })) : null, resolved?.deeplink && info ? _jsx(DeeplinkInstallRow, { deeplink: resolved.deeplink, info: info, agentHandle: agentHandle }) : null, _jsx(InstallSnippet, { resolved: resolved, loading: loading, error: error }), _jsx(PrerequisiteWarning, { info: info }), _jsxs("div", { className: "jini-mcp-restart-note", children: [_jsx("strong", { children: t('Restart your client after installing.') }), ' ', _jsx("span", { children: t('Most MCP clients only pick up new servers on restart.') })] })] })] }));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The client the picker shows, and the snippet generated for THAT client (`null` until install
|
|
31
|
+
* info loads, or when `clients` is empty).
|
|
32
|
+
*/
|
|
33
|
+
function resolveClientSnippet({ clients, clientId, serverName, info, }) {
|
|
26
34
|
// Resolve the client ONCE, then generate from THAT — rather than displaying a
|
|
27
35
|
// fallback while generating from the raw stored id. `initialClientId` defaults
|
|
28
36
|
// to a constant a host with a restricted `clients` list need not include, and
|
|
@@ -32,6 +40,10 @@ export function IntegrationsTab({ serverName = DEFAULT_MCP_SERVER_NAME, clients
|
|
|
32
40
|
// client the host had deliberately excluded.
|
|
33
41
|
const client = clients.find((c) => c.id === clientId) ?? clients[0];
|
|
34
42
|
const resolved = info && client ? snippetForClient(client.id, serverName, info) : null;
|
|
43
|
+
return { client, resolved };
|
|
44
|
+
}
|
|
45
|
+
/** The picker's trigger subtitle and per-row method labels, both blank until install info loads. */
|
|
46
|
+
function methodLabelProps({ resolved, info, clients, t, }) {
|
|
35
47
|
// Origin gates every `buildMethod(info)` call on `info` being loaded
|
|
36
48
|
// (`info ? client.buildMethod(info) : ''` for the trigger subtitle, same
|
|
37
49
|
// guard for each dropdown row) — replicated here so the method labels
|
|
@@ -40,23 +52,57 @@ export function IntegrationsTab({ serverName = DEFAULT_MCP_SERVER_NAME, clients
|
|
|
40
52
|
const methodLabels = info
|
|
41
53
|
? Object.fromEntries(clients.map((c) => [c.id, t(methodLabelForClient(c.id))]))
|
|
42
54
|
: undefined;
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
return { methodLabel, methodLabels };
|
|
56
|
+
}
|
|
57
|
+
/** `{ agentHandle }` for a child, derived from this tab's ONE base handle — or `{}` when the host published none. */
|
|
58
|
+
function childHandleProps({ agentHandle, action }) {
|
|
59
|
+
return agentHandle ? { agentHandle: agentSubHandle({ base: agentHandle, action }) } : {};
|
|
60
|
+
}
|
|
61
|
+
/** Inline card for a failed install-info fetch; nothing while there is no error. */
|
|
62
|
+
function DaemonErrorCard({ error }) {
|
|
63
|
+
const t = useT();
|
|
64
|
+
if (!error)
|
|
65
|
+
return null;
|
|
66
|
+
return _jsx("div", { className: "jini-empty-card jini-empty-card-error", children: t('Could not reach the daemon: {error}', { error }) });
|
|
67
|
+
}
|
|
68
|
+
/** "What this server can do" card: the host's title and lines, or the generic defaults. */
|
|
69
|
+
function CapabilitiesCard({ title, lines }) {
|
|
70
|
+
const t = useT();
|
|
71
|
+
const resolvedCapabilitiesTitle = title ?? t('What this server can do');
|
|
72
|
+
const resolvedCapabilities = lines ?? [
|
|
45
73
|
t('Read your project files'),
|
|
46
74
|
t('Pull context into the conversation'),
|
|
47
75
|
t('Use default, safe tool permissions'),
|
|
48
76
|
];
|
|
49
|
-
return (_jsxs("
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
77
|
+
return (_jsxs("div", { className: "jini-mcp-capabilities-card", children: [_jsx("p", { className: "jini-mcp-capabilities-label", children: resolvedCapabilitiesTitle }), _jsx("ul", { className: "jini-mcp-capabilities-list", children: resolvedCapabilities.map((line) => (_jsx("li", { children: line }, line))) })] }));
|
|
78
|
+
}
|
|
79
|
+
/** One-click deeplink install, inert (no `href`, `aria-disabled`) while a prerequisite is missing. */
|
|
80
|
+
function DeeplinkInstallRow({ deeplink, info, agentHandle }) {
|
|
81
|
+
const t = useT();
|
|
82
|
+
const prerequisiteMissing = isMcpInstallPrerequisiteMissing(info);
|
|
83
|
+
return (_jsxs("div", { className: "jini-mcp-deeplink-row", children: [_jsx("a", { className: `jini-button jini-button-primary${prerequisiteMissing ? ' jini-button-disabled' : ''}`,
|
|
84
|
+
// Origin disables this button via `disabled={!info.cliExists ||
|
|
85
|
+
// !info.nodeExists}` — one-click install can't work until the
|
|
86
|
+
// daemon/CLI prerequisite is actually built. An `<a>` has no
|
|
87
|
+
// native `disabled`, so drop `href` (making it inert/
|
|
88
|
+
// unfocusable-as-a-link) and mark `aria-disabled` instead of
|
|
89
|
+
// silently letting the click through to a config that won't
|
|
90
|
+
// work.
|
|
91
|
+
href: prerequisiteMissing ? undefined : deeplink, "aria-disabled": prerequisiteMissing || undefined, onClick: (event) => {
|
|
92
|
+
if (prerequisiteMissing)
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
}, rel: "noopener noreferrer", ...agentHandleProps({}, { base: agentHandle, action: 'one-click-install', role: 'link', label: t('One-click install') }), children: t('One-click install') }), _jsx("span", { className: "jini-hint", children: t('Your editor will ask you to approve the install.') })] }));
|
|
95
|
+
}
|
|
96
|
+
/** The generated snippet, or a loading / could-not-resolve placeholder while there is none. */
|
|
97
|
+
function InstallSnippet({ resolved, loading, error }) {
|
|
98
|
+
const t = useT();
|
|
99
|
+
return (_jsx(SnippetBlock, { snippet: resolved?.snippet ?? '', language: resolved?.language ?? 'json', placeholder: loading ? t('Loading install paths…') : error ? t('Could not resolve install paths.') : '' }));
|
|
100
|
+
}
|
|
101
|
+
/** Build/Node warning, shown only once install info has loaded and reports a missing prerequisite. */
|
|
102
|
+
function PrerequisiteWarning({ info }) {
|
|
103
|
+
const t = useT();
|
|
104
|
+
if (!info || !isMcpInstallPrerequisiteMissing(info))
|
|
105
|
+
return null;
|
|
106
|
+
return (_jsxs("div", { className: "jini-empty-card jini-empty-card-warning", children: [_jsx("strong", { children: !info.cliExists ? t('Build the server first.') : t('Node.js was not found.') }), ' ', info.buildHint ?? t('See your host application for build instructions.')] }));
|
|
61
107
|
}
|
|
62
108
|
//# sourceMappingURL=IntegrationsTab.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}:root,[data-admin-theme],[data-color-scheme=light]{color-scheme:light;--jini-bg:var(--jini-theme-light-bg,#fff);--jini-surface:var(--jini-theme-light-surface,#f5f5f5);--jini-text:var(--jini-theme-light-text,#202020);--jini-muted:var(--jini-theme-light-muted,#666);--jini-border:var(--jini-theme-light-border,#d9d9d9);--jini-primary:var(--jini-theme-light-primary,#363636);--jini-primary-ink:var(--jini-theme-light-primary-ink,#fff);--jini-danger:var(--jini-theme-light-danger,#b42318);--jini-success:var(--jini-theme-light-success,#18763b);--jini-warning:var(--jini-theme-light-warning,#845800)}[data-color-scheme=dark]{color-scheme:dark;--jini-bg:var(--jini-theme-dark-bg,#171717);--jini-surface:var(--jini-theme-dark-surface,#242424);--jini-text:var(--jini-theme-dark-text,#f0f0f0);--jini-muted:var(--jini-theme-dark-muted,#b3b3b3);--jini-border:var(--jini-theme-dark-border,#454545);--jini-primary:var(--jini-theme-dark-primary,#e0e0e0);--jini-primary-ink:var(--jini-theme-dark-primary-ink,#202020);--jini-danger:var(--jini-theme-dark-danger,#ff8b80);--jini-success:var(--jini-theme-dark-success,#79d69b);--jini-warning:var(--jini-theme-dark-warning,#ebc36b)}:root,[data-color-scheme=light],[data-theme=light]{--jini-chart-default-1:oklch(55.29% .1129 43.4);--jini-chart-default-2:oklch(50% .11 240);--jini-chart-default-3:oklch(64% .13 88);--jini-chart-default-4:oklch(58% .15 350);--jini-chart-default-5:oklch(50% .11 155);--jini-chart-default-6:oklch(48% .12 295)}[data-color-scheme=dark],[data-theme=dark]{--jini-chart-default-1:oklch(62% .11 44);--jini-chart-default-2:oklch(64% .11 240);--jini-chart-default-3:oklch(66% .13 88);--jini-chart-default-4:oklch(65% .14 350);--jini-chart-default-5:oklch(56% .12 155);--jini-chart-default-6:oklch(64% .12 295)}:root{--jini-font-body:system-ui, sans-serif;--jini-font-heading:system-ui, sans-serif;--jini-font-mono:ui-monospace, monospace;--jini-radius:8px;--jini-density:1}:root,[data-admin-theme],[data-color-scheme]{--jini-bg-panel:var(--jini-surface);--jini-bg-subtle:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-bg-subtle:color-mix(in srgb, var(--jini-surface) 75%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-bg-elevated:var(--jini-surface);--jini-border-soft:var(--jini-border);--jini-border-strong:var(--jini-border)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-border-strong:color-mix(in srgb, var(--jini-border) 75%, var(--jini-text))}}:root,[data-admin-theme],[data-color-scheme]{--jini-backdrop:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-backdrop:color-mix(in srgb, var(--jini-text) 42%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-strong:var(--jini-text);--jini-text-secondary:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-secondary:color-mix(in srgb, var(--jini-text) 80%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-muted:var(--jini-muted);--jini-text-faint:var(--jini-muted)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-faint:color-mix(in srgb, var(--jini-muted) 75%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-disabled:var(--jini-muted)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-disabled:color-mix(in srgb, var(--jini-muted) 60%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent:var(--jini-primary);--jini-accent-hover:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-hover:color-mix(in srgb, var(--jini-primary) 88%, var(--jini-text))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-strong:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-strong:color-mix(in srgb, var(--jini-primary) 85%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ink:var(--jini-primary-ink);--jini-accent-soft:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-soft:color-mix(in srgb, var(--jini-primary) 10%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ring:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ring:color-mix(in srgb, var(--jini-primary) 22%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent:var(--jini-text);--jini-neutral-accent-hover:var(--jini-muted);--jini-neutral-accent-ink:var(--jini-bg);--jini-neutral-accent-text:var(--jini-text);--jini-neutral-accent-soft:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-soft:color-mix(in srgb, var(--jini-text) 7%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-ring:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-ring:color-mix(in srgb, var(--jini-text) 16%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-link:var(--jini-primary);--jini-link-ink:var(--jini-primary-ink);--jini-success-bg:var(--jini-success)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-success-bg:color-mix(in srgb, var(--jini-success) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-success-solid:var(--jini-success);--jini-success-solid-ink:var(--jini-bg);--jini-danger-bg:var(--jini-danger)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-danger-bg:color-mix(in srgb, var(--jini-danger) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-warning-bg:var(--jini-warning)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-warning-bg:color-mix(in srgb, var(--jini-warning) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-font-ui:var(--jini-font-body);--jini-font-display:var(--jini-font-heading);--jini-shadow-xs:0 1px 0 var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-xs:0 1px 0 color-mix(in srgb, var(--jini-text) 4%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-sm:0 1px 3px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-sm:0 1px 3px color-mix(in srgb, var(--jini-text) 10%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-md:0 6px 24px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-md:0 6px 24px color-mix(in srgb, var(--jini-text) 15%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-lg:0 24px 60px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-lg:0 24px 60px color-mix(in srgb, var(--jini-text) 22%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-radius-xs:calc(var(--jini-radius) * .5);--jini-radius-sm:calc(var(--jini-radius) * .75);--jini-radius-md:calc(var(--jini-radius) * 1.25);--jini-radius-lg:calc(var(--jini-radius) * 1.5);--jini-radius-pill:999px;--jini-space-1:calc(.25rem * var(--jini-density));--jini-space-2:calc(.5rem * var(--jini-density));--jini-space-3:calc(.75rem * var(--jini-density));--jini-space-4:calc(1rem * var(--jini-density));--jini-space-5:calc(1.25rem * var(--jini-density));--jini-space-6:calc(1.5rem * var(--jini-density));--jini-space-7:calc(2rem * var(--jini-density));--jini-space-8:calc(2.5rem * var(--jini-density));--jini-font-size-2xs:.6875rem;--jini-font-size-xs:.75rem;--jini-font-size-sm:.8125rem;--jini-font-size-base:.875rem;--jini-font-size-md:.95rem;--jini-font-size-lg:1.05rem;--jini-font-size-xl:1.65rem;--jini-font-weight-normal:400;--jini-font-weight-medium:500;--jini-font-weight-semibold:600;--jini-font-weight-bold:700;--jini-line-tight:1.25;--jini-line-normal:1.5;--jini-line-relaxed:1.7;--jini-duration-fast:.12s;--jini-duration-base:.2s;--jini-duration-slow:.32s;--jini-ease-out:cubic-bezier(.23, 1, .32, 1);--jini-ease-in-out:cubic-bezier(.4, 0, .2, 1);--jini-transition-base:var(--jini-duration-base) var(--jini-ease-out);--jini-z-dropdown:100;--jini-z-sticky:200;--jini-z-overlay:300;--jini-z-modal:400;--jini-z-toast:500;--jini-modal-padding:24px;--jini-sidebar-width:240px}@layer theme{:root,:host{--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--radius-sm:.25rem;--radius-md:.375rem;--radius-xl:.75rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer base,components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.right-2{right:calc(var(--spacing) * 2)}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.my-1{margin-block:var(--spacing)}.mt-4{margin-top:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.table{display:table}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-row{display:table-row}.aspect-square{aspect-ratio:1}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-px{height:1px}.max-h-\[--radix-select-content-available-height\]{max-height:--radix-select-content-available-height}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-9{width:calc(var(--spacing) * 9)}.w-full{width:100%}.min-w-\[8rem\]{min-width:8rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.shrink-0{flex-shrink:0}.caption-bottom{caption-side:bottom}.origin-\[--radix-select-content-transform-origin\]{transform-origin:--radix-select-content-transform-origin}.cursor-default{cursor:default}.flex-col{flex-direction:column}.place-content-center{place-content:center}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-input{border-color:var(--jini-border)}.border-primary{border-color:var(--jini-primary)}.bg-background{background-color:var(--jini-bg)}.bg-destructive{background-color:var(--jini-danger)}.bg-muted,.bg-muted\/50{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.bg-primary{background-color:var(--jini-primary)}.bg-secondary{background-color:var(--jini-surface)}.bg-transparent{background-color:#0000}.fill-primary{fill:var(--jini-primary)}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.pt-0{padding-top:0}.pr-8{padding-right:calc(var(--spacing) * 8)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-left{text-align:left}.align-middle{vertical-align:middle}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.whitespace-nowrap{white-space:nowrap}.text-current{color:currentColor}.text-destructive-foreground{color:var(--jini-bg)}.text-foreground{color:var(--jini-text)}.text-input{color:var(--jini-border)}.text-muted-foreground{color:var(--jini-muted)}.text-primary{color:var(--jini-primary)}.text-primary-foreground{color:var(--jini-primary-ink)}.text-secondary-foreground{color:var(--jini-text)}.underline-offset-4{text-underline-offset:4px}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--jini-bg)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--jini-text)}.placeholder\:text-muted-foreground::placeholder{color:var(--jini-muted)}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--jini-surface)}.hover\:bg-destructive\/90:hover{background-color:var(--jini-danger)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--jini-danger) 90%, transparent)}}.hover\:bg-muted\/50:hover{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--jini-primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--jini-surface) 80%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--jini-text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:bg-accent:focus{background-color:var(--jini-surface)}.focus\:text-accent-foreground:focus{color:var(--jini-text)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--jini-primary)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--jini-primary)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.has-aria-expanded\:bg-muted\/50:has([aria-expanded=true]){background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.has-aria-expanded\:bg-muted\/50:has([aria-expanded=true]){background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[placeholder\]\:text-muted-foreground[data-placeholder]{color:var(--jini-muted)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--jini-primary)}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:var(--jini-primary-ink)}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--jini-surface)}@media (min-width:48rem){.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:0}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}.jini-data-table-frame{border:1px solid var(--jini-border);border-radius:var(--jini-radius);background:var(--jini-bg);min-width:0;max-width:100%;color:var(--jini-text);overflow:hidden}.jini-data-table-scroll,.jini-data-table-frame>[data-slot=table-container]{overscroll-behavior-x:contain;width:100%;max-height:28rem;overflow:auto}.jini-data-table{border-collapse:separate;border-spacing:0;width:100%;font-family:var(--jini-font-body);font-size:var(--jini-font-size-sm);line-height:var(--jini-line-normal);font-variant-numeric:tabular-nums}.jini-data-table th,.jini-data-table td{text-align:left;vertical-align:middle;white-space:nowrap;border-bottom:1px solid var(--jini-border);height:2.5rem;padding:.625rem .875rem}.jini-data-table th{z-index:1;background:var(--jini-surface);color:var(--jini-muted);font-size:var(--jini-font-size-xs);font-weight:var(--jini-font-weight-semibold);position:sticky;top:0}.jini-data-table tbody tr:last-child td{border-bottom:0}.jini-data-table tbody tr:nth-child(2n){background:var(--jini-bg-subtle)}.jini-data-table tbody tr:hover,.jini-data-table tbody tr:focus-visible{background:var(--jini-surface)}.jini-data-table tbody tr[role=button]{cursor:pointer}.jini-data-table [data-numeric=true]{text-align:right}.jini-data-table-sort{width:100%;min-height:1.5rem;color:inherit;font:inherit;text-align:inherit;cursor:pointer;background:0 0;border:0;justify-content:space-between;align-items:center;gap:.625rem;padding:0;display:inline-flex}.jini-data-table [data-numeric=true] .jini-data-table-sort{justify-content:flex-end}.jini-data-table th[aria-sort=ascending],.jini-data-table th[aria-sort=descending],.jini-data-table-sort:hover{color:var(--jini-text)}.jini-data-table td.jini-data-table-empty{height:8rem;color:var(--jini-muted);text-align:center}.jini-data-table-pagination{border-top:1px solid var(--jini-border);color:var(--jini-muted);font-size:var(--jini-font-size-xs);font-variant-numeric:tabular-nums;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:.75rem;padding:.625rem .875rem;display:flex}.jini-data-table-pagination-controls{gap:.5rem;display:flex}.jini-data-table-pagination button{border:1px solid var(--jini-border);border-radius:var(--jini-radius-sm);background:var(--jini-bg);min-height:2rem;color:var(--jini-text);font:inherit;cursor:pointer;padding:.375rem .75rem}.jini-data-table-pagination button:hover:not(:disabled){background:var(--jini-surface)}.jini-data-table-pagination button:disabled{opacity:.5;cursor:default}.jini-data-table-sort:focus-visible,.jini-data-table-pagination button:focus-visible,.jini-data-table tr[role=button]:focus-visible{outline:2px solid var(--jini-primary);outline-offset:-2px}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}:root,[data-admin-theme],[data-color-scheme=light]{color-scheme:light;--jini-bg:var(--jini-theme-light-bg,#fff);--jini-surface:var(--jini-theme-light-surface,#f5f5f5);--jini-text:var(--jini-theme-light-text,#202020);--jini-muted:var(--jini-theme-light-muted,#666);--jini-border:var(--jini-theme-light-border,#d9d9d9);--jini-primary:var(--jini-theme-light-primary,#363636);--jini-primary-ink:var(--jini-theme-light-primary-ink,#fff);--jini-danger:var(--jini-theme-light-danger,#b42318);--jini-success:var(--jini-theme-light-success,#18763b);--jini-warning:var(--jini-theme-light-warning,#845800)}[data-color-scheme=dark]{color-scheme:dark;--jini-bg:var(--jini-theme-dark-bg,#171717);--jini-surface:var(--jini-theme-dark-surface,#242424);--jini-text:var(--jini-theme-dark-text,#f0f0f0);--jini-muted:var(--jini-theme-dark-muted,#b3b3b3);--jini-border:var(--jini-theme-dark-border,#454545);--jini-primary:var(--jini-theme-dark-primary,#e0e0e0);--jini-primary-ink:var(--jini-theme-dark-primary-ink,#202020);--jini-danger:var(--jini-theme-dark-danger,#ff8b80);--jini-success:var(--jini-theme-dark-success,#79d69b);--jini-warning:var(--jini-theme-dark-warning,#ebc36b)}:root,[data-color-scheme=light],[data-theme=light]{--jini-chart-default-1:oklch(55.29% .1129 43.4);--jini-chart-default-2:oklch(50% .11 240);--jini-chart-default-3:oklch(64% .13 88);--jini-chart-default-4:oklch(58% .15 350);--jini-chart-default-5:oklch(50% .11 155);--jini-chart-default-6:oklch(48% .12 295)}[data-color-scheme=dark],[data-theme=dark]{--jini-chart-default-1:oklch(62% .11 44);--jini-chart-default-2:oklch(64% .11 240);--jini-chart-default-3:oklch(66% .13 88);--jini-chart-default-4:oklch(65% .14 350);--jini-chart-default-5:oklch(56% .12 155);--jini-chart-default-6:oklch(64% .12 295)}:root{--jini-font-body:system-ui, sans-serif;--jini-font-heading:system-ui, sans-serif;--jini-font-mono:ui-monospace, monospace;--jini-radius:8px;--jini-density:1}:root,[data-admin-theme],[data-color-scheme]{--jini-bg-panel:var(--jini-surface);--jini-bg-subtle:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-bg-subtle:color-mix(in srgb, var(--jini-surface) 75%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-bg-elevated:var(--jini-surface);--jini-border-soft:var(--jini-border);--jini-border-strong:var(--jini-border)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-border-strong:color-mix(in srgb, var(--jini-border) 75%, var(--jini-text))}}:root,[data-admin-theme],[data-color-scheme]{--jini-backdrop:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-backdrop:color-mix(in srgb, var(--jini-text) 42%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-strong:var(--jini-text);--jini-text-secondary:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-secondary:color-mix(in srgb, var(--jini-text) 80%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-muted:var(--jini-muted);--jini-text-faint:var(--jini-muted)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-faint:color-mix(in srgb, var(--jini-muted) 75%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-disabled:var(--jini-muted)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-disabled:color-mix(in srgb, var(--jini-muted) 60%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent:var(--jini-primary);--jini-accent-hover:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-hover:color-mix(in srgb, var(--jini-primary) 88%, var(--jini-text))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-strong:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-strong:color-mix(in srgb, var(--jini-primary) 85%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ink:var(--jini-primary-ink);--jini-accent-soft:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-soft:color-mix(in srgb, var(--jini-primary) 10%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ring:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ring:color-mix(in srgb, var(--jini-primary) 22%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent:var(--jini-text);--jini-neutral-accent-hover:var(--jini-muted);--jini-neutral-accent-ink:var(--jini-bg);--jini-neutral-accent-text:var(--jini-text);--jini-neutral-accent-soft:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-soft:color-mix(in srgb, var(--jini-text) 7%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-ring:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-ring:color-mix(in srgb, var(--jini-text) 16%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-link:var(--jini-primary);--jini-link-ink:var(--jini-primary-ink);--jini-success-bg:var(--jini-success)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-success-bg:color-mix(in srgb, var(--jini-success) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-success-solid:var(--jini-success);--jini-success-solid-ink:var(--jini-bg);--jini-danger-bg:var(--jini-danger)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-danger-bg:color-mix(in srgb, var(--jini-danger) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-warning-bg:var(--jini-warning)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-warning-bg:color-mix(in srgb, var(--jini-warning) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-font-ui:var(--jini-font-body);--jini-font-display:var(--jini-font-heading);--jini-shadow-xs:0 1px 0 var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-xs:0 1px 0 color-mix(in srgb, var(--jini-text) 4%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-sm:0 1px 3px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-sm:0 1px 3px color-mix(in srgb, var(--jini-text) 10%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-md:0 6px 24px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-md:0 6px 24px color-mix(in srgb, var(--jini-text) 15%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-lg:0 24px 60px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-lg:0 24px 60px color-mix(in srgb, var(--jini-text) 22%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-radius-xs:calc(var(--jini-radius) * .5);--jini-radius-sm:calc(var(--jini-radius) * .75);--jini-radius-md:calc(var(--jini-radius) * 1.25);--jini-radius-lg:calc(var(--jini-radius) * 1.5);--jini-radius-pill:999px;--jini-space-1:calc(.25rem * var(--jini-density));--jini-space-2:calc(.5rem * var(--jini-density));--jini-space-3:calc(.75rem * var(--jini-density));--jini-space-4:calc(1rem * var(--jini-density));--jini-space-5:calc(1.25rem * var(--jini-density));--jini-space-6:calc(1.5rem * var(--jini-density));--jini-space-7:calc(2rem * var(--jini-density));--jini-space-8:calc(2.5rem * var(--jini-density));--jini-font-size-2xs:.6875rem;--jini-font-size-xs:.75rem;--jini-font-size-sm:.8125rem;--jini-font-size-base:.875rem;--jini-font-size-md:.95rem;--jini-font-size-lg:1.05rem;--jini-font-size-xl:1.65rem;--jini-font-weight-normal:400;--jini-font-weight-medium:500;--jini-font-weight-semibold:600;--jini-font-weight-bold:700;--jini-line-tight:1.25;--jini-line-normal:1.5;--jini-line-relaxed:1.7;--jini-duration-fast:.12s;--jini-duration-base:.2s;--jini-duration-slow:.32s;--jini-ease-out:cubic-bezier(.23, 1, .32, 1);--jini-ease-in-out:cubic-bezier(.4, 0, .2, 1);--jini-transition-base:var(--jini-duration-base) var(--jini-ease-out);--jini-z-dropdown:100;--jini-z-sticky:200;--jini-z-overlay:300;--jini-z-modal:400;--jini-z-toast:500;--jini-modal-padding:24px;--jini-sidebar-width:240px;--jini-app-bg:var(--jini-theme-app-bg,var(--jini-default-app-bg));--jini-shell-bg:var(--jini-theme-shell-bg,var(--jini-bg));--jini-panel-bg:var(--jini-theme-panel-bg,var(--jini-default-panel-bg));--jini-panel-border:var(--jini-theme-panel-border,var(--jini-default-panel-border));--jini-panel-shadow:var(--jini-theme-panel-shadow,var(--jini-default-panel-shadow));--jini-panel-backdrop:var(--jini-theme-panel-backdrop);--jini-panel-texture:var(--jini-theme-panel-texture);--jini-rail-bg:var(--jini-theme-rail-bg,var(--jini-panel-bg));--jini-rail-border:var(--jini-theme-rail-border,var(--jini-panel-border));--jini-rail-shadow:var(--jini-theme-rail-shadow,none);--jini-rail-backdrop:var(--jini-theme-rail-backdrop,var(--jini-panel-backdrop,none));--jini-overlay-bg:var(--jini-theme-overlay-bg,var(--jini-default-overlay-bg));--jini-overlay-backdrop:var(--jini-theme-overlay-backdrop);--jini-overlay-shadow:var(--jini-theme-overlay-shadow,var(--jini-default-overlay-shadow));--jini-control-preview-backdrop:var(--jini-theme-control-preview-backdrop,blur(6px));--jini-control-bg:var(--jini-theme-control-bg,var(--jini-default-control-bg));--jini-control-border:var(--jini-theme-control-border,var(--jini-default-control-border));--jini-control-shadow:var(--jini-theme-control-shadow);--jini-control-shadow-hover:var(--jini-theme-control-shadow-hover);--jini-control-shadow-pressed:var(--jini-theme-control-shadow-pressed);--jini-control-shadow-inset:var(--jini-theme-control-shadow-inset);--jini-border-width:var(--jini-theme-border-width);--jini-control-chevron-image:var(--jini-theme-control-chevron-image,url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14' fill='none'%3E%3Cpath d='M3.5 5.5 7 9l3.5-3.5' stroke='%23666C75' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"));--jini-overlay-tooltip-bg:var(--jini-theme-overlay-tooltip-bg,#fff);--jini-overlay-tooltip-text:var(--jini-theme-overlay-tooltip-text,#111);--jini-overlay-tooltip-border:var(--jini-theme-overlay-tooltip-border,#0000001a);--jini-overlay-bg-preview:var(--jini-theme-overlay-bg-preview,oklch(0% 0 0/.55));--jini-overlay-bg-navigation:var(--jini-theme-overlay-bg-navigation,oklch(0% 0 0/.4));--jini-code-string:var(--jini-theme-code-string,#4caf7a);--jini-code-number:var(--jini-theme-code-number,#d1975a);--jini-control-thumb-bg:var(--jini-theme-control-thumb-bg,#fff);--jini-control-solid-ink:var(--jini-theme-control-solid-ink,#fff);--jini-overlay-bg-lightbox:var(--jini-theme-overlay-bg-lightbox,oklch(0% 0 0/.6));--jini-lightbox-bg:var(--jini-theme-lightbox-bg,oklch(23% .005 256));--jini-lightbox-ink:var(--jini-theme-lightbox-ink,oklch(97% 0 0));--jini-lightbox-ink-muted:var(--jini-theme-lightbox-ink-muted,oklch(97% 0 0/.58));--jini-lightbox-media-bg:var(--jini-theme-lightbox-media-bg,oklch(0% 0 0/.25));--jini-lightbox-document-bg:var(--jini-theme-lightbox-document-bg,#fff);--jini-lightbox-button-border:var(--jini-theme-lightbox-button-border,oklch(100% 0 0/.16));--jini-lightbox-button-bg:var(--jini-theme-lightbox-button-bg,oklch(100% 0 0/.07));--jini-lightbox-button-bg-hover:var(--jini-theme-lightbox-button-bg-hover,oklch(100% 0 0/.15));--jini-lightbox-button-border-hover:var(--jini-theme-lightbox-button-border-hover,oklch(100% 0 0/.28));--jini-control-media-bg:var(--jini-theme-control-media-bg,oklch(0% 0 0/.55));--jini-control-media-ink:var(--jini-theme-control-media-ink,oklch(100% 0 0));--jini-control-media-border:var(--jini-theme-control-media-border,oklch(100% 0 0/.35));--jini-control-media-bg-hover:var(--jini-theme-control-media-bg-hover,oklch(0% 0 0/.72));--jini-overlay-bg-source:var(--jini-theme-overlay-bg-source,oklch(0% 0 0/.48));--jini-file-icon-folder:var(--jini-theme-file-icon-folder,oklch(72% .12 75));--jini-file-icon-json:var(--jini-theme-file-icon-json,oklch(72% .13 90));--jini-file-icon-markdown:var(--jini-theme-file-icon-markdown,oklch(62% .12 245));--jini-file-icon-javascript:var(--jini-theme-file-icon-javascript,oklch(76% .15 95));--jini-file-icon-typescript:var(--jini-theme-file-icon-typescript,oklch(60% .13 250));--jini-file-icon-config:var(--jini-theme-file-icon-config,oklch(62% .14 20));--jini-file-icon-html:var(--jini-theme-file-icon-html,oklch(64% .17 40));--jini-file-icon-css:var(--jini-theme-file-icon-css,oklch(62% .13 280));--jini-file-icon-image:var(--jini-theme-file-icon-image,oklch(64% .12 160));--jini-file-icon-shell:var(--jini-theme-file-icon-shell,oklch(64% .12 145));--jini-status-complete-ink-fallback:var(--jini-theme-status-complete-ink-fallback,oklch(99% 0 none));--jini-control-preview-ink:var(--jini-theme-control-preview-ink,#fff);--jini-control-preview-bg:var(--jini-theme-control-preview-bg,#1111116b);--jini-control-preview-bg-hover:var(--jini-theme-control-preview-bg-hover,#111111b8);--jini-control-preview-tip-bg:var(--jini-theme-control-preview-tip-bg,#111111e0);--jini-panel-border-muted:var(--jini-theme-panel-border-muted,#d9d9d9);--jini-control-composer-border-focus:var(--jini-theme-control-composer-border-focus,oklch(70% .012 255));--jini-overlay-bg-chat:var(--jini-theme-overlay-bg-chat,#00000073);--jini-control-hover-neutral-bg:var(--jini-theme-control-hover-neutral-bg,#7f7f7f26);--jini-control-recording-bg:var(--jini-theme-control-recording-bg,#dc2626);--jini-control-recording-ink:var(--jini-theme-control-recording-ink,#fff);--jini-control-recording-bg-hover:var(--jini-theme-control-recording-bg-hover,#b91c1c);--jini-control-shadow-focus:var(--jini-theme-control-shadow-focus,0 0 0 3px var(--jini-accent-ring));--jini-overlay-tooltip-shadow:var(--jini-theme-overlay-tooltip-shadow,0 4px 16px #00000040);--jini-control-shadow-focus-subtle:var(--jini-theme-control-shadow-focus-subtle,0 0 0 2px var(--jini-neutral-accent-soft));--jini-overlay-toast-shadow:var(--jini-theme-overlay-toast-shadow,0 8px 24px #00000038);--jini-status-danger-shadow:var(--jini-theme-status-danger-shadow,inset 3px 0 0 var(--jini-danger));--jini-control-thumb-shadow-strong:var(--jini-theme-control-thumb-shadow-strong,0 1px 2px #1c1b1a47);--jini-panel-shadow-divider:var(--jini-theme-panel-shadow-divider,inset 0 -1px 0 var(--jini-border));--jini-control-shadow-focus-accent:var(--jini-theme-control-shadow-focus-accent,0 0 0 3px var(--jini-accent))}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-control-shadow-focus-accent:var(--jini-theme-control-shadow-focus-accent,0 0 0 3px color-mix(in srgb, var(--jini-accent) 18%, transparent))}}:root,[data-admin-theme],[data-color-scheme]{--jini-overlay-menu-shadow-above:var(--jini-theme-overlay-menu-shadow-above,0 -4px 14px #141c2d17, 0 -1px 4px #141c2d0f);--jini-control-shadow-selected:var(--jini-theme-control-shadow-selected,0 0 0 1px var(--jini-accent));--jini-control-shadow-swatch-selected:var(--jini-theme-control-shadow-swatch-selected,0 0 0 2px var(--jini-bg-panel), 0 0 0 4px var(--jini-accent));--jini-control-shadow-segment:var(--jini-theme-control-shadow-segment,0 1px 2px #00000014);--jini-panel-shadow-sticky:var(--jini-theme-panel-shadow-sticky,0 6px 8px -6px #00000024);--jini-overlay-menu-shadow:var(--jini-theme-overlay-menu-shadow,0 12px 32px #0000001f);--jini-control-shadow-segment-raised:var(--jini-theme-control-shadow-segment-raised,0 1px 2px #0000001f);--jini-control-thumb-shadow:var(--jini-theme-control-thumb-shadow,0 1px 2px #00000040);--jini-panel-shadow-banner:var(--jini-theme-panel-shadow-banner,0 2px 8px #0000001f);--jini-status-warning-shadow:var(--jini-theme-status-warning-shadow,inset 2px 0 0 var(--jini-warning));--jini-panel-shadow-flat:var(--jini-theme-panel-shadow-flat,none)}:root{--jini-chat-font-body:var(--jini-theme-chat-font-body,-apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei UI", "Noto Sans", Roboto, "Helvetica Neue", Arial, sans-serif);--jini-chat-font-mono:var(--jini-theme-chat-font-mono,ui-monospace, SFMono-Regular, Menlo, monospace);--jini-chat-popover-shadow:var(--jini-theme-chat-popover-shadow,0 18px 46px #0d0c0a26, 0 2px 8px #0d0c0a0f);--jini-chat-bg:var(--jini-theme-chat-bg);--jini-chat-panel:var(--jini-theme-chat-panel);--jini-chat-text:var(--jini-theme-chat-text);--jini-chat-text-strong:var(--jini-theme-chat-text-strong);--jini-chat-muted:var(--jini-theme-chat-muted);--jini-chat-faint:var(--jini-theme-chat-faint);--jini-chat-border:var(--jini-theme-chat-border);--jini-chat-border-strong:var(--jini-theme-chat-border-strong);--jini-chat-border-soft:var(--jini-theme-chat-border-soft);--jini-chat-subtle:var(--jini-theme-chat-subtle);--jini-chat-accent:var(--jini-theme-chat-accent);--jini-chat-accent-soft:var(--jini-theme-chat-accent-soft);--jini-chat-danger:var(--jini-theme-chat-danger);--jini-chat-radius:var(--jini-theme-chat-radius);--jini-chat-radius-lg:var(--jini-theme-chat-radius-lg);--jini-chat-user-bubble:var(--jini-theme-chat-user-bubble);--jini-chat-user-bubble-ink:var(--jini-theme-chat-user-bubble-ink)}@layer theme{:root,:host{--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--radius-sm:.25rem;--radius-md:.375rem;--radius-xl:.75rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer base,components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.right-2{right:calc(var(--spacing) * 2)}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.my-1{margin-block:var(--spacing)}.mt-4{margin-top:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.table{display:table}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-row{display:table-row}.aspect-square{aspect-ratio:1}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-px{height:1px}.max-h-\[--radix-select-content-available-height\]{max-height:--radix-select-content-available-height}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-9{width:calc(var(--spacing) * 9)}.w-full{width:100%}.min-w-\[8rem\]{min-width:8rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.shrink-0{flex-shrink:0}.caption-bottom{caption-side:bottom}.origin-\[--radix-select-content-transform-origin\]{transform-origin:--radix-select-content-transform-origin}.cursor-default{cursor:default}.flex-col{flex-direction:column}.place-content-center{place-content:center}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-input{border-color:var(--jini-border)}.border-primary{border-color:var(--jini-primary)}.bg-background{background-color:var(--jini-bg)}.bg-destructive{background-color:var(--jini-danger)}.bg-muted,.bg-muted\/50{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.bg-primary{background-color:var(--jini-primary)}.bg-secondary{background-color:var(--jini-surface)}.bg-transparent{background-color:#0000}.fill-primary{fill:var(--jini-primary)}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.pt-0{padding-top:0}.pr-8{padding-right:calc(var(--spacing) * 8)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-left{text-align:left}.align-middle{vertical-align:middle}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.whitespace-nowrap{white-space:nowrap}.text-current{color:currentColor}.text-destructive-foreground{color:var(--jini-bg)}.text-foreground{color:var(--jini-text)}.text-input{color:var(--jini-border)}.text-muted-foreground{color:var(--jini-muted)}.text-primary{color:var(--jini-primary)}.text-primary-foreground{color:var(--jini-primary-ink)}.text-secondary-foreground{color:var(--jini-text)}.underline-offset-4{text-underline-offset:4px}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--jini-bg)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--jini-text)}.placeholder\:text-muted-foreground::placeholder{color:var(--jini-muted)}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--jini-surface)}.hover\:bg-destructive\/90:hover{background-color:var(--jini-danger)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--jini-danger) 90%, transparent)}}.hover\:bg-muted\/50:hover{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--jini-primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--jini-surface) 80%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--jini-text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:bg-accent:focus{background-color:var(--jini-surface)}.focus\:text-accent-foreground:focus{color:var(--jini-text)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--jini-primary)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--jini-primary)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.has-aria-expanded\:bg-muted\/50:has([aria-expanded=true]){background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.has-aria-expanded\:bg-muted\/50:has([aria-expanded=true]){background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[placeholder\]\:text-muted-foreground[data-placeholder]{color:var(--jini-muted)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--jini-primary)}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:var(--jini-primary-ink)}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--jini-surface)}@media (min-width:48rem){.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:0}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}.jini-data-table-frame{border:1px solid var(--jini-border);border-radius:var(--jini-radius);background:var(--jini-bg);min-width:0;max-width:100%;color:var(--jini-text);overflow:hidden}.jini-data-table-scroll,.jini-data-table-frame>[data-slot=table-container]{overscroll-behavior-x:contain;width:100%;max-height:28rem;overflow:auto}.jini-data-table{border-collapse:separate;border-spacing:0;width:100%;font-family:var(--jini-font-body);font-size:var(--jini-font-size-sm);line-height:var(--jini-line-normal);font-variant-numeric:tabular-nums}.jini-data-table th,.jini-data-table td{text-align:left;vertical-align:middle;white-space:nowrap;border-bottom:1px solid var(--jini-border);height:2.5rem;padding:.625rem .875rem}.jini-data-table th{z-index:1;background:var(--jini-surface);color:var(--jini-muted);font-size:var(--jini-font-size-xs);font-weight:var(--jini-font-weight-semibold);position:sticky;top:0}.jini-data-table tbody tr:last-child td{border-bottom:0}.jini-data-table tbody tr:nth-child(2n){background:var(--jini-bg-subtle)}.jini-data-table tbody tr:hover,.jini-data-table tbody tr:focus-visible{background:var(--jini-surface)}.jini-data-table tbody tr[role=button]{cursor:pointer}.jini-data-table [data-numeric=true]{text-align:right}.jini-data-table-sort{width:100%;min-height:1.5rem;color:inherit;font:inherit;text-align:inherit;cursor:pointer;background:0 0;border:0;justify-content:space-between;align-items:center;gap:.625rem;padding:0;display:inline-flex}.jini-data-table [data-numeric=true] .jini-data-table-sort{justify-content:flex-end}.jini-data-table th[aria-sort=ascending],.jini-data-table th[aria-sort=descending],.jini-data-table-sort:hover{color:var(--jini-text)}.jini-data-table td.jini-data-table-empty{height:8rem;color:var(--jini-muted);text-align:center}.jini-data-table-pagination{border-top:1px solid var(--jini-border);color:var(--jini-muted);font-size:var(--jini-font-size-xs);font-variant-numeric:tabular-nums;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:.75rem;padding:.625rem .875rem;display:flex}.jini-data-table-pagination-controls{gap:.5rem;display:flex}.jini-data-table-pagination button{border:1px solid var(--jini-border);border-radius:var(--jini-radius-sm);background:var(--jini-bg);min-height:2rem;color:var(--jini-text);font:inherit;cursor:pointer;padding:.375rem .75rem}.jini-data-table-pagination button:hover:not(:disabled){background:var(--jini-surface)}.jini-data-table-pagination button:disabled{opacity:.5;cursor:default}.jini-data-table-sort:focus-visible,.jini-data-table-pagination button:focus-visible,.jini-data-table tr[role=button]:focus-visible{outline:2px solid var(--jini-primary);outline-offset:-2px}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}
|
|
@@ -19,11 +19,11 @@ export declare const nativeDataTablePropsSchema: z.ZodObject<{
|
|
|
19
19
|
key: z.ZodString;
|
|
20
20
|
label: z.ZodString;
|
|
21
21
|
}, "strict", z.ZodTypeAny, {
|
|
22
|
-
key: string;
|
|
23
22
|
label: string;
|
|
24
|
-
}, {
|
|
25
23
|
key: string;
|
|
24
|
+
}, {
|
|
26
25
|
label: string;
|
|
26
|
+
key: string;
|
|
27
27
|
}>, "many">;
|
|
28
28
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
29
29
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
@@ -31,11 +31,11 @@ export declare const nativeDataTablePropsSchema: z.ZodObject<{
|
|
|
31
31
|
key: z.ZodString;
|
|
32
32
|
label: z.ZodString;
|
|
33
33
|
}, "strict", z.ZodTypeAny, {
|
|
34
|
-
key: string;
|
|
35
34
|
label: string;
|
|
36
|
-
}, {
|
|
37
35
|
key: string;
|
|
36
|
+
}, {
|
|
38
37
|
label: string;
|
|
38
|
+
key: string;
|
|
39
39
|
}>, "many">;
|
|
40
40
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
41
41
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
@@ -43,11 +43,11 @@ export declare const nativeDataTablePropsSchema: z.ZodObject<{
|
|
|
43
43
|
key: z.ZodString;
|
|
44
44
|
label: z.ZodString;
|
|
45
45
|
}, "strict", z.ZodTypeAny, {
|
|
46
|
-
key: string;
|
|
47
46
|
label: string;
|
|
48
|
-
}, {
|
|
49
47
|
key: string;
|
|
48
|
+
}, {
|
|
50
49
|
label: string;
|
|
50
|
+
key: string;
|
|
51
51
|
}>, "many">;
|
|
52
52
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
53
53
|
}, z.ZodTypeAny, "passthrough">>;
|
|
@@ -2,6 +2,15 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useMemo, useState } from 'react';
|
|
3
3
|
import { getNumericColumnKeys, sortTableRows } from '../../table-data.js';
|
|
4
4
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './table.js';
|
|
5
|
+
function resolveTablePage({ pageSize, rowCount, requestedPage }, _options = {}) {
|
|
6
|
+
const requestedSize = pageSize !== undefined && Number.isInteger(pageSize) && pageSize > 0 ? pageSize : null;
|
|
7
|
+
const paging = requestedSize !== null;
|
|
8
|
+
const size = requestedSize ?? Math.max(rowCount, 1);
|
|
9
|
+
const pageCount = Math.max(1, Math.ceil(rowCount / size));
|
|
10
|
+
// Clamp during render so a smaller result set never shows a stale, empty page.
|
|
11
|
+
const page = paging ? Math.min(requestedPage, pageCount - 1) : 0;
|
|
12
|
+
return { paging, size, pageCount, page, start: page * size };
|
|
13
|
+
}
|
|
5
14
|
/** Composes shadcn's real `table.tsx` primitives into the same `columns`/`rows`/`onRowClick` contract `native.data-table` exposes. */
|
|
6
15
|
export function DataTable({ columns, rows, onRowClick, sortable = true, pageSize }) {
|
|
7
16
|
const [sort, setSort] = useState(null);
|
|
@@ -9,13 +18,7 @@ export function DataTable({ columns, rows, onRowClick, sortable = true, pageSize
|
|
|
9
18
|
const numericKeys = useMemo(() => getNumericColumnKeys({ columns, rows }), [columns, rows]);
|
|
10
19
|
const activeSort = sortable && columns.some((column) => column.key === sort?.key) ? sort : null;
|
|
11
20
|
const sortedRows = useMemo(() => sortTableRows({ rows, sort: activeSort, numericKeys }), [rows, activeSort, numericKeys]);
|
|
12
|
-
const
|
|
13
|
-
const paging = requestedSize !== null;
|
|
14
|
-
const size = requestedSize ?? Math.max(rows.length, 1);
|
|
15
|
-
const pageCount = Math.max(1, Math.ceil(rows.length / size));
|
|
16
|
-
// Clamp during render so a smaller result set never shows a stale, empty page.
|
|
17
|
-
const page = paging ? Math.min(requestedPage, pageCount - 1) : 0;
|
|
18
|
-
const start = page * size;
|
|
21
|
+
const { paging, size, pageCount, page, start } = resolveTablePage({ pageSize, rowCount: rows.length, requestedPage });
|
|
19
22
|
const visibleRows = sortedRows.slice(start, start + size);
|
|
20
23
|
return (_jsxs("div", { className: "jini-data-table-frame", "data-table-provider": "shadcn", children: [_jsxs(Table, { className: "jini-data-table", children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: columns.map((column) => (_jsx(TableHead, { scope: "col", "data-numeric": numericKeys.has(column.key), "aria-sort": sortable ? (activeSort?.key === column.key ? activeSort.direction : 'none') : undefined, children: sortable ? (_jsxs("button", { type: "button", className: "jini-data-table-sort", onClick: () => {
|
|
21
24
|
setSort({ key: column.key, direction: activeSort?.key === column.key && activeSort.direction === 'ascending'
|
|
@@ -12,11 +12,11 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
|
|
|
12
12
|
key: z.ZodString;
|
|
13
13
|
label: z.ZodString;
|
|
14
14
|
}, "strict", z.ZodTypeAny, {
|
|
15
|
-
key: string;
|
|
16
15
|
label: string;
|
|
17
|
-
}, {
|
|
18
16
|
key: string;
|
|
17
|
+
}, {
|
|
19
18
|
label: string;
|
|
19
|
+
key: string;
|
|
20
20
|
}>, "many">;
|
|
21
21
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
22
22
|
sortable: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -26,11 +26,11 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
|
|
|
26
26
|
key: z.ZodString;
|
|
27
27
|
label: z.ZodString;
|
|
28
28
|
}, "strict", z.ZodTypeAny, {
|
|
29
|
-
key: string;
|
|
30
29
|
label: string;
|
|
31
|
-
}, {
|
|
32
30
|
key: string;
|
|
31
|
+
}, {
|
|
33
32
|
label: string;
|
|
33
|
+
key: string;
|
|
34
34
|
}>, "many">;
|
|
35
35
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
36
36
|
sortable: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -40,11 +40,11 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
|
|
|
40
40
|
key: z.ZodString;
|
|
41
41
|
label: z.ZodString;
|
|
42
42
|
}, "strict", z.ZodTypeAny, {
|
|
43
|
-
key: string;
|
|
44
43
|
label: string;
|
|
45
|
-
}, {
|
|
46
44
|
key: string;
|
|
45
|
+
}, {
|
|
47
46
|
label: string;
|
|
47
|
+
key: string;
|
|
48
48
|
}>, "many">;
|
|
49
49
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
50
50
|
sortable: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -2,45 +2,26 @@ export function buildMentionToken(label) {
|
|
|
2
2
|
return label.startsWith('@') ? label : `@${label}`;
|
|
3
3
|
}
|
|
4
4
|
export function parseMentionParts(text, entities, options = {}) {
|
|
5
|
-
|
|
6
|
-
return null;
|
|
5
|
+
// An empty string never contains '@', so this one check also covers `!text`.
|
|
7
6
|
if (!text.includes('@'))
|
|
8
7
|
return null;
|
|
9
|
-
const
|
|
10
|
-
|
|
8
|
+
const scan = {
|
|
9
|
+
known: getMentionTokenIndex(entities),
|
|
10
|
+
highlightUnknown: options.highlightUnknown ?? true,
|
|
11
|
+
};
|
|
11
12
|
const parts = [];
|
|
12
|
-
let scanStart = 0;
|
|
13
13
|
let copiedUntil = 0;
|
|
14
|
-
let
|
|
15
|
-
while (
|
|
16
|
-
const
|
|
17
|
-
if (
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
scanStart = start + 1;
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
const knownMatch = findKnownMentionAt(text, known, start);
|
|
24
|
-
const unknownMatch = highlightUnknown ? findUnknownMentionAt(text, start) : null;
|
|
25
|
-
const match = knownMatch && (!unknownMatch || knownMatch.token.length >= unknownMatch.token.length)
|
|
26
|
-
? knownMatch
|
|
27
|
-
: unknownMatch;
|
|
28
|
-
if (!match) {
|
|
29
|
-
scanStart = start + 1;
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
if (match.start > copiedUntil) {
|
|
33
|
-
parts.push({ kind: 'text', text: text.slice(copiedUntil, match.start) });
|
|
34
|
-
}
|
|
35
|
-
parts.push({
|
|
36
|
-
kind: 'mention',
|
|
37
|
-
entity: match.entity,
|
|
38
|
-
text: match.token,
|
|
39
|
-
});
|
|
40
|
-
found = true;
|
|
41
|
-
copiedUntil = match.start + match.token.length;
|
|
42
|
-
scanStart = copiedUntil;
|
|
14
|
+
let start = text.indexOf('@');
|
|
15
|
+
while (start !== -1) {
|
|
16
|
+
const match = findMentionAt({ ...scan, text, start });
|
|
17
|
+
if (match)
|
|
18
|
+
copiedUntil = appendMatch({ parts, text, copiedUntil, match });
|
|
19
|
+
start = text.indexOf('@', match ? copiedUntil : start + 1);
|
|
43
20
|
}
|
|
21
|
+
// Every mention token is at least two characters ('@' plus one more), so
|
|
22
|
+
// `copiedUntil` only moves off 0 once a mention part has been pushed.
|
|
23
|
+
if (copiedUntil === 0)
|
|
24
|
+
return null;
|
|
44
25
|
if (copiedUntil < text.length) {
|
|
45
26
|
parts.push({ kind: 'text', text: text.slice(copiedUntil) });
|
|
46
27
|
}
|
|
@@ -53,9 +34,36 @@ export function parseMentionParts(text, entities, options = {}) {
|
|
|
53
34
|
// per this package's coverage-driven-refactor policy once the loop proved
|
|
54
35
|
// every branch of that pass was unreachable from this one real call site
|
|
55
36
|
// (Phase 9.5: a dead branch gets refactored out, not padded with a test).
|
|
56
|
-
return
|
|
37
|
+
return parts;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Pushes the plain text between `copiedUntil` and the match (when non-empty)
|
|
41
|
+
* followed by the mention part; returns the new `copiedUntil`.
|
|
42
|
+
*/
|
|
43
|
+
function appendMatch(at) {
|
|
44
|
+
const { parts, text, copiedUntil, match } = at;
|
|
45
|
+
if (match.start > copiedUntil) {
|
|
46
|
+
parts.push({ kind: 'text', text: text.slice(copiedUntil, match.start) });
|
|
47
|
+
}
|
|
48
|
+
parts.push({ kind: 'mention', entity: match.entity, text: match.token });
|
|
49
|
+
return match.start + match.token.length;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The mention starting at `scan.start`, or null. A known (trie) match wins
|
|
53
|
+
* unless the unknown-mention run at the same position is strictly longer.
|
|
54
|
+
*/
|
|
55
|
+
function findMentionAt(scan) {
|
|
56
|
+
const { text } = scan;
|
|
57
|
+
if (!isMentionBoundary(text, scan.start))
|
|
58
|
+
return null;
|
|
59
|
+
const knownMatch = findKnownMentionAt(text, scan.known, scan.start);
|
|
60
|
+
const unknownMatch = scan.highlightUnknown ? findUnknownMentionAt(text, scan.start) : null;
|
|
61
|
+
return knownMatch && (!unknownMatch || knownMatch.token.length >= unknownMatch.token.length)
|
|
62
|
+
? knownMatch
|
|
63
|
+
: unknownMatch;
|
|
57
64
|
}
|
|
58
65
|
const mentionTokenIndexCache = new WeakMap();
|
|
66
|
+
/** Root of the (cached, per entities-array) trie of every entity's `@token`. */
|
|
59
67
|
function getMentionTokenIndex(entities) {
|
|
60
68
|
const cached = mentionTokenIndexCache.get(entities);
|
|
61
69
|
if (cached)
|
|
@@ -101,18 +109,15 @@ function getMentionTokenIndex(entities) {
|
|
|
101
109
|
}
|
|
102
110
|
node = child;
|
|
103
111
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
node.token = token;
|
|
107
|
-
}
|
|
112
|
+
// First writer wins: two entities of different kinds can share a token.
|
|
113
|
+
node.entity ??= entity;
|
|
108
114
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return index;
|
|
115
|
+
mentionTokenIndexCache.set(entities, root);
|
|
116
|
+
return root;
|
|
112
117
|
}
|
|
113
|
-
function findKnownMentionAt(text,
|
|
118
|
+
function findKnownMentionAt(text, root, start) {
|
|
114
119
|
let best = null;
|
|
115
|
-
let node =
|
|
120
|
+
let node = root;
|
|
116
121
|
for (let i = start; i < text.length; i += 1) {
|
|
117
122
|
// `i < text.length` is the loop condition itself, so `text[i]` is always
|
|
118
123
|
// defined here — the `!` documents that instead of adding an
|
|
@@ -121,8 +126,8 @@ function findKnownMentionAt(text, index, start) {
|
|
|
121
126
|
node = node.children.get(text[i]);
|
|
122
127
|
if (!node)
|
|
123
128
|
break;
|
|
124
|
-
if (node.entity &&
|
|
125
|
-
best = { start, token: node.token, entity: node.entity };
|
|
129
|
+
if (node.entity && isMentionRightBoundary(text, i + 1)) {
|
|
130
|
+
best = { start, token: node.entity.token, entity: node.entity };
|
|
126
131
|
}
|
|
127
132
|
}
|
|
128
133
|
return best;
|
|
@@ -222,17 +227,15 @@ export function mentionTokenPresent(text, label) {
|
|
|
222
227
|
export function foldPresentMentions(text, present, known) {
|
|
223
228
|
const result = [...present];
|
|
224
229
|
const seen = new Set(present.map((e) => `${e.kind}:${e.id}`));
|
|
225
|
-
const parts = parseMentionParts(text, known, { highlightUnknown: false });
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
}
|
|
230
|
+
const parts = parseMentionParts(text, known, { highlightUnknown: false }) ?? [];
|
|
231
|
+
for (const part of parts) {
|
|
232
|
+
if (part.kind !== 'mention' || part.entity.kind === 'unknown')
|
|
233
|
+
continue;
|
|
234
|
+
const key = `${part.entity.kind}:${part.entity.id}`;
|
|
235
|
+
if (seen.has(key))
|
|
236
|
+
continue;
|
|
237
|
+
seen.add(key);
|
|
238
|
+
result.push(part.entity);
|
|
236
239
|
}
|
|
237
240
|
return result;
|
|
238
241
|
}
|