@jini-ai/ui 0.5.5 → 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.
Files changed (263) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/core/theme/validation.js +40 -38
  3. package/dist/features/a2ui/renderer.js +15 -13
  4. package/dist/features/about/react/components/AboutTab.js +64 -34
  5. package/dist/features/about/rules.d.ts +2 -2
  6. package/dist/features/about/rules.js +156 -129
  7. package/dist/features/admin-widgets/components/ImagePreviewModal.d.ts +4 -3
  8. package/dist/features/admin-widgets/components/ImagePreviewModal.js +6 -10
  9. package/dist/features/admin-widgets/components/InfoTip.d.ts +3 -2
  10. package/dist/features/admin-widgets/components/InfoTip.hooks.js +2 -0
  11. package/dist/features/admin-widgets/components/InfoTip.js +34 -7
  12. package/dist/features/admin-widgets/components/InfoTip.rules.d.ts +13 -0
  13. package/dist/features/admin-widgets/components/InfoTip.rules.js +43 -10
  14. package/dist/features/admin-widgets/components/Lightbox/Lightbox.d.ts +30 -0
  15. package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.d.ts +40 -0
  16. package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.js +128 -0
  17. package/dist/features/admin-widgets/components/Lightbox/Lightbox.js +18 -0
  18. package/dist/features/admin-widgets/components/MiddleTruncate.d.ts +14 -0
  19. package/dist/features/admin-widgets/components/MiddleTruncate.js +12 -0
  20. package/dist/features/admin-widgets/components/MiddleTruncate.rules.d.ts +20 -0
  21. package/dist/features/admin-widgets/components/MiddleTruncate.rules.js +21 -0
  22. package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.d.ts +18 -0
  23. package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.d.ts +16 -0
  24. package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.js +45 -0
  25. package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.js +18 -0
  26. package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.rules.d.ts +32 -0
  27. package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.rules.js +26 -0
  28. package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.js +29 -14
  29. package/dist/features/admin-widgets/index.d.ts +14 -2
  30. package/dist/features/admin-widgets/index.js +7 -1
  31. package/dist/features/admin-widgets/styles/admin-widgets.css +1 -0
  32. package/dist/features/asset-grid/react/components/AssetCard.js +7 -1
  33. package/dist/features/asset-grid/react/components/AssetGrid.d.ts +1 -1
  34. package/dist/features/asset-grid/react/components/AssetGrid.js +38 -18
  35. package/dist/features/asset-grid/react/components/useAssetGridFilters.d.ts +21 -0
  36. package/dist/features/asset-grid/react/components/useAssetGridFilters.js +19 -0
  37. package/dist/features/asset-grid/react/hooks/useAssetGridKeyboardShortcuts.js +16 -11
  38. package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.d.ts +2 -0
  39. package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.js +35 -11
  40. package/dist/features/asset-tree-browser/react/components/AssetTreeBrowser.d.ts +6 -6
  41. package/dist/features/asset-tree-browser/react/components/AssetTreeBrowser.js +10 -129
  42. package/dist/features/asset-tree-browser/react/components/AssetTreeBrowserParts.d.ts +50 -0
  43. package/dist/features/asset-tree-browser/react/components/AssetTreeBrowserParts.js +95 -0
  44. package/dist/features/asset-tree-browser/react/components/useAssetTreeBrowserController.d.ts +56 -0
  45. package/dist/features/asset-tree-browser/react/components/useAssetTreeBrowserController.js +80 -0
  46. package/dist/features/asset-tree-browser/rules.js +40 -22
  47. package/dist/features/browser-chrome/rules.js +74 -70
  48. package/dist/features/charts/browser.js +11 -5
  49. package/dist/features/charts/react.js +2 -2
  50. package/dist/features/charts/table.js +2 -2
  51. package/dist/features/command-palette/react/hooks/useCommandPalette.js +3 -9
  52. package/dist/features/connectors/ConnectorsBrowser.d.ts +4 -4
  53. package/dist/features/connectors/ConnectorsBrowser.js +26 -14
  54. package/dist/features/connectors/components/ConnectorCard.js +67 -38
  55. package/dist/features/connectors/components/ConnectorDetailDrawer.js +62 -31
  56. package/dist/features/connectors/components/ConnectorGrid.js +11 -6
  57. package/dist/features/connectors/hooks/useConnectorAuthorization.js +6 -0
  58. package/dist/features/connectors/hooks/useConnectorCatalog.d.ts +2 -0
  59. package/dist/features/connectors/hooks/useConnectorCatalog.js +32 -13
  60. package/dist/features/connectors/hooks/useWiredConnectorsBrowser.d.ts +3 -3
  61. package/dist/features/connectors/rules.d.ts +8 -1
  62. package/dist/features/connectors/rules.js +42 -20
  63. package/dist/features/connectors/types.d.ts +11 -0
  64. package/dist/features/execution/constants.d.ts +4 -10
  65. package/dist/features/execution/constants.js +9 -94
  66. package/dist/features/execution/react/components/ByokProviderForm.d.ts +2 -4
  67. package/dist/features/execution/react/components/ByokProviderForm.js +140 -43
  68. package/dist/features/execution/react/components/ExecutionTab.d.ts +1 -2
  69. package/dist/features/execution/react/components/ExecutionTab.js +52 -30
  70. package/dist/features/execution/react/components/LocalCliAgentCard.js +12 -3
  71. package/dist/features/execution/react/components/LocalCliAgentList.js +14 -3
  72. package/dist/features/execution/react/components/LocalCliAgentSettings.js +14 -3
  73. package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +54 -36
  74. package/dist/features/execution/react/hooks/useReasoningControl.js +114 -78
  75. package/dist/features/execution/rules.d.ts +2 -2
  76. package/dist/features/execution/rules.js +31 -15
  77. package/dist/features/execution/types.d.ts +4 -42
  78. package/dist/features/execution/types.js +0 -17
  79. package/dist/features/external-mcp/react/components/ExternalMcpTab.d.ts +6 -2
  80. package/dist/features/external-mcp/react/components/ExternalMcpTab.js +9 -2
  81. package/dist/features/file-dropzone/react/components/FileDropzone.js +24 -25
  82. package/dist/features/file-dropzone/react/components/FileDropzoneLightbox.d.ts +2 -2
  83. package/dist/features/file-dropzone/react/components/FileDropzoneLightbox.js +35 -30
  84. package/dist/features/file-dropzone/react/components/FileDropzoneThumbnailGrid.js +30 -24
  85. package/dist/features/file-dropzone/react/components/FileDropzoneZone.d.ts +14 -0
  86. package/dist/features/file-dropzone/react/components/FileDropzoneZone.js +26 -0
  87. package/dist/features/html-editor/canvas-content-wrapper.js +13 -13
  88. package/dist/features/html-editor/canvas-embed-placeholders.js +46 -37
  89. package/dist/features/html-editor/css.js +76 -69
  90. package/dist/features/html-editor/editor-blocks.js +47 -33
  91. package/dist/features/html-editor/editor-serialization.js +6 -5
  92. package/dist/features/html-editor/protected-elements.js +39 -28
  93. package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +4 -4
  94. package/dist/features/html-editor/source-splice.js +51 -30
  95. package/dist/features/i18n/dictionaries/settings-dialog.ja.js +1 -0
  96. package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +1 -0
  97. package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +1 -0
  98. package/dist/features/i18n/locale.js +20 -16
  99. package/dist/features/iframe-pool/react/dom-sync.js +8 -6
  100. package/dist/features/integrations/react/components/CodexInstallToggleButton.js +19 -4
  101. package/dist/features/integrations/react/components/IntegrationsTab.js +60 -14
  102. package/dist/features/interactive-ui/interactive-ui.css +1 -1
  103. package/dist/features/interactive-ui/providers/shadcn/data-table.js +10 -7
  104. package/dist/features/lexical-rich-text-editor/mention-parser.js +60 -57
  105. package/dist/features/lexical-rich-text-editor/react/hooks/useKeyboardCommands.js +33 -38
  106. package/dist/features/lexical-rich-text-editor/rules.js +87 -74
  107. package/dist/features/lexical-rich-text-editor/serialize.js +27 -25
  108. package/dist/features/mcp-ui/secret-card.js +111 -61
  109. package/dist/features/mcp-ui/surfaces/confirmation.js +39 -21
  110. package/dist/features/mcp-ui/surfaces/document.d.ts +1 -1
  111. package/dist/features/mcp-ui/surfaces/document.js +10 -2
  112. package/dist/features/mcp-ui/surfaces/fields.js +30 -50
  113. package/dist/features/mcp-ui/surfaces/form.d.ts +6 -0
  114. package/dist/features/mcp-ui/surfaces/form.js +43 -21
  115. package/dist/features/mcp-ui/surfaces/outcome.js +30 -20
  116. package/dist/features/mcp-ui/surfaces/text-input.js +33 -21
  117. package/dist/features/mcp-ui/surfaces/tokens.d.ts +6 -1
  118. package/dist/features/mcp-ui/surfaces/tokens.js +5 -2
  119. package/dist/features/media-providers/constants.d.ts +1 -0
  120. package/dist/features/media-providers/constants.js +2 -81
  121. package/dist/features/media-providers/index.d.ts +1 -1
  122. package/dist/features/media-providers/ports.d.ts +2 -0
  123. package/dist/features/media-providers/react/components/MediaProviderCard.d.ts +22 -0
  124. package/dist/features/media-providers/react/components/MediaProviderCard.js +50 -0
  125. package/dist/features/media-providers/react/components/MediaProvidersTab.d.ts +5 -6
  126. package/dist/features/media-providers/react/components/MediaProvidersTab.js +40 -72
  127. package/dist/features/media-providers/react/components/media-providers-tab-labels.d.ts +11 -0
  128. package/dist/features/media-providers/react/components/media-providers-tab-labels.js +57 -0
  129. package/dist/features/media-providers/react/hooks/useMediaProvidersTab.d.ts +4 -2
  130. package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +37 -23
  131. package/dist/features/media-providers/rules.js +17 -10
  132. package/dist/features/media-providers/types.d.ts +4 -22
  133. package/dist/features/media-providers/types.js +3 -8
  134. package/dist/features/memory/formatters.js +127 -92
  135. package/dist/features/memory/react/components/MemoryConnectedPanel.js +92 -36
  136. package/dist/features/memory/react/components/MemoryList.js +37 -18
  137. package/dist/features/memory/react/hooks/useMemoryExtractions.store.js +42 -36
  138. package/dist/features/notifications/react/components/NotificationsTab.js +28 -28
  139. package/dist/features/observability/long-task.d.ts +0 -12
  140. package/dist/features/observability/long-task.js +15 -19
  141. package/dist/features/observability/resource-error.d.ts +0 -10
  142. package/dist/features/observability/resource-error.js +18 -13
  143. package/dist/features/observability/stuck-run.js +10 -6
  144. package/dist/features/observability/telemetry-url.d.ts +6 -0
  145. package/dist/features/observability/telemetry-url.js +16 -0
  146. package/dist/features/observability/white-screen.js +12 -24
  147. package/dist/features/panel-kit/fetch-query/adapter.react.d.ts +2 -2
  148. package/dist/features/panel-kit/fetch-query/adapter.react.js +4 -2
  149. package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +46 -33
  150. package/dist/features/panel-kit/helpers/standing-draft-local-backup.js +3 -1
  151. package/dist/features/panel-kit/hooks/use-settings-slice.hooks.js +3 -1
  152. package/dist/features/privacy/react/components/PrivacyTab.js +24 -13
  153. package/dist/features/progress-card/components/ProgressCard.js +7 -3
  154. package/dist/features/progress-card/reference-adapters.js +59 -54
  155. package/dist/features/project-locations/react/components/ProjectLocationsTab.js +24 -15
  156. package/dist/features/project-locations/react/hooks/useProjectLocationsTab.d.ts +8 -0
  157. package/dist/features/project-locations/react/hooks/useProjectLocationsTab.js +31 -23
  158. package/dist/features/resource-dashboard/react/components/ResourceBoard.js +6 -47
  159. package/dist/features/resource-dashboard/react/components/ResourceBoardView.d.ts +2 -2
  160. package/dist/features/resource-dashboard/react/components/ResourceBoardView.js +3 -6
  161. package/dist/features/resource-dashboard/react/components/ResourceBoardViewParts.d.ts +15 -0
  162. package/dist/features/resource-dashboard/react/components/ResourceBoardViewParts.js +35 -0
  163. package/dist/features/resource-dashboard/react/components/ResourceCard.js +5 -16
  164. package/dist/features/resource-dashboard/react/components/ResourceCardParts.d.ts +34 -0
  165. package/dist/features/resource-dashboard/react/components/ResourceCardParts.js +34 -0
  166. package/dist/features/resource-dashboard/react/components/ResourceRowList.js +3 -1
  167. package/dist/features/resource-dashboard/react/components/ResourceRowListItem.js +2 -2
  168. package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.d.ts +19 -0
  169. package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.js +11 -0
  170. package/dist/features/resource-dashboard/react/components/ResourceRowListView.d.ts +1 -1
  171. package/dist/features/resource-dashboard/react/components/ResourceRowListView.js +4 -4
  172. package/dist/features/resource-dashboard/react/components/ResourceRowListViewParts.d.ts +10 -0
  173. package/dist/features/resource-dashboard/react/components/ResourceRowListViewParts.js +20 -0
  174. package/dist/features/resource-dashboard/react/components/resourceBoardProps.d.ts +48 -0
  175. package/dist/features/resource-dashboard/react/components/resourceBoardProps.js +70 -0
  176. package/dist/features/resource-dashboard/react/components/resourceRowListProps.d.ts +19 -0
  177. package/dist/features/resource-dashboard/react/components/resourceRowListProps.js +14 -0
  178. package/dist/features/resource-dashboard/react/components/translatedErrorLabelProps.d.ts +16 -0
  179. package/dist/features/resource-dashboard/react/components/translatedErrorLabelProps.js +13 -0
  180. package/dist/features/resource-dashboard/rules.js +2 -8
  181. package/dist/features/sketch-editor/dom.js +150 -99
  182. package/dist/features/sketch-editor/react/components/SketchEditor.js +26 -15
  183. package/dist/features/skills/react/components/SkillDraftForm.js +13 -19
  184. package/dist/features/skills/react/components/SkillDraftForm.labels.d.ts +31 -0
  185. package/dist/features/skills/react/components/SkillDraftForm.labels.js +54 -0
  186. package/dist/features/skills/react/components/SkillRow.js +38 -18
  187. package/dist/features/skills/react/components/SkillRow.labels.d.ts +7 -0
  188. package/dist/features/skills/react/components/SkillRow.labels.js +18 -0
  189. package/dist/features/skills/react/components/SkillsTab.js +24 -14
  190. package/dist/features/skills/react/components/SkillsTab.labels.d.ts +7 -0
  191. package/dist/features/skills/react/components/SkillsTab.labels.js +11 -0
  192. package/dist/features/skills/rules.js +32 -23
  193. package/dist/features/source-config-list/agent-handles.js +2 -1
  194. package/dist/features/source-config-list/dependencies.js +53 -49
  195. package/dist/features/source-config-list/index.d.ts +3 -3
  196. package/dist/features/source-config-list/react/components/SourceConfigAddForm.d.ts +6 -5
  197. package/dist/features/source-config-list/react/components/SourceConfigAddForm.js +38 -7
  198. package/dist/features/source-config-list/react/components/SourceConfigField.js +69 -25
  199. package/dist/features/source-config-list/react/components/SourceConfigItemCard.d.ts +6 -5
  200. package/dist/features/source-config-list/react/components/SourceConfigItemCard.js +76 -20
  201. package/dist/features/source-config-list/react/components/SourceConfigListView.d.ts +5 -3
  202. package/dist/features/source-config-list/react/components/SourceConfigListView.js +33 -3
  203. package/dist/features/source-config-list/react/components/SourceConfigTestControl.js +17 -1
  204. package/dist/features/source-config-list/react/components/SourceConfigTrustOptions.d.ts +11 -0
  205. package/dist/features/source-config-list/react/components/SourceConfigTrustOptions.js +12 -0
  206. package/dist/features/source-config-list/types.d.ts +14 -0
  207. package/dist/features/tab-launcher-menu/react/components/TabLauncherMenu.js +25 -1
  208. package/dist/features/tab-launcher-menu/react/hooks/useTabLauncherMenu.js +15 -16
  209. package/dist/features/tab-strip/react/components/TabBar.js +8 -1
  210. package/dist/features/tabbed-dialog/react/components/TabbedDialog.js +8 -30
  211. package/dist/features/tabbed-dialog/react/components/TabbedDialogChrome.d.ts +15 -0
  212. package/dist/features/tabbed-dialog/react/components/TabbedDialogChrome.js +8 -0
  213. package/dist/features/tabbed-dialog/react/components/TabbedDialogHeader.d.ts +12 -0
  214. package/dist/features/tabbed-dialog/react/components/TabbedDialogHeader.js +6 -0
  215. package/dist/features/tabbed-dialog/react/components/TabbedDialogSidebar.d.ts +27 -0
  216. package/dist/features/tabbed-dialog/react/components/TabbedDialogSidebar.js +12 -0
  217. package/dist/features/tabbed-dialog/react/components/tabbedDialogView.d.ts +43 -0
  218. package/dist/features/tabbed-dialog/react/components/tabbedDialogView.js +59 -0
  219. package/dist/features/version-manager/dependencies.d.ts +3 -1
  220. package/dist/features/version-manager/dependencies.js +3 -2
  221. package/dist/features/version-manager/react/components/VersionManagerModal.js +10 -6
  222. package/dist/features/version-manager/react/hooks/useVersionManager.js +7 -4
  223. package/dist/features/viewer-shell/react/components/CommentSidePanel.js +103 -50
  224. package/dist/features/viewer-shell/react/components/MarkdownSplitPane.js +28 -8
  225. package/dist/features/viewer-shell/react/hooks/useCommentReorder.js +22 -16
  226. package/dist/features/viewer-shell/rules.js +19 -23
  227. package/dist/react/components/CustomSelect.d.ts +38 -1
  228. package/dist/react/components/CustomSelect.js +94 -38
  229. package/dist/react/components/OnboardingDropdown.js +20 -8
  230. package/dist/react/components/RemixIcon.stylesheet.js +3 -1
  231. package/dist/react/components/Toast.js +13 -2
  232. package/dist/react/components/TooltipLayer.js +5 -14
  233. package/dist/react/components/WorkingDirPicker.js +78 -50
  234. package/dist/react/components/remixicon-font-recovery.js +38 -30
  235. package/dist/react/components/select-popover.d.ts +8 -6
  236. package/dist/react/components/select-popover.js +33 -29
  237. package/dist/react/mcp-ui/McpUiHost.d.ts +1 -1
  238. package/dist/react/mcp-ui/McpUiHost.js +10 -11
  239. package/dist/react/mcp-ui/host-message-source.d.ts +14 -2
  240. package/dist/react/mcp-ui/host-message-source.js +15 -5
  241. package/dist/react/mcp-ui/mcp-ui-host-frame.d.ts +41 -0
  242. package/dist/react/mcp-ui/mcp-ui-host-frame.js +39 -0
  243. package/dist/renderers/annotation-canvas/react/components/AnnotationCanvas.js +97 -69
  244. package/dist/renderers/preview-modal-shell/react/components/PreviewModalShell.js +59 -30
  245. package/dist/renderers/react/components/ArtifactView.js +9 -6
  246. package/dist/renderers/srcdoc/build.d.ts +4 -1
  247. package/dist/renderers/srcdoc/build.js +62 -48
  248. package/dist/styles/admin.css +29 -14
  249. package/dist/styles/lightbox.css +142 -0
  250. package/dist/styles/variables.css +128 -0
  251. package/dist/theme/apply.js +9 -5
  252. package/dist/utils/auto-open-file.d.ts +2 -1
  253. package/dist/utils/auto-open-file.js +69 -85
  254. package/dist/utils/markdown-scroll-sync.js +108 -87
  255. package/dist/utils/polygon-selection.js +25 -26
  256. package/dist/utils/smooth-scroll-to-top.d.ts +1 -1
  257. package/dist/utils/smooth-scroll-to-top.js +2 -32
  258. package/dist/utils/sse.js +26 -26
  259. package/dist/utils/unit-bezier.d.ts +7 -0
  260. package/dist/utils/unit-bezier.js +38 -0
  261. package/package.json +7 -10
  262. package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.d.ts +0 -13
  263. package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.js +0 -46
@@ -1,9 +1,9 @@
1
- import type { SourceConfigItem, SourceFieldSpec, SourceTestResult, SourceTrustOption, SourceUpdateInput } from '../../types.js';
1
+ import type { SourceConfigItem, SourceFieldSpec, SourceTestResult, SourceTrustSelectorProps, SourceUpdateInput } from '../../types.js';
2
2
  import type { SourceConfigListCapabilities } from '../hooks/useSourceConfigList.js';
3
- export interface SourceConfigItemCardProps<TSource extends SourceConfigItem> {
3
+ /** Every item-card prop except the trust selector's pair (see {@link SourceTrustSelectorProps}). */
4
+ export interface SourceConfigItemCardBaseProps<TSource extends SourceConfigItem> {
4
5
  source: TSource;
5
6
  fieldSpecs: readonly SourceFieldSpec[];
6
- trustOptions?: readonly SourceTrustOption[];
7
7
  capabilities: SourceConfigListCapabilities;
8
8
  removing: boolean;
9
9
  refreshing: boolean;
@@ -14,7 +14,6 @@ export interface SourceConfigItemCardProps<TSource extends SourceConfigItem> {
14
14
  testResult?: SourceTestResult;
15
15
  onRefresh: () => void;
16
16
  onRemove: () => void;
17
- onTrustChange: (trust: string) => void;
18
17
  onTest: () => void;
19
18
  /** Patches this item's `label`/`enabled`/`fields`. Only ever called when `capabilities.canUpdate` is true. */
20
19
  onUpdate: (patch: SourceUpdateInput) => void;
@@ -33,6 +32,8 @@ export interface SourceConfigItemCardProps<TSource extends SourceConfigItem> {
33
32
  */
34
33
  agentHandle?: string;
35
34
  }
35
+ /** `onTrustChange` is required only together with `trustOptions` — see {@link SourceTrustSelectorProps}. */
36
+ export type SourceConfigItemCardProps<TSource extends SourceConfigItem> = SourceConfigItemCardBaseProps<TSource> & SourceTrustSelectorProps;
36
37
  /**
37
38
  * One configured source: a collapsed summary row (an always-visible
38
39
  * enable/disable toggle when the source declares `enabled` at all, plus
@@ -68,5 +69,5 @@ export interface SourceConfigItemCardProps<TSource extends SourceConfigItem> {
68
69
  * state privately. That sequencing is the honest shape of the card, not a
69
70
  * limitation of the markup.
70
71
  */
71
- export declare function SourceConfigItemCard<TSource extends SourceConfigItem>({ source, fieldSpecs, trustOptions, capabilities, removing, refreshing, settingTrust, testing, updating, testResult, onRefresh, onRemove, onTrustChange, onTest, onUpdate, agentHandle, }: SourceConfigItemCardProps<TSource>): import("react").JSX.Element;
72
+ export declare function SourceConfigItemCard<TSource extends SourceConfigItem>(props: SourceConfigItemCardProps<TSource>): import("react").JSX.Element;
72
73
  //# sourceMappingURL=SourceConfigItemCard.d.ts.map
@@ -1,10 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { useT } from '../../../i18n/index.js';
4
4
  import { sourceConfigActionHandle, sourceConfigAgentProps, sourceConfigFieldHandle } from '../../agent-handles.js';
5
5
  import { issueForField, maskFieldValue, sourceDisplayLabel, validateSourceDraft, } from '../../rules.js';
6
6
  import { SourceConfigField } from './SourceConfigField.js';
7
7
  import { SourceConfigTestControl } from './SourceConfigTestControl.js';
8
+ import { SourceConfigTrustOptions } from './SourceConfigTrustOptions.js';
8
9
  /**
9
10
  * One configured source: a collapsed summary row (an always-visible
10
11
  * enable/disable toggle when the source declares `enabled` at all, plus
@@ -40,18 +41,58 @@ import { SourceConfigTestControl } from './SourceConfigTestControl.js';
40
41
  * state privately. That sequencing is the honest shape of the card, not a
41
42
  * limitation of the markup.
42
43
  */
43
- export function SourceConfigItemCard({ source, fieldSpecs, trustOptions, capabilities, removing, refreshing, settingTrust, testing, updating, testResult, onRefresh, onRemove, onTrustChange, onTest, onUpdate, agentHandle, }) {
44
- const t = useT();
44
+ export function SourceConfigItemCard(props) {
45
+ const { source, fieldSpecs, agentHandle } = props;
45
46
  const [expanded, setExpanded] = useState(false);
47
+ const edit = useItemCardEdit(props);
48
+ const label = sourceDisplayLabel(source, fieldSpecs);
49
+ return (_jsxs("article", { className: `source-config-item-card${expanded ? ' is-expanded' : ''}`, "data-testid": "source-config-item-card", ...sourceConfigAgentProps(agentHandle, { role: 'region', label }), children: [_jsxs("div", { className: "source-config-item-card-head", children: [_jsx(ItemCardEnabledToggle, { ...props, label: label }), _jsx(ItemCardSummary, { ...props, label: label, expanded: expanded, onToggle: () => setExpanded((current) => !current) }), _jsx(ItemCardActions, { ...props, label: label })] }), expanded ? _jsx(ItemCardBody, { ...props, label: label, edit: edit }) : null] }));
50
+ }
51
+ function isAnyActionPending({ removing, refreshing, settingTrust, updating }) {
52
+ return removing || refreshing || settingTrust || updating;
53
+ }
54
+ /** Always visible (no expand needed) — but only when the source declares `enabled` at all and the host can update it. */
55
+ function ItemCardEnabledToggle({ source, capabilities, updating, onUpdate, agentHandle, label }) {
56
+ const t = useT();
57
+ if (source.enabled === undefined || !capabilities.canUpdate)
58
+ return null;
59
+ const enabledLabel = t('Enable {name}', { name: label });
60
+ return (_jsx("label", { className: "source-config-item-card-enabled-toggle", title: source.enabled ? t('Enabled') : t('Disabled'), children: _jsx("input", { type: "checkbox", checked: source.enabled, disabled: updating, "aria-label": enabledLabel, ...sourceConfigAgentProps(agentHandle, { role: 'checkbox', label: enabledLabel, action: 'enabled' }), onChange: (event) => onUpdate({ enabled: event.target.checked }) }) }));
61
+ }
62
+ function ItemCardSummary({ source, trustOptions, agentHandle, label, expanded, onToggle, }) {
63
+ const t = useT();
64
+ const trustOption = trustOptions?.find((option) => option.value === source.trust);
65
+ return (_jsxs("button", { type: "button", className: "source-config-item-card-summary", ...sourceConfigAgentProps(agentHandle, {
66
+ role: 'button',
67
+ // Stable ontology, so it must not read "Collapse" once expanded — see `agent-handles.ts`.
68
+ label: t('Show or hide details for {name}', { name: label }),
69
+ action: 'expand',
70
+ }), onClick: onToggle, "aria-expanded": expanded, children: [_jsx("span", { className: "source-config-item-card-label", children: label }), source.trust ? _jsx("span", { className: "source-config-item-card-trust-badge", children: t(trustOption?.label ?? source.trust) }) : null] }));
71
+ }
72
+ /** The trust selector (capability- and options-gated), Refresh (capability-gated) and the always-present Remove. */
73
+ function ItemCardActions(props) {
74
+ const { capabilities, refreshing, removing, onRefresh, onRemove, agentHandle } = props;
75
+ const t = useT();
76
+ const anyActionPending = isAnyActionPending(props);
77
+ return (_jsxs("div", { className: "source-config-item-card-actions", children: [_jsx(ItemCardTrustSelect, { ...props }), capabilities.canRefresh ? (_jsx("button", { type: "button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Refresh'), action: 'refresh' }), onClick: onRefresh, disabled: anyActionPending, children: refreshing ? t('Refreshing…') : t('Refresh') })) : null, _jsx("button", { type: "button", className: "source-config-item-card-remove", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Remove'), action: 'remove' }), onClick: onRemove, disabled: anyActionPending, children: removing ? t('Removing…') : t('Remove') })] }));
78
+ }
79
+ function ItemCardTrustSelect(props) {
80
+ const t = useT();
81
+ // Narrow on `props` itself (not a destructured copy) so the non-empty `trustOptions` check also
82
+ // proves `onTrustChange` present — the `SourceTrustSelectorProps` union binds the two.
83
+ if (!props.capabilities.canSetTrust || !props.trustOptions || props.trustOptions.length === 0)
84
+ return null;
85
+ const { source, trustOptions, settingTrust, onTrustChange, agentHandle, label } = props;
86
+ const trustLabel = t('Trust level for {name}', { name: label });
87
+ return (_jsx("select", { value: source.trust ?? '', disabled: settingTrust, "aria-label": trustLabel, ...sourceConfigAgentProps(agentHandle, { role: 'field', label: trustLabel, action: 'trust' }), onChange: (event) => onTrustChange(event.target.value), children: _jsx(SourceConfigTrustOptions, { trust: source.trust, trustOptions: trustOptions }) }));
88
+ }
89
+ /** The private expand-to-edit draft: label + fields, seeded from the source each time editing starts. */
90
+ function useItemCardEdit({ source, fieldSpecs, onUpdate }) {
46
91
  const [editing, setEditing] = useState(false);
47
92
  const [editLabel, setEditLabel] = useState('');
48
93
  const [editFields, setEditFields] = useState({});
49
94
  /** Errors stay hidden until the operator actually tries to save, matching the add form's `submitAttempted`. */
50
95
  const [saveAttempted, setSaveAttempted] = useState(false);
51
- const label = sourceDisplayLabel(source, fieldSpecs);
52
- const trustOption = trustOptions?.find((option) => option.value === source.trust);
53
- const editableTrustOptions = capabilities.canSetTrust && trustOptions && trustOptions.length > 0 ? trustOptions : null;
54
- const anyActionPending = removing || refreshing || settingTrust || updating;
55
96
  // The SAME validation the add form runs (`useSourceConfigAddForm`). The edit
56
97
  // path used to run none at all — not even the required-field check — so a
57
98
  // source added through a validated form could be edited into a state the form
@@ -75,18 +116,33 @@ export function SourceConfigItemCard({ source, fieldSpecs, trustOptions, capabil
75
116
  setSaveAttempted(false);
76
117
  setEditing(false);
77
118
  };
78
- const enabledLabel = t('Enable {name}', { name: label });
79
- const trustLabel = t('Trust level for {name}', { name: label });
80
- return (_jsxs("article", { className: `source-config-item-card${expanded ? ' is-expanded' : ''}`, "data-testid": "source-config-item-card", ...sourceConfigAgentProps(agentHandle, { role: 'region', label }), children: [_jsxs("div", { className: "source-config-item-card-head", children: [source.enabled !== undefined && capabilities.canUpdate ? (_jsx("label", { className: "source-config-item-card-enabled-toggle", title: source.enabled ? t('Enabled') : t('Disabled'), children: _jsx("input", { type: "checkbox", checked: source.enabled, disabled: updating, "aria-label": enabledLabel, ...sourceConfigAgentProps(agentHandle, { role: 'checkbox', label: enabledLabel, action: 'enabled' }), onChange: (event) => onUpdate({ enabled: event.target.checked }) }) })) : null, _jsxs("button", { type: "button", className: "source-config-item-card-summary", ...sourceConfigAgentProps(agentHandle, {
81
- role: 'button',
82
- // Stable ontology, so it must not read "Collapse" once expanded — see `agent-handles.ts`.
83
- label: t('Show or hide details for {name}', { name: label }),
84
- action: 'expand',
85
- }), onClick: () => setExpanded((current) => !current), "aria-expanded": expanded, children: [_jsx("span", { className: "source-config-item-card-label", children: label }), source.trust ? (_jsx("span", { className: "source-config-item-card-trust-badge", children: t(trustOption?.label ?? source.trust) })) : null] }), _jsxs("div", { className: "source-config-item-card-actions", children: [editableTrustOptions ? (_jsxs("select", { value: source.trust ?? '', disabled: settingTrust, "aria-label": trustLabel, ...sourceConfigAgentProps(agentHandle, { role: 'field', label: trustLabel, action: 'trust' }), onChange: (event) => onTrustChange(event.target.value), children: [!source.trust ? (_jsx("option", { value: "", disabled: true, hidden: true, children: t('Select…') })) : null, editableTrustOptions.map((option) => (_jsx("option", { value: option.value, children: t(option.label) }, option.value)))] })) : null, capabilities.canRefresh ? (_jsx("button", { type: "button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Refresh'), action: 'refresh' }), onClick: onRefresh, disabled: anyActionPending, children: refreshing ? t('Refreshing…') : t('Refresh') })) : null, _jsx("button", { type: "button", className: "source-config-item-card-remove", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Remove'), action: 'remove' }), onClick: onRemove, disabled: anyActionPending, children: removing ? t('Removing…') : t('Remove') })] })] }), expanded ? (_jsxs("div", { className: "source-config-item-card-body", children: [capabilities.canUpdate ? (_jsx("div", { className: "source-config-item-card-edit-toggle", children: editing ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Save'), action: 'save' }), onClick: saveEditing, disabled: updating || (saveAttempted && !editValidation.ok), children: t('Save') }), _jsx("button", { type: "button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Cancel'), action: 'cancel' }), onClick: cancelEditing, disabled: updating, children: t('Cancel') })] })) : (_jsx("button", { type: "button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Edit'), action: 'edit' }), onClick: startEditing, disabled: anyActionPending, children: t('Edit') })) })) : null, editing ? (_jsxs("div", { className: "source-config-item-card-edit-fields", children: [_jsxs("label", { className: "source-config-field", htmlFor: `source-config-item-card-${source.id}-label`, children: [_jsx("span", { className: "source-config-field-label", children: t('Label') }), _jsx("input", { id: `source-config-item-card-${source.id}-label`, type: "text", value: editLabel, placeholder: label, ...sourceConfigAgentProps(agentHandle, { role: 'field', label: t('Label'), action: 'label' }), onChange: (event) => setEditLabel(event.target.value) })] }), fieldSpecs.map((spec) => {
86
- // Same `{label}`-template wrapping the add form uses — `rules.ts`
87
- // stays hook-free and returns i18n templates, not sentences.
88
- const issue = saveAttempted ? issueForField(editValidation, spec.key) : undefined;
89
- return (_jsx(SourceConfigField, { spec: spec, value: editFields[spec.key] ?? '', idPrefix: `source-config-item-card-${source.id}-field`, ...(issue ? { error: t(issue.message, { label: t(spec.label) }) } : {}), ...(agentHandle ? { agentHandle: sourceConfigFieldHandle(agentHandle, spec.key) } : {}), onChange: (value) => setEditFields((current) => ({ ...current, [spec.key]: value })) }, spec.key));
90
- })] })) : (_jsx("dl", { className: "source-config-item-card-fields", children: fieldSpecs.map((spec) => (_jsxs("div", { className: "source-config-item-card-field", children: [_jsx("dt", { children: t(spec.label) }), _jsx("dd", { children: maskFieldValue(spec.kind, source.fields[spec.key] ?? '') })] }, spec.key))) })), capabilities.canTest ? (_jsx(SourceConfigTestControl, { running: testing, disabled: anyActionPending, onTest: onTest, ...(testResult ? { result: testResult } : {}), ...(agentHandle ? { agentHandle: sourceConfigActionHandle(agentHandle, 'test') } : {}) })) : null] })) : null] }));
119
+ const setEditField = (key, value) => setEditFields((current) => ({ ...current, [key]: value }));
120
+ return { editing, editLabel, setEditLabel, editFields, setEditField, saveAttempted, editValidation, startEditing, cancelEditing, saveEditing };
121
+ }
122
+ /** The expanded body: the Edit/Save/Cancel toggle, the editable or read-only fields, and the test control. */
123
+ function ItemCardBody(props) {
124
+ const { capabilities, testing, testResult, onTest, agentHandle, edit } = props;
125
+ return (_jsxs("div", { className: "source-config-item-card-body", children: [capabilities.canUpdate ? _jsx(ItemCardEditToggle, { ...props, edit: edit }) : null, edit.editing ? _jsx(ItemCardEditFields, { ...props, edit: edit }) : _jsx(ItemCardReadOnlyFields, { ...props }), capabilities.canTest ? (_jsx(SourceConfigTestControl, { running: testing, disabled: isAnyActionPending(props), onTest: onTest, ...(testResult ? { result: testResult } : {}), ...(agentHandle ? { agentHandle: sourceConfigActionHandle(agentHandle, 'test') } : {}) })) : null] }));
126
+ }
127
+ function ItemCardEditToggle(props) {
128
+ const { updating, agentHandle, edit } = props;
129
+ const t = useT();
130
+ if (!edit.editing) {
131
+ return (_jsx("div", { className: "source-config-item-card-edit-toggle", children: _jsx("button", { type: "button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Edit'), action: 'edit' }), onClick: edit.startEditing, disabled: isAnyActionPending(props), children: t('Edit') }) }));
132
+ }
133
+ return (_jsxs("div", { className: "source-config-item-card-edit-toggle", children: [_jsx("button", { type: "button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Save'), action: 'save' }), onClick: edit.saveEditing, disabled: updating || (edit.saveAttempted && !edit.editValidation.ok), children: t('Save') }), _jsx("button", { type: "button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Cancel'), action: 'cancel' }), onClick: edit.cancelEditing, disabled: updating, children: t('Cancel') })] }));
134
+ }
135
+ function ItemCardEditFields({ source, fieldSpecs, agentHandle, label, edit }) {
136
+ const t = useT();
137
+ return (_jsxs("div", { className: "source-config-item-card-edit-fields", children: [_jsxs("label", { className: "source-config-field", htmlFor: `source-config-item-card-${source.id}-label`, children: [_jsx("span", { className: "source-config-field-label", children: t('Label') }), _jsx("input", { id: `source-config-item-card-${source.id}-label`, type: "text", value: edit.editLabel, placeholder: label, ...sourceConfigAgentProps(agentHandle, { role: 'field', label: t('Label'), action: 'label' }), onChange: (event) => edit.setEditLabel(event.target.value) })] }), fieldSpecs.map((spec) => {
138
+ // Same `{label}`-template wrapping the add form uses — `rules.ts`
139
+ // stays hook-free and returns i18n templates, not sentences.
140
+ const issue = edit.saveAttempted ? issueForField(edit.editValidation, spec.key) : undefined;
141
+ return (_jsx(SourceConfigField, { spec: spec, value: edit.editFields[spec.key] ?? '', idPrefix: `source-config-item-card-${source.id}-field`, ...(issue ? { error: t(issue.message, { label: t(spec.label) }) } : {}), ...(agentHandle ? { agentHandle: sourceConfigFieldHandle(agentHandle, spec.key) } : {}), onChange: (value) => edit.setEditField(spec.key, value) }, spec.key));
142
+ })] }));
143
+ }
144
+ function ItemCardReadOnlyFields({ source, fieldSpecs }) {
145
+ const t = useT();
146
+ return (_jsx("dl", { className: "source-config-item-card-fields", children: fieldSpecs.map((spec) => (_jsxs("div", { className: "source-config-item-card-field", children: [_jsx("dt", { children: t(spec.label) }), _jsx("dd", { children: maskFieldValue(spec.kind, source.fields[spec.key] ?? '') })] }, spec.key))) }));
91
147
  }
92
148
  //# sourceMappingURL=SourceConfigItemCard.js.map
@@ -1,5 +1,5 @@
1
1
  import type { SourceConfigItem, SourceFieldSpec, SourceTestResult, SourceTrustOption, SourceUpdateInput } from '../../types.js';
2
- import { type SourceConfigAddFormProps } from './SourceConfigAddForm.js';
2
+ import { type SourceConfigAddFormBaseProps } from './SourceConfigAddForm.js';
3
3
  import type { SourceConfigListCapabilities } from '../hooks/useSourceConfigList.js';
4
4
  export interface SourceConfigListViewProps<TSource extends SourceConfigItem> {
5
5
  title?: string;
@@ -13,7 +13,9 @@ export interface SourceConfigListViewProps<TSource extends SourceConfigItem> {
13
13
  capabilities: SourceConfigListCapabilities;
14
14
  pendingKeys: ReadonlySet<string>;
15
15
  testResults: Record<string, SourceTestResult>;
16
- addForm: Omit<SourceConfigAddFormProps, 'fieldSpecs' | 'trustOptions'>;
16
+ addForm: Omit<SourceConfigAddFormBaseProps, 'fieldSpecs'> & {
17
+ onTrustChange: (value: string) => void;
18
+ };
17
19
  onRefresh: (id: string) => void;
18
20
  onRemove: (id: string) => void;
19
21
  onTrustChange: (id: string, trust: string) => void;
@@ -37,5 +39,5 @@ export interface SourceConfigListViewProps<TSource extends SourceConfigItem> {
37
39
  * wired orchestrator (`SourceConfigList.tsx`) supplies every prop from its
38
40
  * hooks.
39
41
  */
40
- export declare function SourceConfigListView<TSource extends SourceConfigItem>({ title, subtitle, emptyMessage, fieldSpecs, trustOptions, sources, loading, loadError, capabilities, pendingKeys, testResults, addForm, onRefresh, onRemove, onTrustChange, onTest, onUpdate, agentHandle, }: SourceConfigListViewProps<TSource>): import("react").JSX.Element;
42
+ export declare function SourceConfigListView<TSource extends SourceConfigItem>(props: SourceConfigListViewProps<TSource>): import("react").JSX.Element;
41
43
  //# sourceMappingURL=SourceConfigListView.d.ts.map
@@ -10,13 +10,43 @@ import { SourceConfigItemCard } from './SourceConfigItemCard.js';
10
10
  * wired orchestrator (`SourceConfigList.tsx`) supplies every prop from its
11
11
  * hooks.
12
12
  */
13
- export function SourceConfigListView({ title, subtitle, emptyMessage, fieldSpecs, trustOptions, sources, loading, loadError, capabilities, pendingKeys, testResults, addForm, onRefresh, onRemove, onTrustChange, onTest, onUpdate, agentHandle, }) {
13
+ export function SourceConfigListView(props) {
14
+ const { title, subtitle, fieldSpecs, trustOptions, addForm, agentHandle } = props;
15
+ const resolvedAddFormHandle = addForm.agentHandle ?? (agentHandle ? sourceConfigAddFormHandle(agentHandle) : undefined);
16
+ return (_jsxs("section", { className: "source-config-list", children: [_jsx(SourceConfigListHead, { title: title, subtitle: subtitle }), _jsx(SourceConfigAddForm, { ...addForm, fieldSpecs: fieldSpecs, ...(trustOptions ? { trustOptions } : {}), ...(resolvedAddFormHandle ? { agentHandle: resolvedAddFormHandle } : {}) }), _jsx(SourceConfigListError, { loadError: props.loadError }), _jsx(SourceConfigListBody, { ...props })] }));
17
+ }
18
+ /** The optional title/subtitle block — omitted entirely when neither is given. */
19
+ function SourceConfigListHead({ title, subtitle }) {
20
+ const t = useT();
21
+ if (!title && !subtitle)
22
+ return null;
23
+ return (_jsxs("div", { className: "source-config-list-head", children: [title ? _jsx("h3", { children: t(title) }) : null, subtitle ? _jsx("p", { className: "source-config-list-subtitle", children: t(subtitle) }) : null] }));
24
+ }
25
+ function SourceConfigListError({ loadError }) {
14
26
  const t = useT();
27
+ if (!loadError)
28
+ return null;
29
+ return (_jsx("div", { className: "source-config-list-error", role: "alert", children: t(loadError) }));
30
+ }
31
+ /** The loading indicator, the empty message, or one item card per source — in that order of precedence. */
32
+ function SourceConfigListBody(props) {
33
+ const t = useT();
34
+ const { sources, loading, emptyMessage, agentHandle } = props;
35
+ if (loading) {
36
+ return (_jsx("div", { className: "source-config-list-loading", role: "status", children: t('Loading…') }));
37
+ }
38
+ if (sources.length === 0) {
39
+ return _jsx("div", { className: "source-config-list-empty", children: emptyMessage ? t(emptyMessage) : t('No sources configured yet.') });
40
+ }
15
41
  // Positionally aligned with `sources` below — computed once per render rather than per card, so
16
42
  // the O(n) suffix-search dedup in `buildAgentListHandles` runs once for the whole list, not once
17
43
  // per item.
18
44
  const itemHandles = agentHandle ? sourceConfigItemHandles(agentHandle, sources.map((source) => source.id)) : undefined;
19
- const resolvedAddFormHandle = addForm.agentHandle ?? (agentHandle ? sourceConfigAddFormHandle(agentHandle) : undefined);
20
- return (_jsxs("section", { className: "source-config-list", children: [title || subtitle ? (_jsxs("div", { className: "source-config-list-head", children: [title ? _jsx("h3", { children: t(title) }) : null, subtitle ? _jsx("p", { className: "source-config-list-subtitle", children: t(subtitle) }) : null] })) : null, _jsx(SourceConfigAddForm, { ...addForm, fieldSpecs: fieldSpecs, ...(trustOptions ? { trustOptions } : {}), ...(resolvedAddFormHandle ? { agentHandle: resolvedAddFormHandle } : {}) }), loadError ? (_jsx("div", { className: "source-config-list-error", role: "alert", children: t(loadError) })) : null, loading ? (_jsx("div", { className: "source-config-list-loading", role: "status", children: t('Loading…') })) : sources.length === 0 ? (_jsx("div", { className: "source-config-list-empty", children: emptyMessage ? t(emptyMessage) : t('No sources configured yet.') })) : (_jsx("div", { className: "source-config-list-items", children: sources.map((source, index) => (_jsx(SourceConfigItemCard, { source: source, fieldSpecs: fieldSpecs, capabilities: capabilities, removing: isActionPending(pendingKeys, source.id, 'remove'), refreshing: isActionPending(pendingKeys, source.id, 'refresh'), settingTrust: isActionPending(pendingKeys, source.id, 'trust'), testing: isActionPending(pendingKeys, source.id, 'test'), updating: isActionPending(pendingKeys, source.id, 'update'), onRefresh: () => onRefresh(source.id), onRemove: () => onRemove(source.id), onTrustChange: (trust) => onTrustChange(source.id, trust), onTest: () => onTest(source.id), onUpdate: (patch) => onUpdate(source.id, patch), ...(trustOptions ? { trustOptions } : {}), ...(testResults[source.id] ? { testResult: testResults[source.id] } : {}), ...(itemHandles ? { agentHandle: itemHandles[index] } : {}) }, source.id))) }))] }));
45
+ return (_jsx("div", { className: "source-config-list-items", children: sources.map((source, index) => (_jsx(SourceConfigListItem, { ...props, source: source, ...(itemHandles ? { itemHandle: itemHandles[index] } : {}) }, source.id))) }));
46
+ }
47
+ /** One source's card, with the list-level per-id callbacks and pending state bound to that source. */
48
+ function SourceConfigListItem({ source, itemHandle, fieldSpecs, trustOptions, capabilities, pendingKeys, testResults, onRefresh, onRemove, onTrustChange, onTest, onUpdate, }) {
49
+ const testResult = testResults[source.id];
50
+ return (_jsx(SourceConfigItemCard, { source: source, fieldSpecs: fieldSpecs, capabilities: capabilities, removing: isActionPending(pendingKeys, source.id, 'remove'), refreshing: isActionPending(pendingKeys, source.id, 'refresh'), settingTrust: isActionPending(pendingKeys, source.id, 'trust'), testing: isActionPending(pendingKeys, source.id, 'test'), updating: isActionPending(pendingKeys, source.id, 'update'), onRefresh: () => onRefresh(source.id), onRemove: () => onRemove(source.id), onTrustChange: (trust) => onTrustChange(source.id, trust), onTest: () => onTest(source.id), onUpdate: (patch) => onUpdate(source.id, patch), ...(trustOptions ? { trustOptions } : {}), ...(testResult ? { testResult } : {}), ...(itemHandle !== undefined ? { agentHandle: itemHandle } : {}) }));
21
51
  }
22
52
  //# sourceMappingURL=SourceConfigListView.js.map
@@ -24,6 +24,22 @@ export function SourceConfigTestControl({ running, result, disabled = false, age
24
24
  role: 'status',
25
25
  label: t('Connection test result'),
26
26
  action: 'status',
27
- }), children: running ? (_jsx("span", { className: "source-config-test-status is-running", role: "status", "aria-live": "polite", children: t('Testing…') })) : result ? (_jsx("span", { className: result.ok ? 'source-config-test-status is-success' : 'source-config-test-status is-error', role: result.ok ? 'status' : 'alert', children: result.message ?? (result.ok ? t('Connection ok.') : t('Connection failed.')) })) : null }), _jsx("button", { type: "button", className: "source-config-test-button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Test connection') }), onClick: onTest, disabled: disabled || running, children: running ? t('Testing…') : result && !result.ok ? t('Retry') : t('Test') })] }));
27
+ }), children: _jsx(TestStatusMessage, { running: running, result: result }) }), _jsx("button", { type: "button", className: "source-config-test-button", ...sourceConfigAgentProps(agentHandle, { role: 'button', label: t('Test connection') }), onClick: onTest, disabled: disabled || running, children: testButtonLabel({ running, t }, { result }) })] }));
28
+ }
29
+ /** The status line's content: "Testing…" while running, the last result once one exists, nothing before the first test. */
30
+ function TestStatusMessage({ running, result }) {
31
+ const t = useT();
32
+ if (running) {
33
+ return (_jsx("span", { className: "source-config-test-status is-running", role: "status", "aria-live": "polite", children: t('Testing…') }));
34
+ }
35
+ if (!result)
36
+ return null;
37
+ return (_jsx("span", { className: result.ok ? 'source-config-test-status is-success' : 'source-config-test-status is-error', role: result.ok ? 'status' : 'alert', children: result.message ?? (result.ok ? t('Connection ok.') : t('Connection failed.')) }));
38
+ }
39
+ /** "Testing…" while running, "Retry" after a failed result, otherwise "Test". */
40
+ function testButtonLabel({ running, t }, { result }) {
41
+ if (running)
42
+ return t('Testing…');
43
+ return result && !result.ok ? t('Retry') : t('Test');
28
44
  }
29
45
  //# sourceMappingURL=SourceConfigTestControl.js.map
@@ -0,0 +1,11 @@
1
+ import type { SourceTrustOption } from '../../types.js';
2
+ /**
3
+ * The `<option>` list both trust `<select>`s in this feature render (the add
4
+ * form's and each item card's): a hidden, disabled "Select…" placeholder while
5
+ * no trust value is chosen yet, then one option per `trustOptions` entry.
6
+ */
7
+ export declare function SourceConfigTrustOptions({ trust, trustOptions }: {
8
+ trust?: string | undefined;
9
+ trustOptions: readonly SourceTrustOption[];
10
+ }): import("react").JSX.Element;
11
+ //# sourceMappingURL=SourceConfigTrustOptions.d.ts.map
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useT } from '../../../i18n/index.js';
3
+ /**
4
+ * The `<option>` list both trust `<select>`s in this feature render (the add
5
+ * form's and each item card's): a hidden, disabled "Select…" placeholder while
6
+ * no trust value is chosen yet, then one option per `trustOptions` entry.
7
+ */
8
+ export function SourceConfigTrustOptions({ trust, trustOptions }) {
9
+ const t = useT();
10
+ return (_jsxs(_Fragment, { children: [!trust ? (_jsx("option", { value: "", disabled: true, hidden: true, children: t('Select…') })) : null, trustOptions.map((option) => (_jsx("option", { value: option.value, children: t(option.label) }, option.value)))] }));
11
+ }
12
+ //# sourceMappingURL=SourceConfigTrustOptions.js.map
@@ -61,6 +61,20 @@ export interface SourceTrustOption {
61
61
  value: string;
62
62
  label: string;
63
63
  }
64
+ /**
65
+ * The trust selector's two inputs, bound together. The selector only renders when `trustOptions` is
66
+ * non-empty, so its change handler is required exactly when options can be present and may be
67
+ * omitted when they are not — a host whose sources have no trust concept passes neither, instead of a
68
+ * no-op `onTrustChange` that can never fire. Passing options (even possibly-undefined ones) still
69
+ * requires the handler, so every pre-existing caller type-checks unchanged.
70
+ */
71
+ export type SourceTrustSelectorProps = {
72
+ trustOptions?: readonly SourceTrustOption[] | undefined;
73
+ onTrustChange: (trust: string) => void;
74
+ } | {
75
+ trustOptions?: undefined;
76
+ onTrustChange?: undefined;
77
+ };
64
78
  export type SourceConnectionStatus = 'idle' | 'testing' | 'connected' | 'error';
65
79
  export interface SourceTestResult {
66
80
  ok: boolean;
@@ -6,6 +6,14 @@ import { ALL_KIND_FILTER } from '../../constants.js';
6
6
  import { useTabLauncherMenu } from '../hooks/useTabLauncherMenu.js';
7
7
  import { TabLauncherActionRow } from './TabLauncherActionRow.js';
8
8
  import { TabLauncherResultRow } from './TabLauncherResultRow.js';
9
+ function renderResultSection({ items, renderLabel, startIndex, selected, ...rowProps }, { renderIcon } = {}) {
10
+ if (items.length === 0)
11
+ return null;
12
+ return (_jsxs("section", { className: "jini-tab-launcher-menu__section", children: [_jsx("div", { className: "jini-tab-launcher-menu__section-header", children: renderLabel() }), _jsx("ul", { className: "jini-tab-launcher-menu__list", children: items.map((item, index) => {
13
+ const selectableIndex = startIndex + index;
14
+ return (_jsx(TabLauncherResultRow, { item: item, selectableIndex: selectableIndex, selected: selectableIndex === selected, renderIcon: renderIcon, ...rowProps }, item.id));
15
+ }) })] }));
16
+ }
9
17
  /**
10
18
  * An anchored, portal-rendered command-palette dropdown for a tab strip's
11
19
  * "+" button: viewport-clamped fixed positioning off an anchor element,
@@ -37,6 +45,22 @@ export function TabLauncherMenu({ searchPlaceholder, renderIcon, renderSearchIco
37
45
  return null;
38
46
  const openLabel = t('Open');
39
47
  const hasResults = menu.fileResults.length > 0 || menu.tabResults.length > 0;
40
- return createPortal(_jsxs("div", { ref: menu.containerRef, className: "jini-tab-launcher-menu", style: { top: menu.position.top, left: menu.position.left }, role: "dialog", "aria-label": t('New tab'), children: [_jsxs("div", { className: "jini-tab-launcher-menu__search-row", children: [renderSearchIcon ? _jsx("span", { className: "jini-tab-launcher-menu__search-icon", "aria-hidden": "true", children: renderSearchIcon() }) : null, _jsx("input", { autoFocus: true, className: "jini-tab-launcher-menu__search-input", type: "text", value: menu.query, placeholder: searchPlaceholder ?? t('Search files…'), onChange: (event) => menu.setQuery(event.target.value), onKeyDown: menu.handleInputKeyDown })] }), menu.presentKinds.length > 0 ? (_jsxs("div", { className: "jini-tab-launcher-menu__chips", children: [_jsx("button", { type: "button", className: `jini-tab-launcher-menu__chip${menu.kindFilter === ALL_KIND_FILTER ? ' jini-tab-launcher-menu__chip--active' : ''}`, onClick: () => menu.setKindFilter(ALL_KIND_FILTER), children: t('All files') }), menu.presentKinds.map((kind) => (_jsx("button", { type: "button", className: `jini-tab-launcher-menu__chip${menu.kindFilter === kind ? ' jini-tab-launcher-menu__chip--active' : ''}`, onClick: () => menu.setKindFilter(kind), children: kind }, kind)))] })) : null, _jsxs("div", { className: "jini-tab-launcher-menu__scroll-body", children: [menu.actions.length > 0 ? (_jsxs("section", { className: "jini-tab-launcher-menu__section", children: [_jsx("div", { className: "jini-tab-launcher-menu__section-header", children: t('Create new') }), _jsx("ul", { className: "jini-tab-launcher-menu__list", children: menu.actions.map((action) => (_jsx(TabLauncherActionRow, { action: action, onSelect: menu.runAction, renderIcon: renderIcon }, action.id))) })] })) : null, menu.fileResults.length > 0 ? (_jsxs("section", { className: "jini-tab-launcher-menu__section", children: [_jsx("div", { className: "jini-tab-launcher-menu__section-header", children: t('Open file') }), _jsx("ul", { className: "jini-tab-launcher-menu__list", children: menu.fileResults.map((item, index) => (_jsx(TabLauncherResultRow, { item: item, selectableIndex: index, selected: index === menu.selected, openLabel: openLabel, onHover: menu.setSelected, onSelect: menu.selectFile, renderIcon: renderIcon }, item.id))) })] })) : null, menu.tabResults.length > 0 ? (_jsxs("section", { className: "jini-tab-launcher-menu__section", children: [_jsx("div", { className: "jini-tab-launcher-menu__section-header", children: t('Open tabs') }), _jsx("ul", { className: "jini-tab-launcher-menu__list", children: menu.tabResults.map((item, index) => (_jsx(TabLauncherResultRow, { item: item, selectableIndex: menu.fileResults.length + index, selected: menu.fileResults.length + index === menu.selected, openLabel: openLabel, onHover: menu.setSelected, onSelect: menu.selectTab, renderIcon: renderIcon }, item.id))) })] })) : null, !hasResults ? _jsx("div", { className: "jini-tab-launcher-menu__empty", children: t('No files match') }) : null] })] }), document.body);
48
+ return createPortal(_jsxs("div", { ref: menu.containerRef, className: "jini-tab-launcher-menu", style: { top: menu.position.top, left: menu.position.left }, role: "dialog", "aria-label": t('New tab'), children: [_jsxs("div", { className: "jini-tab-launcher-menu__search-row", children: [renderSearchIcon ? _jsx("span", { className: "jini-tab-launcher-menu__search-icon", "aria-hidden": "true", children: renderSearchIcon() }) : null, _jsx("input", { autoFocus: true, className: "jini-tab-launcher-menu__search-input", type: "text", value: menu.query, placeholder: searchPlaceholder ?? t('Search files…'), onChange: (event) => menu.setQuery(event.target.value), onKeyDown: menu.handleInputKeyDown })] }), menu.presentKinds.length > 0 ? (_jsxs("div", { className: "jini-tab-launcher-menu__chips", children: [_jsx("button", { type: "button", className: `jini-tab-launcher-menu__chip${menu.kindFilter === ALL_KIND_FILTER ? ' jini-tab-launcher-menu__chip--active' : ''}`, onClick: () => menu.setKindFilter(ALL_KIND_FILTER), children: t('All files') }), menu.presentKinds.map((kind) => (_jsx("button", { type: "button", className: `jini-tab-launcher-menu__chip${menu.kindFilter === kind ? ' jini-tab-launcher-menu__chip--active' : ''}`, onClick: () => menu.setKindFilter(kind), children: kind }, kind)))] })) : null, _jsxs("div", { className: "jini-tab-launcher-menu__scroll-body", children: [menu.actions.length > 0 ? (_jsxs("section", { className: "jini-tab-launcher-menu__section", children: [_jsx("div", { className: "jini-tab-launcher-menu__section-header", children: t('Create new') }), _jsx("ul", { className: "jini-tab-launcher-menu__list", children: menu.actions.map((action) => (_jsx(TabLauncherActionRow, { action: action, onSelect: menu.runAction, renderIcon: renderIcon }, action.id))) })] })) : null, renderResultSection({
49
+ items: menu.fileResults,
50
+ renderLabel: () => t('Open file'),
51
+ startIndex: 0,
52
+ selected: menu.selected,
53
+ openLabel,
54
+ onHover: menu.setSelected,
55
+ onSelect: menu.selectFile,
56
+ }, { renderIcon }), renderResultSection({
57
+ items: menu.tabResults,
58
+ renderLabel: () => t('Open tabs'),
59
+ startIndex: menu.fileResults.length,
60
+ selected: menu.selected,
61
+ openLabel,
62
+ onHover: menu.setSelected,
63
+ onSelect: menu.selectTab,
64
+ }, { renderIcon }), !hasResults ? _jsx("div", { className: "jini-tab-launcher-menu__empty", children: t('No files match') }) : null] })] }), document.body);
41
65
  }
42
66
  //# sourceMappingURL=TabLauncherMenu.js.map
@@ -75,28 +75,27 @@ export function useTabLauncherMenu(options) {
75
75
  setSelected((current) => nextSelected(current, selectableCount, -1));
76
76
  return;
77
77
  }
78
- if (event.key === 'Enter') {
79
- event.preventDefault();
80
- if (selectableCount > 0) {
81
- const resolved = resolveSelection(selected, fileResults.length);
82
- if (resolved.zone === 'file') {
83
- const file = fileResults[resolved.index];
84
- if (file)
85
- selectFile(file);
86
- }
87
- else {
88
- const tab = tabResults[resolved.index];
89
- if (tab)
90
- selectTab(tab);
91
- }
92
- return;
93
- }
78
+ if (event.key !== 'Enter')
79
+ return;
80
+ event.preventDefault();
81
+ if (selectableCount === 0) {
94
82
  // No file/tab matches the query but "create new" actions exist —
95
83
  // Enter triggers the first one so the keyboard path is never a dead end.
96
84
  const firstAction = actions[0];
97
85
  if (firstAction)
98
86
  runAction(firstAction);
87
+ return;
88
+ }
89
+ const resolved = resolveSelection(selected, fileResults.length);
90
+ if (resolved.zone === 'file') {
91
+ const file = fileResults[resolved.index];
92
+ if (file)
93
+ selectFile(file);
94
+ return;
99
95
  }
96
+ const tab = tabResults[resolved.index];
97
+ if (tab)
98
+ selectTab(tab);
100
99
  }, [selectableCount, selected, fileResults, tabResults, actions, selectFile, selectTab, runAction]);
101
100
  return {
102
101
  containerRef,
@@ -15,11 +15,18 @@ function tabDotAccessibleSuffix(tab) {
15
15
  return null;
16
16
  return _jsxs("span", { className: "visually-hidden", children: [", ", tab.dotLabel] });
17
17
  }
18
+ function tabAccessibleLabel({ tab }, _optional = {}) {
19
+ if (!tab.dot || !tab.dotLabel)
20
+ return undefined;
21
+ return [tab.label + ", " + tab.dotLabel, tab.tag, tab.count]
22
+ .filter((part) => part !== undefined)
23
+ .join(" ");
24
+ }
18
25
  /** One tab button. A named top-level component avoids the nesting penalty for branches inside
19
26
  * an inline map callback under the cyclomatic/cognitive complexity gate. Derived props live in
20
27
  * TabBar.hooks.tsx; tabDotAccessibleSuffix stays here because it renders JSX. */
21
28
  function TabBarButton({ tab, active, tabIndex, onChange, }) {
22
- return (_jsxs("button", { type: "button", role: "tab", className: "tab-bar-item", "aria-selected": active, "aria-label": tab.dot && tab.dotLabel ? [tab.label + ", " + tab.dotLabel, tab.tag, tab.count].filter((part) => part !== undefined).join(" ") : undefined, "aria-disabled": tab.disabled || undefined, disabled: tab.disabled, tabIndex: tabIndex, onClick: tab.disabled ? undefined : () => onChange(tab.id), ...tabHandleProps({ tab: tab }), children: [tab.dot ? _jsx("span", { className: "tab-bar-dot", "aria-hidden": "true" }) : null, tab.icon ? (_jsx("span", { className: "tab-bar-icon", "aria-hidden": "true", children: tab.icon })) : null, tab.label, tabDotAccessibleSuffix(tab), tab.tag ? _jsx("span", { className: "tab-bar-tag", children: tab.tag }) : null, tab.count !== undefined ? _jsx("span", { className: "tab-bar-count", children: tab.count }) : null] }));
29
+ return (_jsxs("button", { type: "button", role: "tab", className: "tab-bar-item", "aria-selected": active, "aria-label": tabAccessibleLabel({ tab }), "aria-disabled": tab.disabled || undefined, disabled: tab.disabled, tabIndex: tabIndex, onClick: tab.disabled ? undefined : () => onChange(tab.id), ...tabHandleProps({ tab: tab }), children: [tab.dot ? _jsx("span", { className: "tab-bar-dot", "aria-hidden": "true" }) : null, tab.icon ? (_jsx("span", { className: "tab-bar-icon", "aria-hidden": "true", children: tab.icon })) : null, tab.label, tabDotAccessibleSuffix(tab), tab.tag ? _jsx("span", { className: "tab-bar-tag", children: tab.tag }) : null, tab.count !== undefined ? _jsx("span", { className: "tab-bar-count", children: tab.count }) : null] }));
23
30
  }
24
31
  /** Controlled button-based selection strip, including roving focus and optional agent handles. */
25
32
  export function TabBar({ tabs, activeId, onChange, ariaLabel, containerHandle }, _optional = {}) {
@@ -1,8 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useT } from '../../../i18n/index.js';
3
- import { Icon } from '../../../../react/components/Icon.js';
4
3
  import { findActiveTab } from '../../rules.js';
5
4
  import { useTabbedDialog } from '../hooks/useTabbedDialog.js';
5
+ import { TabbedDialogChrome } from './TabbedDialogChrome.js';
6
+ import { TabbedDialogHeader } from './TabbedDialogHeader.js';
7
+ import { TabbedDialogSidebar } from './TabbedDialogSidebar.js';
8
+ import { buildTabbedDialogClassName, dialogRootRoleProps, resolveIsModal, resolveTabbedDialogLabels, } from './tabbedDialogView.js';
6
9
  /**
7
10
  * Generic tabbed-dialog chrome: modal backdrop + sidebar nav + active-panel
8
11
  * switching + fullscreen/collapse/close affordances. Carries no opinion
@@ -23,7 +26,7 @@ import { useTabbedDialog } from '../hooks/useTabbedDialog.js';
23
26
  * itself never reached into a tab's internals.
24
27
  */
25
28
  export function TabbedDialog({ tabs, initialActiveTabId, activeTabId: controlledActiveTabId, onActiveTabIdChange, onClose, presentation, welcome = false, defaultSidebarCollapsed = false, fullscreenEnabled = true, defaultFullscreen = false, labels, chromeExtra, dialogAriaLabelledBy = 'tabbed-dialog-title', className, }) {
26
- const isModal = (presentation ?? (onClose ? 'modal' : 'inline')) === 'modal';
29
+ const isModal = resolveIsModal({ hasOnClose: Boolean(onClose) }, { presentation });
27
30
  const t = useT();
28
31
  const shell = useTabbedDialog({
29
32
  tabs,
@@ -35,33 +38,8 @@ export function TabbedDialog({ tabs, initialActiveTabId, activeTabId: controlled
35
38
  defaultFullscreen,
36
39
  });
37
40
  const activeTab = findActiveTab(tabs, shell.activeTabId);
38
- // No brand/product word defaults to a bare `''` here on purpose — this component has no
39
- // opinion about what it's a dialog FOR. A host that wants a kicker (as `SettingsDialogShell`
40
- // does, with `t('Settings')`) supplies one via `labels.kicker`.
41
- const kicker = labels?.kicker ?? '';
42
- const welcomeKicker = labels?.welcomeKicker ?? t('Welcome');
43
- const welcomeTitle = labels?.welcomeTitle ?? t('Get started');
44
- const welcomeSubtitle = labels?.welcomeSubtitle ?? t('Set up your preferences before you begin.');
45
- const closeLabel = labels?.closeLabel ?? t('Close');
46
- const fullscreenLabel = labels?.fullscreenLabel ?? t('Fullscreen');
47
- const exitFullscreenLabel = labels?.exitFullscreenLabel ?? t('Exit fullscreen');
48
- const collapseSidebarLabel = labels?.collapseSidebarLabel ?? t('Collapse sidebar');
49
- const expandSidebarLabel = labels?.expandSidebarLabel ?? t('Expand sidebar');
50
- const sidebarAriaLabel = labels?.sidebarAriaLabel ?? t('Sections');
51
- const sidebarToggleLabel = shell.sidebarCollapsed ? expandSidebarLabel : collapseSidebarLabel;
52
- const fullscreenToggleLabel = shell.fullscreen ? exitFullscreenLabel : fullscreenLabel;
53
- const dialogClassName = [
54
- 'jini-tabbed-dialog',
55
- shell.sidebarCollapsed ? 'jini-tabbed-dialog-sidebar-collapsed' : '',
56
- shell.fullscreen ? 'jini-tabbed-dialog-fullscreen' : '',
57
- className ?? '',
58
- ]
59
- .filter(Boolean)
60
- .join(' ');
61
- const body = (_jsxs("div", { className: dialogClassName, role: isModal ? 'dialog' : 'region', "aria-modal": isModal ? true : undefined, "aria-labelledby": dialogAriaLabelledBy, onClick: isModal ? (event) => event.stopPropagation() : undefined, children: [_jsxs("div", { className: "jini-tabbed-dialog-chrome", children: [chromeExtra, fullscreenEnabled ? (_jsx("button", { type: "button", className: "jini-tabbed-dialog-chrome-btn jini-tabbed-dialog-fullscreen-toggle", onClick: shell.toggleFullscreen, "aria-label": fullscreenToggleLabel, "aria-pressed": shell.fullscreen, title: fullscreenToggleLabel, children: _jsx(Icon, { name: shell.fullscreen ? 'minimize' : 'maximize', size: 15, strokeWidth: 2 }) })) : null, onClose ? (_jsx("button", { type: "button", className: "jini-tabbed-dialog-chrome-btn jini-tabbed-dialog-close", onClick: onClose, "aria-label": closeLabel, title: closeLabel, children: _jsx(Icon, { name: "close", size: 16, strokeWidth: 2 }) })) : null] }), _jsx("header", { className: "jini-tabbed-dialog-head", id: dialogAriaLabelledBy, children: welcome ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "jini-tabbed-dialog-kicker", children: welcomeKicker }), _jsx("h2", { children: welcomeTitle }), _jsx("p", { className: "jini-tabbed-dialog-subtitle", children: welcomeSubtitle })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "jini-tabbed-dialog-kicker", children: kicker }), _jsxs("div", { className: "jini-tabbed-dialog-head-line", children: [_jsx("h2", { children: activeTab?.title ?? activeTab?.label ?? '' }), activeTab?.subtitle ? (_jsx("p", { className: "jini-tabbed-dialog-subtitle", children: activeTab.subtitle })) : null] })] })) }), _jsxs("div", { className: "jini-tabbed-dialog-body", children: [_jsx("button", { type: "button", className: "jini-tabbed-dialog-sidebar-toggle", onClick: shell.toggleSidebarCollapsed, "aria-label": sidebarToggleLabel, "aria-pressed": shell.sidebarCollapsed, "aria-controls": "jini-tabbed-dialog-sidebar", title: sidebarToggleLabel, children: _jsx(Icon, { name: shell.sidebarCollapsed ? 'chevron-right' : 'chevron-left', size: 15, strokeWidth: 2 }) }), _jsx("aside", { id: "jini-tabbed-dialog-sidebar", className: "jini-tabbed-dialog-sidebar", "aria-label": sidebarAriaLabel, "aria-hidden": shell.sidebarCollapsed ? true : undefined, children: tabs.map((tab) => {
62
- const active = tab.id === shell.activeTabId;
63
- return (_jsxs("button", { type: "button", className: `jini-tabbed-dialog-nav-item${active ? ' active' : ''}`, "aria-pressed": active, onClick: () => shell.setActiveTabId(tab.id), "data-testid": `settings-dialog-nav-${tab.id}`, "data-agent-element": isModal ? undefined : `tab-${tab.id}`, "data-agent-role": isModal ? undefined : 'button', "data-agent-label": isModal ? undefined : tab.label, children: [_jsx("span", { className: "jini-tabbed-dialog-nav-icon", "aria-hidden": "true", children: tab.icon }), _jsxs("span", { className: "jini-tabbed-dialog-nav-text", children: [_jsx("strong", { children: tab.label }), tab.navHint ? _jsx("small", { children: tab.navHint }) : null] })] }, tab.id));
64
- }) }), _jsx("div", { className: "jini-tabbed-dialog-content", ref: shell.contentRef, children: activeTab?.panel })] })] }));
41
+ const resolvedLabels = resolveTabbedDialogLabels({ t }, { labels });
42
+ const body = (_jsxs("div", { className: buildTabbedDialogClassName(shell, { className }), ...dialogRootRoleProps({ isModal }), "aria-labelledby": dialogAriaLabelledBy, children: [_jsx(TabbedDialogChrome, { chromeExtra: chromeExtra, fullscreenEnabled: fullscreenEnabled, fullscreen: shell.fullscreen, onToggleFullscreen: shell.toggleFullscreen, onClose: onClose, labels: resolvedLabels }), _jsx(TabbedDialogHeader, { id: dialogAriaLabelledBy, welcome: welcome, activeTab: activeTab, labels: resolvedLabels }), _jsxs("div", { className: "jini-tabbed-dialog-body", children: [_jsx(TabbedDialogSidebar, { tabs: tabs, activeTabId: shell.activeTabId, isModal: isModal, collapsed: shell.sidebarCollapsed, onToggleCollapsed: shell.toggleSidebarCollapsed, onSelect: shell.setActiveTabId, labels: resolvedLabels }), _jsx("div", { className: "jini-tabbed-dialog-content", ref: shell.contentRef, children: activeTab?.panel })] })] }));
65
43
  // Inline presentation returns the panel bare: no fixed-position backdrop, no
66
44
  // `aria-modal`, no click-outside handler. Wrapping it anyway is what made an
67
45
  // embedded shell paint a full-viewport overlay over its own host's chrome.
@@ -0,0 +1,15 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { ResolvedTabbedDialogLabels } from './tabbedDialogView.js';
3
+ export interface TabbedDialogChromeProps {
4
+ /** Host-owned extra chrome, rendered as-is ahead of the built-in buttons. */
5
+ chromeExtra?: ReactNode;
6
+ fullscreenEnabled: boolean;
7
+ fullscreen: boolean;
8
+ onToggleFullscreen: () => void;
9
+ /** Omit to render no close button. */
10
+ onClose?: (() => void) | undefined;
11
+ labels: ResolvedTabbedDialogLabels;
12
+ }
13
+ /** The top-right strip: host extras, the fullscreen toggle, and the close button. */
14
+ export declare function TabbedDialogChrome({ chromeExtra, fullscreenEnabled, fullscreen, onToggleFullscreen, onClose, labels, }: TabbedDialogChromeProps): import("react").JSX.Element;
15
+ //# sourceMappingURL=TabbedDialogChrome.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Icon } from '../../../../react/components/Icon.js';
3
+ /** The top-right strip: host extras, the fullscreen toggle, and the close button. */
4
+ export function TabbedDialogChrome({ chromeExtra, fullscreenEnabled, fullscreen, onToggleFullscreen, onClose, labels, }) {
5
+ const fullscreenToggleLabel = fullscreen ? labels.exitFullscreenLabel : labels.fullscreenLabel;
6
+ return (_jsxs("div", { className: "jini-tabbed-dialog-chrome", children: [chromeExtra, fullscreenEnabled ? (_jsx("button", { type: "button", className: "jini-tabbed-dialog-chrome-btn jini-tabbed-dialog-fullscreen-toggle", onClick: onToggleFullscreen, "aria-label": fullscreenToggleLabel, "aria-pressed": fullscreen, title: fullscreenToggleLabel, children: _jsx(Icon, { name: fullscreen ? 'minimize' : 'maximize', size: 15, strokeWidth: 2 }) })) : null, onClose ? (_jsx("button", { type: "button", className: "jini-tabbed-dialog-chrome-btn jini-tabbed-dialog-close", onClick: onClose, "aria-label": labels.closeLabel, title: labels.closeLabel, children: _jsx(Icon, { name: "close", size: 16, strokeWidth: 2 }) })) : null] }));
7
+ }
8
+ //# sourceMappingURL=TabbedDialogChrome.js.map
@@ -0,0 +1,12 @@
1
+ import type { TabbedDialogTabMeta } from '../../types.js';
2
+ import type { ResolvedTabbedDialogLabels } from './tabbedDialogView.js';
3
+ export interface TabbedDialogHeaderProps {
4
+ /** Element id the dialog root's `aria-labelledby` points at. */
5
+ id: string;
6
+ welcome: boolean;
7
+ activeTab: TabbedDialogTabMeta | undefined;
8
+ labels: ResolvedTabbedDialogLabels;
9
+ }
10
+ /** Either the welcome hero (kicker/title/subtitle) or the active tab's own header. */
11
+ export declare function TabbedDialogHeader({ id, welcome, activeTab, labels }: TabbedDialogHeaderProps): import("react").JSX.Element;
12
+ //# sourceMappingURL=TabbedDialogHeader.d.ts.map
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /** Either the welcome hero (kicker/title/subtitle) or the active tab's own header. */
3
+ export function TabbedDialogHeader({ id, welcome, activeTab, labels }) {
4
+ return (_jsx("header", { className: "jini-tabbed-dialog-head", id: id, children: welcome ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "jini-tabbed-dialog-kicker", children: labels.welcomeKicker }), _jsx("h2", { children: labels.welcomeTitle }), _jsx("p", { className: "jini-tabbed-dialog-subtitle", children: labels.welcomeSubtitle })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "jini-tabbed-dialog-kicker", children: labels.kicker }), _jsxs("div", { className: "jini-tabbed-dialog-head-line", children: [_jsx("h2", { children: activeTab?.title ?? activeTab?.label ?? '' }), activeTab?.subtitle ? _jsx("p", { className: "jini-tabbed-dialog-subtitle", children: activeTab.subtitle }) : null] })] })) }));
5
+ }
6
+ //# sourceMappingURL=TabbedDialogHeader.js.map
@@ -0,0 +1,27 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { TabbedDialogTabMeta } from '../../types.js';
3
+ import type { ResolvedTabbedDialogLabels } from './tabbedDialogView.js';
4
+ /** The slice of a tab the sidebar nav renders (no `panel`). */
5
+ export type TabbedDialogNavTab = TabbedDialogTabMeta & {
6
+ icon?: ReactNode;
7
+ };
8
+ export interface TabbedDialogNavItemProps {
9
+ tab: TabbedDialogNavTab;
10
+ active: boolean;
11
+ isModal: boolean;
12
+ onSelect: (tabId: string) => void;
13
+ }
14
+ /** One sidebar nav button. */
15
+ export declare function TabbedDialogNavItem({ tab, active, isModal, onSelect }: TabbedDialogNavItemProps): import("react").JSX.Element;
16
+ export interface TabbedDialogSidebarProps {
17
+ tabs: readonly TabbedDialogNavTab[];
18
+ activeTabId: string | null;
19
+ isModal: boolean;
20
+ collapsed: boolean;
21
+ onToggleCollapsed: () => void;
22
+ onSelect: (tabId: string) => void;
23
+ labels: ResolvedTabbedDialogLabels;
24
+ }
25
+ /** The collapse toggle plus the sidebar nav it controls. */
26
+ export declare function TabbedDialogSidebar({ tabs, activeTabId, isModal, collapsed, onToggleCollapsed, onSelect, labels, }: TabbedDialogSidebarProps): import("react").JSX.Element;
27
+ //# sourceMappingURL=TabbedDialogSidebar.d.ts.map