@jini-ai/ui 0.3.14 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +120 -26
  3. package/dist/browser/index.js +1 -1
  4. package/dist/browser/useDismissOnOutsideOrEscape.d.ts +10 -1
  5. package/dist/browser/useDismissOnOutsideOrEscape.js +7 -4
  6. package/dist/browser/useGlobalKeydown.d.ts +14 -2
  7. package/dist/browser/useGlobalKeydown.js +8 -17
  8. package/dist/features/a2ui/catalog-from-registry.d.ts +6 -3
  9. package/dist/features/a2ui/catalog-from-registry.js +1 -1
  10. package/dist/features/a2ui/index.d.ts +1 -1
  11. package/dist/features/a2ui/protocol.d.ts +1 -1
  12. package/dist/features/a2ui/renderer.js +23 -10
  13. package/dist/features/a2ui/use-a2ui-surface.d.ts +11 -6
  14. package/dist/features/a2ui/use-a2ui-surface.js +40 -10
  15. package/dist/features/admin-widgets/components/ComingSoonNotice.d.ts +11 -0
  16. package/dist/features/admin-widgets/components/ComingSoonNotice.js +7 -0
  17. package/dist/features/admin-widgets/components/ComingSoonPanel.d.ts +10 -0
  18. package/dist/features/admin-widgets/components/ComingSoonPanel.js +10 -0
  19. package/dist/features/admin-widgets/components/ImagePreviewModal.d.ts +16 -0
  20. package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.d.ts +13 -0
  21. package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.js +46 -0
  22. package/dist/features/admin-widgets/components/ImagePreviewModal.js +13 -0
  23. package/dist/features/admin-widgets/components/InfoTip.d.ts +18 -0
  24. package/dist/features/admin-widgets/components/InfoTip.hooks.d.ts +16 -0
  25. package/dist/features/admin-widgets/components/InfoTip.hooks.js +45 -0
  26. package/dist/features/admin-widgets/components/InfoTip.js +12 -0
  27. package/dist/features/admin-widgets/components/SeeMore/SeeMore.d.ts +41 -0
  28. package/dist/features/admin-widgets/components/SeeMore/SeeMore.hooks.d.ts +14 -0
  29. package/dist/features/admin-widgets/components/SeeMore/SeeMore.hooks.js +57 -0
  30. package/dist/features/admin-widgets/components/SeeMore/SeeMore.js +24 -0
  31. package/dist/features/admin-widgets/components/Select/Select.d.ts +39 -0
  32. package/dist/features/admin-widgets/components/Select/Select.hooks.d.ts +105 -0
  33. package/dist/features/admin-widgets/components/Select/Select.hooks.js +359 -0
  34. package/dist/features/admin-widgets/components/Select/Select.js +46 -0
  35. package/dist/features/admin-widgets/index.d.ts +20 -0
  36. package/dist/features/admin-widgets/index.js +11 -0
  37. package/dist/features/admin-widgets/styles/admin-widgets.css +2 -0
  38. package/dist/features/appearance/constants.d.ts +2 -2
  39. package/dist/features/appearance/constants.js +2 -1
  40. package/dist/features/appearance/react/components/AppearanceTab.js +5 -5
  41. package/dist/features/appearance/rules.d.ts +10 -4
  42. package/dist/features/appearance/rules.js +5 -5
  43. package/dist/features/appearance/types.d.ts +1 -1
  44. package/dist/features/appearance/types.js +1 -1
  45. package/dist/features/asset-grid/react/components/AssetGrid.js +1 -1
  46. package/dist/features/asset-grid/react/components/DeleteConfirmDialog.js +1 -1
  47. package/dist/features/asset-grid/react/hooks/useAssetGridKeyboardShortcuts.js +23 -21
  48. package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.d.ts +1 -1
  49. package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.js +1 -1
  50. package/dist/features/asset-tree-browser/ports.d.ts +3 -1
  51. package/dist/features/asset-tree-browser/react/hooks/useAssetTreeCopyLocalPath.js +1 -1
  52. package/dist/features/browser-chrome/react/components/BrowserViewportControls.js +1 -1
  53. package/dist/features/browser-chrome/types.js +1 -1
  54. package/dist/features/command-palette/ports.js +1 -1
  55. package/dist/features/connectors/ConnectorsBrowser.js +2 -2
  56. package/dist/features/connectors/components/ConnectorCard.js +3 -3
  57. package/dist/features/connectors/components/ConnectorDetailDrawer.js +1 -1
  58. package/dist/features/connectors/components/ConnectorGrid.js +2 -2
  59. package/dist/features/connectors/components/ConnectorSearchBar.js +2 -2
  60. package/dist/features/connectors/components/ProviderTabBar.js +2 -2
  61. package/dist/features/connectors/constants.d.ts +1 -1
  62. package/dist/features/connectors/constants.js +1 -1
  63. package/dist/features/connectors/hooks/useConnectorAuthorization.js +1 -1
  64. package/dist/features/connectors/rules.d.ts +2 -2
  65. package/dist/features/connectors/rules.js +1 -1
  66. package/dist/features/connectors/types.d.ts +2 -2
  67. package/dist/features/connectors/types.js +1 -1
  68. package/dist/features/execution/react/components/ByokProviderForm.js +3 -3
  69. package/dist/features/execution/react/components/ExecutionTab.js +2 -2
  70. package/dist/features/execution/react/components/LocalCliAgentCard.js +3 -3
  71. package/dist/features/execution/react/components/LocalCliAgentList.js +2 -2
  72. package/dist/features/execution/react/components/ProviderChipGroup.js +2 -2
  73. package/dist/features/execution/react/components/SearchableModelSelect.js +1 -1
  74. package/dist/features/execution/rules.js +1 -1
  75. package/dist/features/file-dropzone/react/components/FileDropzone.js +5 -3
  76. package/dist/features/file-dropzone/react/hooks/useFileDropzone.d.ts +1 -1
  77. package/dist/features/file-dropzone/react/hooks/useFileDropzone.js +1 -1
  78. package/dist/features/file-dropzone/types.d.ts +1 -1
  79. package/dist/features/file-dropzone/types.js +1 -1
  80. package/dist/features/folder-path-drop/react/hooks/useFolderPathDropCapture.js +6 -4
  81. package/dist/features/html-editor/canvas-content-wrapper.js +1 -1
  82. package/dist/features/html-editor/canvas-embed-placeholders.js +7 -7
  83. package/dist/features/html-editor/canvas-style.d.ts +4 -0
  84. package/dist/features/html-editor/canvas-style.js +6 -21
  85. package/dist/features/html-viewer/constants.d.ts +1 -1
  86. package/dist/features/html-viewer/constants.js +1 -1
  87. package/dist/features/html-viewer/react/components/PresentMenu.js +1 -1
  88. package/dist/features/html-viewer/react/components/ZoomMenu.js +1 -1
  89. package/dist/features/html-viewer/types.d.ts +1 -1
  90. package/dist/features/html-viewer/types.js +1 -1
  91. package/dist/features/i18n/dictionaries/index.d.ts +2 -3
  92. package/dist/features/i18n/dictionaries/settings-dialog.en.d.ts +1 -1
  93. package/dist/features/i18n/dictionary-translator.d.ts +16 -0
  94. package/dist/features/i18n/dictionary-translator.js +14 -0
  95. package/dist/features/i18n/index.d.ts +3 -0
  96. package/dist/features/i18n/index.js +2 -0
  97. package/dist/features/i18n/locale.d.ts +1 -1
  98. package/dist/features/i18n/template-i18n.d.ts +26 -0
  99. package/dist/features/i18n/template-i18n.js +36 -0
  100. package/dist/features/iframe-pool/react/components/IframeKeepAliveProvider.d.ts +1 -1
  101. package/dist/features/iframe-pool/react/components/IframeKeepAliveProvider.js +1 -1
  102. package/dist/features/instructions/react/components/InstructionsTab.js +1 -1
  103. package/dist/features/integrations/react/components/ClientPicker.js +4 -4
  104. package/dist/features/integrations/react/components/CodexInstallToggleButton.js +1 -1
  105. package/dist/features/integrations/react/components/IntegrationsTab.js +2 -2
  106. package/dist/features/integrations/react/components/SnippetBlock.js +1 -1
  107. package/dist/features/integrations/types.d.ts +1 -1
  108. package/dist/features/integrations/types.js +1 -1
  109. package/dist/features/interactive-ui/index.js +13 -13
  110. package/dist/features/interactive-ui/interactive-ui.css +1 -1
  111. package/dist/features/interactive-ui/providers/recharts/bar-chart.js +1 -1
  112. package/dist/features/interactive-ui/providers/recharts/line-chart.js +1 -1
  113. package/dist/features/interactive-ui/providers/recharts/pie-chart.js +2 -2
  114. package/dist/features/interactive-ui/providers/shadcn/lib/utils.d.ts +1 -1
  115. package/dist/features/interactive-ui/providers/shadcn/lib/utils.js +1 -1
  116. package/dist/features/interactive-ui/registry.d.ts +15 -4
  117. package/dist/features/interactive-ui/registry.js +5 -5
  118. package/dist/features/language/react/components/LanguageTab.js +2 -2
  119. package/dist/features/list-detail-panel/types.d.ts +1 -1
  120. package/dist/features/list-detail-panel/types.js +1 -1
  121. package/dist/features/mcp-ui/confirmation-store.js +2 -1
  122. package/dist/features/mcp-ui/surfaces/tokens.d.ts +17 -20
  123. package/dist/features/mcp-ui/surfaces/tokens.js +33 -35
  124. package/dist/features/media-providers/index.d.ts +1 -1
  125. package/dist/features/media-providers/index.js +1 -1
  126. package/dist/features/media-providers/react/components/MediaProvidersTab.js +4 -4
  127. package/dist/features/media-providers/rules.js +1 -1
  128. package/dist/features/memory/async-commit-guard.d.ts +1 -1
  129. package/dist/features/memory/constants.d.ts +1 -1
  130. package/dist/features/memory/constants.js +1 -1
  131. package/dist/features/memory/dependencies.d.ts +11 -23
  132. package/dist/features/memory/dependencies.js +116 -106
  133. package/dist/features/memory/index.d.ts +1 -1
  134. package/dist/features/memory/index.js +1 -1
  135. package/dist/features/memory/react/components/MemoryAdvancedModal.js +2 -2
  136. package/dist/features/memory/react/components/MemoryEntryCard.js +1 -1
  137. package/dist/features/memory/react/components/MemoryExtractionCard.js +1 -1
  138. package/dist/features/memory/react/components/MemoryHooksPanel.js +1 -1
  139. package/dist/features/memory/react/components/MemoryList.js +5 -5
  140. package/dist/features/memory/react/components/MemoryManualEditor.js +5 -5
  141. package/dist/features/memory/react/components/MemorySettingsPanel.js +1 -1
  142. package/dist/features/memory/react/hooks/useMemoryEntries.hooks.js +1 -1
  143. package/dist/features/memory/react/hooks/useMemoryNavigation.hooks.js +1 -1
  144. package/dist/features/memory/react/styles.js +1 -1
  145. package/dist/features/memory/rules.js +1 -1
  146. package/dist/features/memory/types.d.ts +1 -1
  147. package/dist/features/mention-autocomplete/react/hooks/useMentionAutocomplete.js +1 -1
  148. package/dist/features/notifications/react/components/NotificationsTab.js +7 -7
  149. package/dist/features/notifications/types.d.ts +1 -1
  150. package/dist/features/observability/boot-timing.js +2 -2
  151. package/dist/features/observability/stuck-run.js +1 -1
  152. package/dist/features/observability/white-screen.js +4 -4
  153. package/dist/features/panel-kit/fetch-query/adapter.react.d.ts +35 -0
  154. package/dist/features/panel-kit/fetch-query/adapter.react.js +122 -0
  155. package/dist/features/panel-kit/fetch-query/cache.d.ts +123 -0
  156. package/dist/features/panel-kit/fetch-query/cache.js +231 -0
  157. package/dist/features/panel-kit/fetch-query/environment.browser.d.ts +4 -0
  158. package/dist/features/panel-kit/fetch-query/environment.browser.js +25 -0
  159. package/dist/features/panel-kit/fetch-query/index.d.ts +4 -0
  160. package/dist/features/panel-kit/fetch-query/index.js +2 -0
  161. package/dist/features/panel-kit/fetch-query/types.d.ts +91 -0
  162. package/dist/features/panel-kit/fetch-query/types.js +2 -0
  163. package/dist/features/panel-kit/helpers/format-timestamp.d.ts +18 -0
  164. package/dist/features/panel-kit/helpers/format-timestamp.js +20 -0
  165. package/dist/features/panel-kit/helpers/permissions.d.ts +11 -0
  166. package/dist/features/panel-kit/helpers/permissions.js +10 -0
  167. package/dist/features/panel-kit/helpers/resolve-active-tab-id.d.ts +13 -0
  168. package/dist/features/panel-kit/helpers/resolve-active-tab-id.js +13 -0
  169. package/dist/features/panel-kit/helpers/retry-unreachable.d.ts +20 -0
  170. package/dist/features/panel-kit/helpers/retry-unreachable.js +39 -0
  171. package/dist/features/panel-kit/hooks/use-async-action.hooks.d.ts +13 -0
  172. package/dist/features/panel-kit/hooks/use-async-action.hooks.js +27 -0
  173. package/dist/features/panel-kit/hooks/use-dirty-guard.hooks.d.ts +18 -0
  174. package/dist/features/panel-kit/hooks/use-dirty-guard.hooks.js +33 -0
  175. package/dist/features/panel-kit/hooks/use-focus-trap.hooks.d.ts +8 -0
  176. package/dist/features/panel-kit/hooks/use-focus-trap.hooks.js +66 -0
  177. package/dist/features/panel-kit/hooks/use-serial-writes.hooks.d.ts +26 -0
  178. package/dist/features/panel-kit/hooks/use-serial-writes.hooks.js +41 -0
  179. package/dist/features/panel-kit/hooks/use-settlement-generation.hooks.d.ts +9 -0
  180. package/dist/features/panel-kit/hooks/use-settlement-generation.hooks.js +25 -0
  181. package/dist/features/panel-kit/index.d.ts +19 -0
  182. package/dist/features/panel-kit/index.js +13 -0
  183. package/dist/features/privacy/react/components/PrivacyTab.js +2 -2
  184. package/dist/features/privacy/types.d.ts +1 -1
  185. package/dist/features/privacy/types.js +1 -1
  186. package/dist/features/progress-card/reference-adapters.d.ts +1 -1
  187. package/dist/features/progress-card/rules.d.ts +1 -1
  188. package/dist/features/progress-card/rules.js +1 -1
  189. package/dist/features/progress-card/types.d.ts +1 -1
  190. package/dist/features/progress-card/types.js +1 -1
  191. package/dist/features/resource-dashboard/dependencies.d.ts +1 -1
  192. package/dist/features/resource-dashboard/ports.d.ts +1 -1
  193. package/dist/features/resource-dashboard/react/hooks/useResourceBoard.d.ts +1 -1
  194. package/dist/features/resource-dashboard/react/hooks/useResourceBoard.js +1 -1
  195. package/dist/features/resource-dashboard/rules.d.ts +1 -1
  196. package/dist/features/resource-dashboard/rules.js +2 -2
  197. package/dist/features/resource-dashboard/types.d.ts +4 -4
  198. package/dist/features/resource-dashboard/types.js +1 -1
  199. package/dist/features/schedule-picker/react/hooks/useRecurringSchedulePicker.js +1 -1
  200. package/dist/features/settings/dialog/styles/settings-dialog.css +62 -60
  201. package/dist/features/sketch-editor/constants.d.ts +1 -1
  202. package/dist/features/sketch-editor/constants.js +1 -1
  203. package/dist/features/sketch-editor/dom.d.ts +1 -1
  204. package/dist/features/sketch-editor/dom.js +1 -1
  205. package/dist/features/sketch-editor/react/hooks/useSketchDomEnhancements.d.ts +1 -1
  206. package/dist/features/sketch-editor/react/hooks/useSketchDomEnhancements.js +11 -9
  207. package/dist/features/sketch-editor/types.d.ts +1 -1
  208. package/dist/features/sketch-editor/types.js +1 -1
  209. package/dist/features/skills/react/components/SkillDraftForm.js +1 -1
  210. package/dist/features/skills/react/components/SkillRow.js +1 -1
  211. package/dist/features/skills/react/components/SkillsTab.js +2 -2
  212. package/dist/features/source-config-list/agent-handles.js +2 -2
  213. package/dist/features/source-config-list/react/hooks/useSourceConfigAddForm.d.ts +1 -1
  214. package/dist/features/source-config-list/react/hooks/useSourceConfigAddForm.js +1 -1
  215. package/dist/features/source-config-list/rules.d.ts +1 -1
  216. package/dist/features/source-config-list/rules.js +3 -3
  217. package/dist/features/source-config-list/types.d.ts +1 -1
  218. package/dist/features/source-config-list/types.js +1 -1
  219. package/dist/features/tab-launcher-menu/react/hooks/useTabLauncherMenu.js +1 -1
  220. package/dist/features/tab-strip/index.d.ts +4 -0
  221. package/dist/features/tab-strip/index.js +2 -0
  222. package/dist/features/tab-strip/react/components/TabBar.d.ts +23 -0
  223. package/dist/features/tab-strip/react/components/TabBar.hooks.d.ts +25 -0
  224. package/dist/features/tab-strip/react/components/TabBar.hooks.js +57 -0
  225. package/dist/features/tab-strip/react/components/TabBar.js +18 -0
  226. package/dist/features/tab-strip/react/components/TabStrip.js +2 -1
  227. package/dist/features/tab-strip/react/components/TabStripFrame.d.ts +3 -0
  228. package/dist/features/tab-strip/react/components/TabStripFrame.js +7 -0
  229. package/dist/features/tabbed-dialog/react/hooks/useTabbedDialog.js +1 -1
  230. package/dist/features/tabbed-dialog/styles/tabbed-dialog.css +8 -141
  231. package/dist/features/tabbed-dialog/types.d.ts +1 -1
  232. package/dist/features/tabbed-dialog/types.js +1 -1
  233. package/dist/features/version-manager/ports.d.ts +1 -1
  234. package/dist/features/version-manager/react/components/VersionPromptPopover.js +5 -3
  235. package/dist/features/version-manager/react/components/VersionRestoreControl.js +1 -1
  236. package/dist/features/version-manager/types.d.ts +1 -1
  237. package/dist/features/version-manager/types.js +1 -1
  238. package/dist/features/viewer-shell/dependencies.js +1 -1
  239. package/dist/features/viewer-shell/ports.d.ts +1 -1
  240. package/dist/features/viewer-shell/react/components/ViewportSwitcher.js +1 -1
  241. package/dist/features/viewer-shell/react/hooks/useMarkdownScrollSync.d.ts +1 -1
  242. package/dist/features/viewer-shell/react/hooks/useMarkdownScrollSync.js +1 -1
  243. package/dist/features/viewer-shell/types.d.ts +1 -1
  244. package/dist/features/viewer-shell/types.js +1 -1
  245. package/dist/index.d.ts +420 -0
  246. package/dist/index.js +421 -1
  247. package/dist/react/components/ComponentKitPreview.js +1 -1
  248. package/dist/react/components/EditorIcon.d.ts +1 -1
  249. package/dist/react/components/EditorIcon.js +22 -22
  250. package/dist/react/components/ExportDiagnosticsButton.d.ts +8 -1
  251. package/dist/react/components/ExportDiagnosticsButton.js +6 -6
  252. package/dist/react/components/PaletteTweaks.js +5 -5
  253. package/dist/react/hooks/useBrandFonts.d.ts +19 -4
  254. package/dist/react/hooks/useBrandFonts.js +11 -7
  255. package/dist/react/hooks/useDebouncedValue.d.ts +12 -1
  256. package/dist/react/hooks/useDebouncedValue.js +9 -4
  257. package/dist/react/hooks/useStableHandler.d.ts +3 -1
  258. package/dist/react/hooks/useStableHandler.js +1 -1
  259. package/dist/renderers/annotation-canvas/drawing.d.ts +4 -4
  260. package/dist/renderers/annotation-canvas/drawing.js +28 -15
  261. package/dist/renderers/annotation-canvas/react/components/AnnotationCanvas.js +2 -2
  262. package/dist/renderers/annotation-canvas/react/hooks/useAnnotationCanvas.js +4 -3
  263. package/dist/renderers/annotation-canvas/rules.d.ts +1 -1
  264. package/dist/renderers/annotation-canvas/theme.d.ts +13 -0
  265. package/dist/renderers/annotation-canvas/theme.js +16 -0
  266. package/dist/renderers/annotation-canvas/types.d.ts +1 -1
  267. package/dist/renderers/index.d.ts +1 -1
  268. package/dist/renderers/new-tab-preview.d.ts +3 -0
  269. package/dist/renderers/new-tab-preview.js +3 -1
  270. package/dist/renderers/preview-modal-shell/react/hooks/usePreviewModalShell.d.ts +1 -1
  271. package/dist/renderers/preview-modal-shell/react/hooks/usePreviewModalShell.js +1 -1
  272. package/dist/renderers/preview-modal-shell/rules.d.ts +1 -1
  273. package/dist/renderers/preview-modal-shell/types.d.ts +3 -3
  274. package/dist/renderers/preview-modal-shell/types.js +2 -2
  275. package/dist/renderers/react/components/ArtifactView.d.ts +1 -1
  276. package/dist/renderers/react/components/ArtifactView.js +1 -1
  277. package/dist/renderers/registry.d.ts +12 -6
  278. package/dist/renderers/registry.js +7 -9
  279. package/dist/renderers/renderers/html.js +2 -2
  280. package/dist/renderers/renderers/index.js +1 -1
  281. package/dist/renderers/renderers/markdown.js +2 -2
  282. package/dist/renderers/renderers/react-component.js +1 -1
  283. package/dist/renderers/renderers/svg.js +1 -1
  284. package/dist/renderers/shiki.js +1 -1
  285. package/dist/renderers/srcdoc/build.d.ts +1 -1
  286. package/dist/renderers/srcdoc/build.js +1 -1
  287. package/dist/renderers/url-load-decision.d.ts +1 -1
  288. package/dist/renderers/url-load-decision.js +1 -1
  289. package/dist/styles/admin.css +273 -0
  290. package/dist/styles/variables.css +117 -0
  291. package/dist/theme/apply.d.ts +9 -0
  292. package/dist/theme/apply.js +77 -0
  293. package/dist/theme/color-scheme.d.ts +8 -0
  294. package/dist/theme/color-scheme.js +9 -0
  295. package/dist/theme/default.d.ts +4 -0
  296. package/dist/theme/default.js +11 -0
  297. package/dist/theme/index.d.ts +6 -0
  298. package/dist/theme/index.js +5 -0
  299. package/dist/theme/stylesheet.d.ts +8 -0
  300. package/dist/theme/stylesheet.js +14 -0
  301. package/dist/theme/types.d.ts +39 -0
  302. package/dist/theme/types.js +2 -0
  303. package/dist/theme/validation.d.ts +15 -0
  304. package/dist/theme/validation.js +55 -0
  305. package/dist/utils/appearance.js +1 -1
  306. package/dist/utils/browser-request.d.ts +12 -0
  307. package/dist/utils/browser-request.js +10 -0
  308. package/dist/utils/color-math.d.ts +20 -6
  309. package/dist/utils/color-math.js +12 -12
  310. package/dist/utils/copy-to-clipboard.d.ts +19 -8
  311. package/dist/utils/copy-to-clipboard.js +15 -11
  312. package/dist/utils/dom-subscriptions.js +1 -1
  313. package/dist/utils/endpoint-policy.d.ts +9 -3
  314. package/dist/utils/endpoint-policy.js +5 -5
  315. package/dist/utils/markdown-scroll-sync.js +3 -3
  316. package/dist/utils/notifications.d.ts +1 -1
  317. package/dist/utils/notifications.js +1 -1
  318. package/dist/utils/polygon-selection.d.ts +1 -1
  319. package/dist/utils/polygon-selection.js +1 -1
  320. package/dist/utils/scroll-tabs-with-wheel.d.ts +4 -1
  321. package/dist/utils/scroll-tabs-with-wheel.js +1 -1
  322. package/dist/utils/smooth-scroll-to-top.js +1 -1
  323. package/dist/utils/sse.d.ts +3 -1
  324. package/dist/utils/sse.js +1 -1
  325. package/package.json +105 -16
  326. package/dist/features/lexical-rich-text-editor/react/test-support/lexical-harness.d.ts +0 -11
  327. package/dist/features/lexical-rich-text-editor/react/test-support/lexical-harness.js +0 -35
@@ -0,0 +1,105 @@
1
+ export interface SelectOption {
2
+ value: string;
3
+ label: string;
4
+ }
5
+ export declare function focusableInDomOrder({ exclude }: {
6
+ exclude: HTMLElement | null;
7
+ }): HTMLElement[];
8
+ export interface PanelPosition {
9
+ top?: number | undefined;
10
+ bottom?: number | undefined;
11
+ left: number;
12
+ width: number;
13
+ maxHeight: number;
14
+ }
15
+ /**
16
+ * Use fixed viewport-relative coordinates to escape scrolling/overflow-hidden ancestors
17
+ * without coupling to their layout. maxHeight uses actual remaining space, not the estimate,
18
+ * so the panel scroll area clips options before the viewport edge does.
19
+ */
20
+ export declare function computePosition({ trigger }: {
21
+ trigger: HTMLElement;
22
+ }): PanelPosition;
23
+ export declare function buildOptionId({ listboxId, index }: {
24
+ listboxId: string;
25
+ index: number;
26
+ }): string;
27
+ /**
28
+ * Positioning reports a clipped or obscured trigger through onOutOfView; deciding whether
29
+ * to close belongs to the dropdown lifecycle rather than this reusable measurement hook.
30
+ */
31
+ export declare function usePanelPosition({ open, triggerRef, panelRef, searchInputRef, showSearch, onOutOfView, }: {
32
+ open: boolean;
33
+ triggerRef: React.RefObject<HTMLButtonElement | null>;
34
+ panelRef: React.RefObject<HTMLDivElement | null>;
35
+ searchInputRef: React.RefObject<HTMLInputElement | null>;
36
+ showSearch: boolean;
37
+ onOutOfView: () => void;
38
+ }): {
39
+ position: PanelPosition | null;
40
+ setPosition: import("react").Dispatch<import("react").SetStateAction<PanelPosition | null>>;
41
+ };
42
+ export declare function repositionOrClose({ trigger, onOutOfView, setPosition }: {
43
+ trigger: HTMLElement;
44
+ onOutOfView: () => void;
45
+ setPosition: (position: PanelPosition) => void;
46
+ }): void;
47
+ export declare function resolveTabTarget({ panel, trigger, shiftKey }: {
48
+ panel: HTMLElement | null;
49
+ trigger: HTMLElement | null;
50
+ shiftKey: boolean;
51
+ }): HTMLElement | null;
52
+ export declare function edgeHighlightIndex({ filteredLength, edge }: {
53
+ filteredLength: number;
54
+ edge: "first" | "last";
55
+ }): number;
56
+ export declare function highlightedOptionOrNull({ filtered, highlightedIndex }: {
57
+ filtered: SelectOption[];
58
+ highlightedIndex: number;
59
+ }): SelectOption | null;
60
+ export declare function applyHighlightKey({ key, filtered, highlightedIndex, actions }: {
61
+ key: string;
62
+ filtered: SelectOption[];
63
+ highlightedIndex: number;
64
+ actions: {
65
+ preventDefault: () => void;
66
+ moveHighlight: (delta: 1 | -1) => void;
67
+ setHighlightedIndex: (index: number) => void;
68
+ selectOption: (option: SelectOption) => void;
69
+ };
70
+ }): boolean;
71
+ /**
72
+ * Separate hook state from rendering so search visibility, wraparound, placement and
73
+ * out-of-view closing can be asserted directly without coupling every case to portal DOM.
74
+ */
75
+ export declare function useSelectDropdown({ value, onChange, options, }: {
76
+ value: string;
77
+ onChange: (value: string) => void;
78
+ options: SelectOption[];
79
+ }, { disabled }?: {
80
+ disabled?: boolean | undefined;
81
+ }): {
82
+ open: boolean;
83
+ query: string;
84
+ setQuery: import("react").Dispatch<import("react").SetStateAction<string>>;
85
+ highlightedIndex: number;
86
+ setHighlightedIndex: import("react").Dispatch<import("react").SetStateAction<number>>;
87
+ position: PanelPosition | null;
88
+ triggerRef: import("react").RefObject<HTMLButtonElement | null>;
89
+ panelRef: import("react").RefObject<HTMLDivElement | null>;
90
+ searchInputRef: import("react").RefObject<HTMLInputElement | null>;
91
+ optionRefs: import("react").RefObject<Map<number, HTMLLIElement>>;
92
+ listboxId: string;
93
+ showSearch: boolean;
94
+ filtered: SelectOption[];
95
+ selectedOption: SelectOption | null;
96
+ openPanel: () => void;
97
+ closePanel: (opts: {
98
+ refocusTrigger: boolean;
99
+ }) => void;
100
+ selectOption: (option: SelectOption) => void;
101
+ handleTriggerKeyDown: (e: React.KeyboardEvent<HTMLButtonElement>) => void;
102
+ handlePanelKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void;
103
+ optionId: (index: number) => string;
104
+ };
105
+ //# sourceMappingURL=Select.hooks.d.ts.map
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Keep state/effects and DOM helpers separate from JSX so the dropdown hook can be
3
+ * injected through useDropdown and exercised directly without driving a portaled tree.
4
+ * Compose the smaller hooks unconditionally in their original relative order to obey
5
+ * React hook ordering. Extracting the live DOM key handling from pure highlight decisions
6
+ * reduces the review burden without changing focus or event-order contracts.
7
+ */
8
+ import { useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
9
+ // Below eight options, a search field adds clutter to a list that is already easy to scan.
10
+ const SEARCH_VISIBILITY_THRESHOLD = 8;
11
+ // 280px is only a placement heuristic; the panel actual maxHeight and scroll limit use
12
+ // the remaining viewport space so a low trigger does not open a mostly off-screen panel.
13
+ const ESTIMATED_PANEL_HEIGHT = 280;
14
+ // The panel is portaled to the end of document.body. Native Tab would follow that DOM
15
+ // position toward browser chrome; walk the trigger real DOM-order neighbours instead.
16
+ const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
17
+ export function focusableInDomOrder({ exclude }) {
18
+ return Array.from(document.querySelectorAll(FOCUSABLE_SELECTOR)).filter((el) => !exclude || !exclude.contains(el));
19
+ }
20
+ /**
21
+ * Use fixed viewport-relative coordinates to escape scrolling/overflow-hidden ancestors
22
+ * without coupling to their layout. maxHeight uses actual remaining space, not the estimate,
23
+ * so the panel scroll area clips options before the viewport edge does.
24
+ */
25
+ export function computePosition({ trigger }) {
26
+ const rect = trigger.getBoundingClientRect();
27
+ const gap = 4;
28
+ const viewportHeight = window.innerHeight;
29
+ const spaceBelow = viewportHeight - rect.bottom;
30
+ const spaceAbove = rect.top;
31
+ const openUpward = spaceBelow < ESTIMATED_PANEL_HEIGHT && spaceAbove > spaceBelow;
32
+ if (openUpward) {
33
+ return { bottom: viewportHeight - rect.top + gap, left: rect.left, width: rect.width, maxHeight: Math.max(120, spaceAbove - gap * 2) };
34
+ }
35
+ return { top: rect.bottom + gap, left: rect.left, width: rect.width, maxHeight: Math.max(120, spaceBelow - gap * 2) };
36
+ }
37
+ export function buildOptionId({ listboxId, index }) {
38
+ return `${listboxId}-option-${index}`;
39
+ }
40
+ /**
41
+ * Positioning reports a clipped or obscured trigger through onOutOfView; deciding whether
42
+ * to close belongs to the dropdown lifecycle rather than this reusable measurement hook.
43
+ */
44
+ export function usePanelPosition({ open, triggerRef, panelRef, searchInputRef, showSearch, onOutOfView, }) {
45
+ const [position, setPosition] = useState(null);
46
+ // Two phases, deliberately in one effect rather than two: (1) `position` starts `null` on every
47
+ // open (`closePanel` resets it), so the panel/`createPortal` call below isn't rendered at all yet
48
+ // — `panelRef`/`searchInputRef` are still unattached, so focusing them here would silently no-op.
49
+ // Computing `position` schedules a state update; because this is a `useLayoutEffect`, React
50
+ // re-renders and re-runs layout effects synchronously before the browser paints, rather than
51
+ // waiting a frame. (2) On that second pass `position` is non-null, the portal now exists in the
52
+ // DOM, and the refs are populated — only now is it correct to move focus into it. Found live via
53
+ // this component's own tests: every keyboard-driven test failed until this was split out, because
54
+ // `panelRef.current`/`searchInputRef.current` were both still `null` when focus was attempted in
55
+ // the same pass that first computed the position.
56
+ // biome-ignore lint/correctness/useExhaustiveDependencies: two-phase focus effect — see comment above; refs/showSearch intentionally excluded, only open/position redrive it.
57
+ useLayoutEffect(() => {
58
+ if (!open)
59
+ return;
60
+ if (!position) {
61
+ if (triggerRef.current)
62
+ setPosition(computePosition({ trigger: triggerRef.current }));
63
+ return;
64
+ }
65
+ if (showSearch) {
66
+ searchInputRef.current?.focus();
67
+ }
68
+ else {
69
+ panelRef.current?.focus();
70
+ }
71
+ }, [open, position]);
72
+ // Keeps the panel anchored to the trigger if the surrounding page/dialog scrolls or resizes while
73
+ // it's open — `.widget-picker-body`'s own `overflow-y: auto` made this a real, live scenario
74
+ // rather than a hypothetical one. `scroll` needs the capture phase: an inner element's own scroll
75
+ // does not bubble to `window` in the bubble phase. The decision logic itself is
76
+ // `repositionOrClose`, above; this effect is only the DOM listener wiring.
77
+ //
78
+ // Found live in a real browser, not by this component's own test suite: scrolling a host's
79
+ // scrolling ancestor far enough that the trigger scrolls out of its own visible clip used to leave
80
+ // this effect happily recomputing a mathematically-correct `position` for it — the panel just
81
+ // ended up following the trigger to an off-screen (or behind-the-header, obscured) spot, floating
82
+ // there indefinitely, nominally still "open" with no visible way to tell.
83
+ // biome-ignore lint/correctness/useExhaustiveDependencies: scroll/resize listener wiring — see comment above; triggerRef/onOutOfView intentionally excluded, only `open` re-arms it.
84
+ useEffect(() => {
85
+ if (!open)
86
+ return;
87
+ function reposition() {
88
+ const el = triggerRef.current;
89
+ if (!el)
90
+ return;
91
+ repositionOrClose({ trigger: el, onOutOfView: onOutOfView, setPosition: setPosition });
92
+ }
93
+ window.addEventListener("scroll", reposition, true);
94
+ window.addEventListener("resize", reposition);
95
+ return () => {
96
+ window.removeEventListener("scroll", reposition, true);
97
+ window.removeEventListener("resize", reposition);
98
+ };
99
+ }, [open]);
100
+ return { position, setPosition };
101
+ }
102
+ export function repositionOrClose({ trigger, onOutOfView, setPosition }) {
103
+ const rect = trigger.getBoundingClientRect();
104
+ const outOfViewport = rect.bottom <= 0 || rect.top >= window.innerHeight || rect.right <= 0 || rect.left >= window.innerWidth;
105
+ if (outOfViewport) {
106
+ onOutOfView();
107
+ return;
108
+ }
109
+ if (typeof document.elementFromPoint === "function") {
110
+ const topmostAtCenter = document.elementFromPoint(rect.left + rect.width / 2, rect.top + rect.height / 2);
111
+ const obscured = !topmostAtCenter || !(trigger.contains(topmostAtCenter) || topmostAtCenter.contains(trigger));
112
+ if (obscured) {
113
+ onOutOfView();
114
+ return;
115
+ }
116
+ }
117
+ setPosition(computePosition({ trigger: trigger }));
118
+ }
119
+ function useCloseOnOutsideClick({ open, triggerRef, panelRef, onOutside, }) {
120
+ useEffect(() => {
121
+ if (!open)
122
+ return;
123
+ function onDocMouseDown(e) {
124
+ const target = e.target;
125
+ if (triggerRef.current?.contains(target))
126
+ return;
127
+ if (panelRef.current?.contains(target))
128
+ return;
129
+ onOutside();
130
+ }
131
+ document.addEventListener("mousedown", onDocMouseDown);
132
+ return () => document.removeEventListener("mousedown", onDocMouseDown);
133
+ // eslint-disable-next-line react-hooks/exhaustive-deps
134
+ }, [open]);
135
+ }
136
+ // A search can remove the previously highlighted option; re-anchor to the first match
137
+ // rather than keep a stale index outside the narrowed list.
138
+ function useResetHighlightOnQueryChange({ open, query, hasMatches, setHighlightedIndex, }) {
139
+ useEffect(() => {
140
+ if (!open)
141
+ return;
142
+ setHighlightedIndex(hasMatches ? 0 : -1);
143
+ // eslint-disable-next-line react-hooks/exhaustive-deps
144
+ }, [query]);
145
+ }
146
+ /**
147
+ * Keyboard highlight used to move logically past the visible fold without scrolling its
148
+ * row into view. nearest scrolls only what is needed instead of recentering the list and
149
+ * fighting a user who has already scrolled it manually.
150
+ */
151
+ function useScrollHighlightedIntoView({ open, highlightedIndex, optionRefs, }) {
152
+ useEffect(() => {
153
+ if (!open || highlightedIndex < 0)
154
+ return;
155
+ const el = optionRefs.current.get(highlightedIndex);
156
+ // Guarded the same way as `document.elementFromPoint` above — this app's own jsdom test
157
+ // harness doesn't implement `scrollIntoView` at all (not even as a no-op), so an unguarded call
158
+ // throws inside the effect on every highlight change.
159
+ if (el && typeof el.scrollIntoView === "function")
160
+ el.scrollIntoView({ block: "nearest" });
161
+ }, [open, highlightedIndex]);
162
+ }
163
+ export function resolveTabTarget({ panel, trigger, shiftKey }) {
164
+ const nodes = focusableInDomOrder({ exclude: panel });
165
+ const triggerIndex = trigger ? nodes.indexOf(trigger) : -1;
166
+ if (triggerIndex < 0)
167
+ return null;
168
+ return nodes[triggerIndex + (shiftKey ? -1 : 1)] ?? null;
169
+ }
170
+ export function edgeHighlightIndex({ filteredLength, edge }) {
171
+ if (filteredLength === 0)
172
+ return -1;
173
+ return edge === "first" ? 0 : filteredLength - 1;
174
+ }
175
+ export function highlightedOptionOrNull({ filtered, highlightedIndex }) {
176
+ return highlightedIndex >= 0 ? (filtered[highlightedIndex] ?? null) : null;
177
+ }
178
+ export function applyHighlightKey({ key, filtered, highlightedIndex, actions }) {
179
+ switch (key) {
180
+ case "ArrowDown":
181
+ actions.preventDefault();
182
+ actions.moveHighlight(1);
183
+ return true;
184
+ case "ArrowUp":
185
+ actions.preventDefault();
186
+ actions.moveHighlight(-1);
187
+ return true;
188
+ case "Home":
189
+ actions.preventDefault();
190
+ actions.setHighlightedIndex(edgeHighlightIndex({ filteredLength: filtered.length, edge: "first" }));
191
+ return true;
192
+ case "End":
193
+ actions.preventDefault();
194
+ actions.setHighlightedIndex(edgeHighlightIndex({ filteredLength: filtered.length, edge: "last" }));
195
+ return true;
196
+ case "Enter": {
197
+ actions.preventDefault();
198
+ const option = highlightedOptionOrNull({ filtered: filtered, highlightedIndex: highlightedIndex });
199
+ if (option)
200
+ actions.selectOption(option);
201
+ return true;
202
+ }
203
+ default:
204
+ return false;
205
+ }
206
+ }
207
+ // Keep live event/focus effects in the key handler; move the trigger-neighbour calculation
208
+ // out so changing the DOM effects does not bury the independently testable focus decision.
209
+ function useSelectKeyboardHandlers({ disabled, open, openPanel, closePanel, moveHighlight, selectOption, highlightedIndex, setHighlightedIndex, filtered, triggerRef, panelRef, }) {
210
+ function handleTriggerKeyDown(e) {
211
+ if (disabled || open)
212
+ return;
213
+ switch (e.key) {
214
+ case "Enter":
215
+ case " ":
216
+ case "ArrowDown":
217
+ case "ArrowUp":
218
+ e.preventDefault();
219
+ openPanel();
220
+ break;
221
+ default:
222
+ break;
223
+ }
224
+ }
225
+ // Escape/Tab need live propagation and focus effects. Highlight/selection keys delegate
226
+ // to the pure helper; preventDefault is injected to preserve its order before each action.
227
+ function handlePanelKeyDown(e) {
228
+ if (e.key === "Escape") {
229
+ // Must not bubble: a host dialog (`WidgetPickerDialog`) listens for Escape on `document`
230
+ // to cancel the whole modal. Without stopping propagation here, closing just this dropdown
231
+ // would also close the dialog underneath it — the regression `Select.unit.test.tsx` pins.
232
+ e.preventDefault();
233
+ e.stopPropagation();
234
+ closePanel({ refocusTrigger: true });
235
+ return;
236
+ }
237
+ if (e.key === "Tab") {
238
+ // See `resolveTabTarget`'s own comment: walk the trigger's real DOM-order neighbours rather
239
+ // than let native Tab handling run, since this event is bubbling from a panel portaled to
240
+ // the end of `document.body`, not sitting next to the trigger in the DOM.
241
+ const target = resolveTabTarget({ panel: panelRef.current, trigger: triggerRef.current, shiftKey: e.shiftKey });
242
+ e.preventDefault();
243
+ closePanel({ refocusTrigger: false });
244
+ target?.focus();
245
+ return;
246
+ }
247
+ applyHighlightKey({ key: e.key, filtered: filtered, highlightedIndex: highlightedIndex, actions: {
248
+ preventDefault: () => e.preventDefault(),
249
+ moveHighlight,
250
+ setHighlightedIndex,
251
+ selectOption,
252
+ } });
253
+ }
254
+ return { handleTriggerKeyDown, handlePanelKeyDown };
255
+ }
256
+ /**
257
+ * Separate hook state from rendering so search visibility, wraparound, placement and
258
+ * out-of-view closing can be asserted directly without coupling every case to portal DOM.
259
+ */
260
+ export function useSelectDropdown({ value, onChange, options, }, { disabled } = {}) {
261
+ const [open, setOpen] = useState(false);
262
+ const [query, setQuery] = useState("");
263
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
264
+ const triggerRef = useRef(null);
265
+ const panelRef = useRef(null);
266
+ const searchInputRef = useRef(null);
267
+ // Index -> `<li>` node, so the highlight-follow effect below can scroll the right row into view
268
+ // without an id-based `querySelector` (this component's ids come from `useId()`, which can
269
+ // contain characters — `:`, in React's own scheme — that need escaping in a CSS selector; a
270
+ // direct ref avoids that entirely). Populated by each option's own ref callback below.
271
+ const optionRefs = useRef(new Map());
272
+ const listboxId = useId();
273
+ const showSearch = options.length >= SEARCH_VISIBILITY_THRESHOLD;
274
+ const filtered = useMemo(() => {
275
+ if (!showSearch || !query.trim())
276
+ return options;
277
+ const q = query.trim().toLowerCase();
278
+ return options.filter((o) => o.label.toLowerCase().includes(q));
279
+ }, [options, query, showSearch]);
280
+ const selectedOption = options.find((o) => o.value === value) ?? null;
281
+ function openPanel() {
282
+ if (disabled)
283
+ return;
284
+ const initialIndex = options.findIndex((o) => o.value === value);
285
+ setQuery("");
286
+ setOpen(true);
287
+ setHighlightedIndex(initialIndex >= 0 ? initialIndex : options.length ? 0 : -1);
288
+ }
289
+ function closePanel(opts) {
290
+ setOpen(false);
291
+ setPosition(null); // forces the effect below through its "measure, then focus" two-phase sequence again on the next open, rather than focusing at a stale, pre-close position
292
+ if (opts.refocusTrigger)
293
+ triggerRef.current?.focus();
294
+ }
295
+ function selectOption(option) {
296
+ onChange(option.value);
297
+ closePanel({ refocusTrigger: true });
298
+ }
299
+ function moveHighlight(delta) {
300
+ setHighlightedIndex((current) => {
301
+ if (filtered.length === 0)
302
+ return -1;
303
+ return (current + delta + filtered.length) % filtered.length;
304
+ });
305
+ }
306
+ const { position, setPosition } = usePanelPosition({
307
+ open,
308
+ triggerRef,
309
+ panelRef,
310
+ searchInputRef,
311
+ showSearch,
312
+ onOutOfView: () => closePanel({ refocusTrigger: false }),
313
+ });
314
+ useCloseOnOutsideClick({
315
+ open,
316
+ triggerRef,
317
+ panelRef,
318
+ onOutside: () => closePanel({ refocusTrigger: false }),
319
+ });
320
+ useResetHighlightOnQueryChange({ open, query, hasMatches: filtered.length > 0, setHighlightedIndex });
321
+ useScrollHighlightedIntoView({ open, highlightedIndex, optionRefs });
322
+ const { handleTriggerKeyDown, handlePanelKeyDown } = useSelectKeyboardHandlers({
323
+ disabled,
324
+ open,
325
+ openPanel,
326
+ closePanel,
327
+ moveHighlight,
328
+ selectOption,
329
+ highlightedIndex,
330
+ setHighlightedIndex,
331
+ filtered,
332
+ triggerRef,
333
+ panelRef,
334
+ });
335
+ const optionId = (index) => buildOptionId({ listboxId: listboxId, index: index });
336
+ return {
337
+ open,
338
+ query,
339
+ setQuery,
340
+ highlightedIndex,
341
+ setHighlightedIndex,
342
+ position,
343
+ triggerRef,
344
+ panelRef,
345
+ searchInputRef,
346
+ optionRefs,
347
+ listboxId,
348
+ showSearch,
349
+ filtered,
350
+ selectedOption,
351
+ openPanel,
352
+ closePanel,
353
+ selectOption,
354
+ handleTriggerKeyDown,
355
+ handlePanelKeyDown,
356
+ optionId,
357
+ };
358
+ }
359
+ //# sourceMappingURL=Select.hooks.js.map
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { createPortal } from "react-dom";
3
+ import { agentHandle } from "@jini-ai/agentic";
4
+ import { buildAgentListHandles } from "@jini-ai/agentic";
5
+ import { useSelectDropdown } from "./Select.hooks.js";
6
+ function SelectOptionRow({ option, index, isSelected, isHighlighted, optionId, setOptionRef, onHighlight, onSelect, agentHandle: optionHandle, }) {
7
+ return (_jsxs("li", { ref: (el) => setOptionRef(index, el), id: optionId, role: "option", "aria-selected": isSelected, className: `select-option${isSelected ? " is-selected" : ""}${isHighlighted ? " is-highlighted" : ""}`, onMouseEnter: () => onHighlight(index), onClick: () => onSelect(option), ...(optionHandle ? agentHandle({ handle: optionHandle }, { role: "button", label: option.label }) : {}), children: [_jsx("span", { className: "select-option-label", children: option.label }), isSelected ? (_jsx("svg", { className: "select-option-check", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M3.5 8.5 6.5 11.5 12.5 4.5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) })) : null] }));
8
+ }
9
+ function SelectPanel({ panelRef, position, showSearch, searchInputRef, query, setQuery, filtered, value, highlightedIndex, listboxId, optionId, setOptionRef, onHighlight, onSelect, onKeyDown, searchHandle, optionHandles, t, }) {
10
+ return (_jsxs("div", { ref: panelRef, className: "select-panel", style: { left: position.left, width: position.width, top: position.top, bottom: position.bottom, maxHeight: position.maxHeight }, tabIndex: -1, onKeyDown: onKeyDown, children: [showSearch ? (_jsx("input", { ref: searchInputRef, type: "text", className: "select-search", "aria-label": t("Search options"), placeholder: t("Search…"), value: query, onChange: (e) => setQuery(e.target.value), ...(searchHandle ? agentHandle({ handle: searchHandle }, { role: "field", label: "Search the option list" }) : {}) })) : null, _jsx("ul", { className: "select-list", role: "listbox", id: listboxId, children: filtered.length === 0 ? (_jsx("li", { className: "select-empty", role: "presentation", children: t("No matches") })) : (filtered.map((option, index) => (_jsx(SelectOptionRow, { option: option, index: index, isSelected: option.value === value, isHighlighted: index === highlightedIndex, optionId: optionId(index), setOptionRef: setOptionRef, onHighlight: onHighlight, onSelect: onSelect, agentHandle: optionHandles?.[index] }, option.value)))) })] }));
11
+ }
12
+ export function resolveSelectTriggerLabel({ selectedOption, placeholder }, { t = (key) => key } = {}) {
13
+ if (selectedOption)
14
+ return { text: selectedOption.label, className: "select-trigger-label" };
15
+ return { text: placeholder ?? t("Select…"), className: "select-trigger-label is-placeholder" };
16
+ }
17
+ function resolveSelectTriggerActiveDescendant(open, highlightedIndex, optionId) {
18
+ return open && highlightedIndex >= 0 ? optionId(highlightedIndex) : undefined;
19
+ }
20
+ function resolveSelectTriggerHandleProps(base, ariaLabel, placeholder) {
21
+ return base ? agentHandle({ handle: base }, { role: "button", label: ariaLabel ?? placeholder ?? "Select an option" }) : {};
22
+ }
23
+ /** Controlled searchable listbox with portal positioning and keyboard navigation. */
24
+ export function Select(props) {
25
+ const { value, onChange, options, placeholder, id, disabled, useDropdown = useSelectDropdown, agentHandle: base, translate, t = translate ?? ((key) => key) } = props;
26
+ const ariaLabel = props["aria-label"];
27
+ const ariaLabelledBy = props["aria-labelledby"];
28
+ const { open, highlightedIndex, setHighlightedIndex, position, triggerRef, panelRef, searchInputRef, optionRefs, listboxId, showSearch, filtered, selectedOption, openPanel, closePanel, selectOption, handleTriggerKeyDown, handlePanelKeyDown, optionId, query, setQuery, } = useDropdown({ value, onChange, options }, { disabled });
29
+ function setOptionRef(index, el) {
30
+ if (el)
31
+ optionRefs.current.set(index, el);
32
+ else
33
+ optionRefs.current.delete(index);
34
+ }
35
+ const triggerLabel = resolveSelectTriggerLabel({ selectedOption: selectedOption, placeholder: placeholder }, { t: t });
36
+ const activeDescendant = resolveSelectTriggerActiveDescendant(open, highlightedIndex, optionId);
37
+ // One handle per FILTERED option, recomputed as the search query narrows the list — an option
38
+ // dropped by the current query has no rendered row to attach a handle to, so it is simply absent
39
+ // this render rather than holding a handle nothing resolves to. `undefined` (not an empty array)
40
+ // when `base` itself is unset, so `SelectPanel` can tell "opted out" apart from "no options match".
41
+ const optionHandles = base ? buildAgentListHandles({ prefix: `${base}-option`, ids: filtered.map((option) => option.value) }) : undefined;
42
+ return (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", ref: triggerRef, id: id, className: "select-trigger", role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", "aria-controls": open ? listboxId : undefined, "aria-activedescendant": activeDescendant, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, disabled: disabled, onClick: () => (open ? closePanel({ refocusTrigger: false }) : openPanel()), onKeyDown: handleTriggerKeyDown, ...resolveSelectTriggerHandleProps(base, ariaLabel, placeholder), children: [_jsx("span", { className: triggerLabel.className, children: triggerLabel.text }), _jsx("span", { className: "select-trigger-chevron", "aria-hidden": "true" })] }), open && position
43
+ ? createPortal(_jsx(SelectPanel, { panelRef: panelRef, position: position, showSearch: showSearch, searchInputRef: searchInputRef, query: query, setQuery: setQuery, filtered: filtered, value: value, highlightedIndex: highlightedIndex, listboxId: listboxId, optionId: optionId, setOptionRef: setOptionRef, onHighlight: setHighlightedIndex, onSelect: selectOption, onKeyDown: handlePanelKeyDown, searchHandle: base ? `${base}-search` : undefined, optionHandles: optionHandles, t: t }), document.body)
44
+ : null] }));
45
+ }
46
+ //# sourceMappingURL=Select.js.map
@@ -0,0 +1,20 @@
1
+ export { Select, resolveSelectTriggerLabel } from './components/Select/Select.js';
2
+ export type { SelectProps, SelectOption } from './components/Select/Select.js';
3
+ export { useSelectDropdown, usePanelPosition } from './components/Select/Select.hooks.js';
4
+ export type { PanelPosition } from './components/Select/Select.hooks.js';
5
+ export { InfoTip } from './components/InfoTip.js';
6
+ export type { InfoTipProps } from './components/InfoTip.js';
7
+ export { useInfoTip } from './components/InfoTip.hooks.js';
8
+ export type { InfoTipController } from './components/InfoTip.hooks.js';
9
+ export { SeeMore, resolveSeeMoreView } from './components/SeeMore/SeeMore.js';
10
+ export type { SeeMoreProps, SeeMoreView } from './components/SeeMore/SeeMore.js';
11
+ export { useSeeMoreClamp } from './components/SeeMore/SeeMore.hooks.js';
12
+ export { ImagePreviewModal } from './components/ImagePreviewModal.js';
13
+ export type { ImagePreviewModalProps } from './components/ImagePreviewModal.js';
14
+ export { useImagePreviewModal } from './components/ImagePreviewModal.hooks.js';
15
+ export type { ImagePreviewModalController } from './components/ImagePreviewModal.hooks.js';
16
+ export { ComingSoonPanel } from './components/ComingSoonPanel.js';
17
+ export type { ComingSoonPanelProps } from './components/ComingSoonPanel.js';
18
+ export { ComingSoonNotice } from './components/ComingSoonNotice.js';
19
+ export type { ComingSoonNoticeProps } from './components/ComingSoonNotice.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,11 @@
1
+ export { Select, resolveSelectTriggerLabel } from './components/Select/Select.js';
2
+ export { useSelectDropdown, usePanelPosition } from './components/Select/Select.hooks.js';
3
+ export { InfoTip } from './components/InfoTip.js';
4
+ export { useInfoTip } from './components/InfoTip.hooks.js';
5
+ export { SeeMore, resolveSeeMoreView } from './components/SeeMore/SeeMore.js';
6
+ export { useSeeMoreClamp } from './components/SeeMore/SeeMore.hooks.js';
7
+ export { ImagePreviewModal } from './components/ImagePreviewModal.js';
8
+ export { useImagePreviewModal } from './components/ImagePreviewModal.hooks.js';
9
+ export { ComingSoonPanel } from './components/ComingSoonPanel.js';
10
+ export { ComingSoonNotice } from './components/ComingSoonNotice.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,2 @@
1
+ /* Existing ui subpath continues to load the merged admin styles. */
2
+ @import "../../../styles/admin.css";
@@ -11,6 +11,6 @@ export interface ThemeOption {
11
11
  export declare const THEME_OPTIONS: ThemeOption[];
12
12
  /** Neutral default accent — hosts are expected to override via their own
13
13
  * config/branding; this only guarantees the CSS vars are always set. */
14
- export declare const DEFAULT_ACCENT_COLOR = "#2563eb";
15
- export declare const ACCENT_SWATCHES: readonly ["#2563eb", "#c96442", "#7c3aed", "#059669", "#dc2626", "#d97706", "#0891b2", "#db2777"];
14
+ export declare const DEFAULT_ACCENT_COLOR: string;
15
+ export declare const ACCENT_SWATCHES: readonly [string, "#c96442", "#7c3aed", "#059669", "#dc2626", "#d97706", "#0891b2", "#db2777"];
16
16
  //# sourceMappingURL=constants.d.ts.map
@@ -1,3 +1,4 @@
1
+ import { defaultAdminTheme } from '../../theme/default.js';
1
2
  /** Plain-English defaults for the three segmented-control options — a host
2
3
  * wanting localized copy overrides via `AppearanceTabProps.themeLabels` (the
3
4
  * component wraps each through `useT()` regardless, so this is only the
@@ -9,7 +10,7 @@ export const THEME_OPTIONS = [
9
10
  ];
10
11
  /** Neutral default accent — hosts are expected to override via their own
11
12
  * config/branding; this only guarantees the CSS vars are always set. */
12
- export const DEFAULT_ACCENT_COLOR = '#2563eb';
13
+ export const DEFAULT_ACCENT_COLOR = defaultAdminTheme.light.primary;
13
14
  export const ACCENT_SWATCHES = [
14
15
  DEFAULT_ACCENT_COLOR,
15
16
  '#c96442',
@@ -13,8 +13,8 @@ import { THEME_OPTIONS } from '../../constants.js';
13
13
  */
14
14
  export function AppearanceTab({ theme, onThemeChange, accentColor, onAccentColorChange, accentSwatches = ACCENT_SWATCHES, livePreview = true, ariaLabel, accentLabel, defaultAccentAriaLabel, customAccentAriaLabel, agentHandle, }) {
15
15
  const t = useT();
16
- const resolvedAccent = resolveAccentColor(accentColor);
17
- const swatchHandles = agentHandle ? buildAgentListHandles(agentSubHandle(agentHandle, 'swatch'), accentSwatches) : undefined;
16
+ const resolvedAccent = resolveAccentColor({ value: accentColor });
17
+ const swatchHandles = agentHandle ? buildAgentListHandles({ prefix: agentSubHandle({ base: agentHandle, action: 'swatch' }), ids: accentSwatches }) : undefined;
18
18
  const resolvedAriaLabel = ariaLabel ?? t('Appearance');
19
19
  const resolvedAccentLabel = accentLabel ?? t('Accent color');
20
20
  const resolvedDefaultAccentAriaLabel = defaultAccentAriaLabel ?? t('Default accent color');
@@ -25,10 +25,10 @@ export function AppearanceTab({ theme, onThemeChange, accentColor, onAccentColor
25
25
  return;
26
26
  applyAppearanceToDocument({ ...(appliedTheme ? { theme: appliedTheme } : {}), accentColor: resolvedAccent });
27
27
  }, [livePreview, appliedTheme, resolvedAccent]);
28
- return (_jsxs("section", { className: "jini-settings-section jini-settings-appearance", children: [_jsx("div", { className: "jini-seg-control", role: "group", "aria-label": resolvedAriaLabel, style: { '--seg-cols': THEME_OPTIONS.length }, children: THEME_OPTIONS.map((option) => (_jsxs("button", { type: "button", className: 'jini-seg-btn' + (theme === option.value ? ' active' : ''), "aria-pressed": theme === option.value, onClick: () => onThemeChange(option.value), ...agentHandleProps(agentHandle, { action: `theme-${option.value}`, role: 'button', label: t(option.label) }), children: [option.icon ? _jsx(Icon, { name: option.icon, size: 14, "aria-hidden": "true" }) : null, _jsx("span", { className: "jini-seg-title", children: t(option.label) })] }, option.value))) }), _jsxs("div", { className: "jini-field", children: [_jsx("span", { className: "jini-field-label", children: resolvedAccentLabel }), _jsxs("div", { className: "jini-accent-swatches", role: "radiogroup", "aria-label": resolvedAccentLabel, children: [accentSwatches.map((color, index) => {
28
+ return (_jsxs("section", { className: "jini-settings-section jini-settings-appearance", children: [_jsx("div", { className: "jini-seg-control", role: "group", "aria-label": resolvedAriaLabel, style: { '--seg-cols': THEME_OPTIONS.length }, children: THEME_OPTIONS.map((option) => (_jsxs("button", { type: "button", className: 'jini-seg-btn' + (theme === option.value ? ' active' : ''), "aria-pressed": theme === option.value, onClick: () => onThemeChange(option.value), ...agentHandleProps({}, { base: agentHandle, ...({ action: `theme-${option.value}`, role: 'button', label: t(option.label) }) }), children: [option.icon ? _jsx(Icon, { name: option.icon, size: 14, "aria-hidden": "true" }) : null, _jsx("span", { className: "jini-seg-title", children: t(option.label) })] }, option.value))) }), _jsxs("div", { className: "jini-field", children: [_jsx("span", { className: "jini-field-label", children: resolvedAccentLabel }), _jsxs("div", { className: "jini-accent-swatches", role: "radiogroup", "aria-label": resolvedAccentLabel, children: [accentSwatches.map((color, index) => {
29
29
  const active = resolvedAccent === color;
30
30
  const swatchLabel = color === DEFAULT_ACCENT_COLOR ? resolvedDefaultAccentAriaLabel : color;
31
- return (_jsx("button", { type: "button", className: `jini-accent-swatch${active ? ' active' : ''}`, style: { background: color }, "aria-label": swatchLabel, "aria-checked": active, role: "radio", onClick: () => onAccentColorChange(normalizeAccentColor(color) ?? color), ...agentHandleProps(swatchHandles?.[index], { role: 'button', label: swatchLabel }) }, color));
32
- }), _jsx("input", { type: "color", "aria-label": resolvedCustomAccentAriaLabel, className: "jini-accent-swatch-picker", value: resolvedAccent, onChange: (event) => onAccentColorChange(event.target.value), ...agentHandleProps(agentHandle, { action: 'custom-accent', role: 'field', label: resolvedCustomAccentAriaLabel }) })] })] })] }));
31
+ return (_jsx("button", { type: "button", className: `jini-accent-swatch${active ? ' active' : ''}`, style: { background: color }, "aria-label": swatchLabel, "aria-checked": active, role: "radio", onClick: () => onAccentColorChange(normalizeAccentColor({ value: color }) ?? color), ...agentHandleProps({}, { base: swatchHandles?.[index], ...({ role: 'button', label: swatchLabel }) }) }, color));
32
+ }), _jsx("input", { type: "color", "aria-label": resolvedCustomAccentAriaLabel, className: "jini-accent-swatch-picker", value: resolvedAccent, onChange: (event) => onAccentColorChange(event.target.value), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'custom-accent', role: 'field', label: resolvedCustomAccentAriaLabel }) }) })] })] })] }));
33
33
  }
34
34
  //# sourceMappingURL=AppearanceTab.js.map
@@ -13,10 +13,14 @@ export type AccentCssVars = Record<(typeof ACCENT_VARS)[number], string>;
13
13
  * string or does not match `#rrggbb`.
14
14
  * @complexity O(1).
15
15
  */
16
- export declare function normalizeAccentColor(value: unknown): string | null;
17
- /** `normalizeAccentColor(value) ?? DEFAULT_ACCENT_COLOR` — always returns a
16
+ export declare function normalizeAccentColor({ value }: {
17
+ value: unknown;
18
+ }): string | null;
19
+ /** `normalizeAccentColor({ value }) ?? DEFAULT_ACCENT_COLOR` — always returns a
18
20
  * usable color. */
19
- export declare function resolveAccentColor(value: unknown): string;
21
+ export declare function resolveAccentColor({ value }: {
22
+ value: unknown;
23
+ }): string;
20
24
  /**
21
25
  * Pure computation of the five `--accent*` CSS custom property values for a
22
26
  * given (already-resolved) accent color, via `color-mix()` formulas. The DOM
@@ -26,6 +30,8 @@ export declare function resolveAccentColor(value: unknown): string;
26
30
  *
27
31
  * @complexity O(1) — five template-string formulas, no DOM access.
28
32
  */
29
- export declare function accentVars(accentColor: string): AccentCssVars;
33
+ export declare function accentVars({ accentColor }: {
34
+ accentColor: string;
35
+ }): AccentCssVars;
30
36
  export {};
31
37
  //# sourceMappingURL=rules.d.ts.map