@jini-ai/ui 0.3.14 → 0.4.1

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 +143 -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 +11 -0
  176. package/dist/features/panel-kit/hooks/use-focus-trap.hooks.js +76 -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
@@ -28,10 +28,10 @@ import { testStatusLabel } from '../../rules.js';
28
28
  export function NotificationsTab({ preferences, onChange, testNotificationTitle, testNotificationBody, labels, agentHandle, }) {
29
29
  const t = useT();
30
30
  const successSoundHandles = agentHandle
31
- ? buildAgentListHandles(agentSubHandle(agentHandle, 'success-sound'), SUCCESS_SOUNDS.map((s) => s.id))
31
+ ? buildAgentListHandles({ prefix: agentSubHandle({ base: agentHandle, action: 'success-sound' }), ids: SUCCESS_SOUNDS.map((s) => s.id) })
32
32
  : undefined;
33
33
  const failureSoundHandles = agentHandle
34
- ? buildAgentListHandles(agentSubHandle(agentHandle, 'failure-sound'), FAILURE_SOUNDS.map((s) => s.id))
34
+ ? buildAgentListHandles({ prefix: agentSubHandle({ base: agentHandle, action: 'failure-sound' }), ids: FAILURE_SOUNDS.map((s) => s.id) })
35
35
  : undefined;
36
36
  const [permission, setPermission] = useState(() => notificationPermission());
37
37
  const [testStatus, setTestStatus] = useState(null);
@@ -76,16 +76,16 @@ export function NotificationsTab({ preferences, onChange, testNotificationTitle,
76
76
  // outcome here rather than getting their own dead states.
77
77
  setTestStatus(result === 'shown' ? 'sent' : 'failed');
78
78
  };
79
- return (_jsxs("section", { className: "jini-settings-section jini-settings-notifications", children: [_jsxs("div", { className: "jini-settings-subsection", children: [_jsxs("div", { className: "jini-settings-notify-card", children: [_jsxs("div", { className: "jini-settings-notify-card-header", children: [_jsx("h4", { children: completionSoundTitle }), _jsx("div", { className: "jini-seg-control", role: "group", "aria-label": completionSoundTitle, style: { '--seg-cols': 1 }, children: _jsx("button", { type: "button", className: 'jini-seg-btn' + (preferences.soundEnabled ? ' active' : ''), "aria-pressed": preferences.soundEnabled, "aria-label": completionSoundTitle, onClick: toggleSound, ...agentHandleProps(agentHandle, { action: 'sound-toggle', role: 'button', label: completionSoundTitle }), children: _jsx("span", { className: "jini-seg-title", children: preferences.soundEnabled ? activeLabel : offLabel }) }) })] }), _jsx("p", { className: "jini-hint", children: completionSoundHint })] }), preferences.soundEnabled ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "jini-settings-field", children: [_jsx("label", { children: successSoundLabel }), _jsx("div", { className: "jini-seg-control", role: "group", "aria-label": successSoundLabel, style: { '--seg-cols': SUCCESS_SOUNDS.length }, children: SUCCESS_SOUNDS.map((sound, index) => (_jsx("button", { type: "button", className: 'jini-seg-btn' + (preferences.successSoundId === sound.id ? ' active' : ''), "aria-pressed": preferences.successSoundId === sound.id, onClick: () => {
79
+ return (_jsxs("section", { className: "jini-settings-section jini-settings-notifications", children: [_jsxs("div", { className: "jini-settings-subsection", children: [_jsxs("div", { className: "jini-settings-notify-card", children: [_jsxs("div", { className: "jini-settings-notify-card-header", children: [_jsx("h4", { children: completionSoundTitle }), _jsx("div", { className: "jini-seg-control", role: "group", "aria-label": completionSoundTitle, style: { '--seg-cols': 1 }, children: _jsx("button", { type: "button", className: 'jini-seg-btn' + (preferences.soundEnabled ? ' active' : ''), "aria-pressed": preferences.soundEnabled, "aria-label": completionSoundTitle, onClick: toggleSound, ...agentHandleProps({}, { base: agentHandle, ...({ action: 'sound-toggle', role: 'button', label: completionSoundTitle }) }), children: _jsx("span", { className: "jini-seg-title", children: preferences.soundEnabled ? activeLabel : offLabel }) }) })] }), _jsx("p", { className: "jini-hint", children: completionSoundHint })] }), preferences.soundEnabled ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "jini-settings-field", children: [_jsx("label", { children: successSoundLabel }), _jsx("div", { className: "jini-seg-control", role: "group", "aria-label": successSoundLabel, style: { '--seg-cols': SUCCESS_SOUNDS.length }, children: SUCCESS_SOUNDS.map((sound, index) => (_jsx("button", { type: "button", className: 'jini-seg-btn' + (preferences.successSoundId === sound.id ? ' active' : ''), "aria-pressed": preferences.successSoundId === sound.id, onClick: () => {
80
80
  onChange({ successSoundId: sound.id });
81
81
  playSound(sound.id);
82
- }, ...agentHandleProps(successSoundHandles?.[index], { role: 'button', label: t(sound.labelKey) }), children: _jsx("span", { className: "jini-seg-title", children: t(sound.labelKey) }) }, sound.id))) })] }), _jsxs("div", { className: "jini-settings-field", children: [_jsx("label", { children: failureSoundLabel }), _jsx("div", { className: "jini-seg-control", role: "group", "aria-label": failureSoundLabel, style: { '--seg-cols': FAILURE_SOUNDS.length }, children: FAILURE_SOUNDS.map((sound, index) => (_jsx("button", { type: "button", className: 'jini-seg-btn' + (preferences.failureSoundId === sound.id ? ' active' : ''), "aria-pressed": preferences.failureSoundId === sound.id, onClick: () => {
82
+ }, ...agentHandleProps({}, { base: successSoundHandles?.[index], ...({ role: 'button', label: t(sound.labelKey) }) }), children: _jsx("span", { className: "jini-seg-title", children: t(sound.labelKey) }) }, sound.id))) })] }), _jsxs("div", { className: "jini-settings-field", children: [_jsx("label", { children: failureSoundLabel }), _jsx("div", { className: "jini-seg-control", role: "group", "aria-label": failureSoundLabel, style: { '--seg-cols': FAILURE_SOUNDS.length }, children: FAILURE_SOUNDS.map((sound, index) => (_jsx("button", { type: "button", className: 'jini-seg-btn' + (preferences.failureSoundId === sound.id ? ' active' : ''), "aria-pressed": preferences.failureSoundId === sound.id, onClick: () => {
83
83
  onChange({ failureSoundId: sound.id });
84
84
  playSound(sound.id);
85
- }, ...agentHandleProps(failureSoundHandles?.[index], { role: 'button', label: t(sound.labelKey) }), children: _jsx("span", { className: "jini-seg-title", children: t(sound.labelKey) }) }, sound.id))) })] })] })) : null] }), _jsxs("div", { className: "jini-settings-subsection", children: [_jsxs("div", { className: "jini-settings-notify-card", children: [_jsxs("div", { className: "jini-settings-notify-card-header", children: [_jsx("h4", { children: desktopTitle }), _jsx("div", { className: "jini-seg-control", role: "group", "aria-label": desktopTitle, style: { '--seg-cols': 1 }, children: _jsx("button", { type: "button", className: 'jini-seg-btn' + (preferences.desktopEnabled ? ' active' : ''), "aria-pressed": preferences.desktopEnabled, "aria-label": desktopTitle, disabled: permission === 'unsupported', onClick: () => {
85
+ }, ...agentHandleProps({}, { base: failureSoundHandles?.[index], ...({ role: 'button', label: t(sound.labelKey) }) }), children: _jsx("span", { className: "jini-seg-title", children: t(sound.labelKey) }) }, sound.id))) })] })] })) : null] }), _jsxs("div", { className: "jini-settings-subsection", children: [_jsxs("div", { className: "jini-settings-notify-card", children: [_jsxs("div", { className: "jini-settings-notify-card-header", children: [_jsx("h4", { children: desktopTitle }), _jsx("div", { className: "jini-seg-control", role: "group", "aria-label": desktopTitle, style: { '--seg-cols': 1 }, children: _jsx("button", { type: "button", className: 'jini-seg-btn' + (preferences.desktopEnabled ? ' active' : ''), "aria-pressed": preferences.desktopEnabled, "aria-label": desktopTitle, disabled: permission === 'unsupported', onClick: () => {
86
86
  void toggleDesktop();
87
- }, ...agentHandleProps(agentHandle, { action: 'desktop-toggle', role: 'button', label: desktopTitle }), children: _jsx("span", { className: "jini-seg-title", children: preferences.desktopEnabled ? activeLabel : offLabel }) }) })] }), _jsx("p", { className: "jini-hint", children: desktopHint })] }), permission === 'unsupported' ? _jsx("p", { className: "jini-hint", children: desktopUnsupported }) : null, permission === 'denied' ? _jsx("p", { className: "jini-hint", children: desktopBlocked }) : null, preferences.desktopEnabled && permission === 'granted' ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "jini-button jini-button-ghost", onClick: () => {
87
+ }, ...agentHandleProps({}, { base: agentHandle, ...({ action: 'desktop-toggle', role: 'button', label: desktopTitle }) }), children: _jsx("span", { className: "jini-seg-title", children: preferences.desktopEnabled ? activeLabel : offLabel }) }) })] }), _jsx("p", { className: "jini-hint", children: desktopHint })] }), permission === 'unsupported' ? _jsx("p", { className: "jini-hint", children: desktopUnsupported }) : null, permission === 'denied' ? _jsx("p", { className: "jini-hint", children: desktopBlocked }) : null, preferences.desktopEnabled && permission === 'granted' ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "jini-button jini-button-ghost", onClick: () => {
88
88
  void sendTestNotification();
89
- }, ...agentHandleProps(agentHandle, { action: 'send-test', role: 'button', label: sendTestLabel }), children: sendTestLabel }), testStatus ? (_jsx("p", { className: "jini-hint", role: "status", children: testStatusLabel(testStatus, { testSentLabel, testFailedLabel }) })) : null] })) : null] })] }));
89
+ }, ...agentHandleProps({}, { base: agentHandle, ...({ action: 'send-test', role: 'button', label: sendTestLabel }) }), children: sendTestLabel }), testStatus ? (_jsx("p", { className: "jini-hint", role: "status", children: testStatusLabel(testStatus, { testSentLabel, testFailedLabel }) })) : null] })) : null] })] }));
90
90
  }
91
91
  //# sourceMappingURL=NotificationsTab.js.map
@@ -2,7 +2,7 @@
2
2
  * Origin: `NotificationsSection` in `SettingsDialog.tsx` (completion-sound
3
3
  * toggle/picker + browser Notification-permission flow), GENERIC per
4
4
  * `ADS-memory/reports/jini-port/recon/r6-god-component-internals.md` §1.3 — browser-API
5
- * only, zero product-domain coupling. See `packages/ui/source-map.md` for
5
+ * only, zero product-domain coupling. See `packages/ui/archived provenance ledger` for
6
6
  * the full provenance note.
7
7
  */
8
8
  import type { SoundId } from './notifications-catalog.js';
@@ -59,7 +59,7 @@ export function installBootTimingObserver(options = {}) {
59
59
  // only ever runs after that function's own `typeof window === 'undefined'`
60
60
  // guard has already passed, so a second check here was dead code for every
61
61
  // real call — removed rather than tested around (see
62
- // packages/ui/source-map.md's 2026-07-22 dated entry).
62
+ // packages/ui/archived provenance ledger's 2026-07-22 dated entry).
63
63
  function schedule(fn) {
64
64
  const rIC = window.requestIdleCallback;
65
65
  if (typeof rIC === 'function') {
@@ -90,7 +90,7 @@ function emit(reporter) {
90
90
  // resolvable in global scope by the time this line runs; a `typeof
91
91
  // document !== 'undefined'` re-check here was dead code for every real
92
92
  // call, removed rather than tested around (see
93
- // packages/ui/source-map.md's 2026-07-22 dated entry).
93
+ // packages/ui/archived provenance ledger's 2026-07-22 dated entry).
94
94
  visibility_state: document.visibilityState,
95
95
  });
96
96
  }
@@ -90,7 +90,7 @@ function emitStuck(runId) {
90
90
  // time this callback runs, its entry is guaranteed to both exist and
91
91
  // have `emitted === false`. Left in place (not stripped) as a guard
92
92
  // against a future refactor silently breaking that invariant — see
93
- // packages/ui/source-map.md's 2026-07-22 dated entry for the full proof,
93
+ // packages/ui/archived provenance ledger's 2026-07-22 dated entry for the full proof,
94
94
  // matching this task's own standard for documenting provable
95
95
  // unreachability instead of forcing a test.
96
96
  if (!entry || entry.emitted)
@@ -69,7 +69,7 @@ export function installWhiteScreenDetector(options = {}) {
69
69
  // its callback afterward. So by the time either callback runs at all,
70
70
  // `cancelled` is guaranteed to still be its initial `false`. Left in
71
71
  // place (not stripped) as a guard against a future refactor silently
72
- // breaking that invariant — see packages/ui/source-map.md's 2026-07-22
72
+ // breaking that invariant — see packages/ui/archived provenance ledger's 2026-07-22
73
73
  // dated entry for the full proof, same pattern as this package's
74
74
  // `stuck-run.ts` `emitStuck` precedent.
75
75
  const timer = window.setTimeout(() => {
@@ -105,7 +105,7 @@ function checkAppMounted(options) {
105
105
  // `installWhiteScreenDetector`, itself only ever reachable after that
106
106
  // function's own `typeof document === 'undefined'` guard has already
107
107
  // passed — a second check here was dead code for every real call,
108
- // removed rather than tested around (see packages/ui/source-map.md's
108
+ // removed rather than tested around (see packages/ui/archived provenance ledger's
109
109
  // 2026-07-22 dated entry).
110
110
  // Primary signal: the host's root-mount effect ran.
111
111
  if (document.documentElement.getAttribute(options.mountedAttribute) === options.mountedAttributeValue) {
@@ -126,7 +126,7 @@ function checkAppMounted(options) {
126
126
  // only for `Document`/`DocumentType` nodes — for any `Element` it is
127
127
  // always a string (possibly `''`). The `?? ''` fallback this used to
128
128
  // have was dead code for every real entry here, removed rather than
129
- // tested around (see packages/ui/source-map.md's 2026-07-22 dated
129
+ // tested around (see packages/ui/archived provenance ledger's 2026-07-22 dated
130
130
  // entry).
131
131
  .map((el) => el.innerText ?? el.textContent)
132
132
  .join('')
@@ -154,7 +154,7 @@ function monitorMount(isAppMounted, onMounted) {
154
154
  // about): two synchronous body mutations followed by two microtask
155
155
  // flushes produced exactly one callback invocation with `stopped` still
156
156
  // `false` at its start, and a further post-disconnect mutation produced
157
- // zero more. See packages/ui/source-map.md's 2026-07-22 dated entry for
157
+ // zero more. See packages/ui/archived provenance ledger's 2026-07-22 dated entry for
158
158
  // the full record.
159
159
  const observer = new MutationObserver(() => {
160
160
  if (stopped)
@@ -0,0 +1,35 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type FetchQueryEnvironmentPort } from './cache.js';
3
+ import type { CachedLoader, CachedLoaderOptions, FetchMutationOptions, FetchQueryOptions, MutationResult, QueryKey, QueryResult } from './types.js';
4
+ /** Isolated cache scope; no external provider or query-library singleton is needed. */
5
+ export declare function FetchQueryProvider({ children, environment }: {
6
+ children: ReactNode;
7
+ environment?: FetchQueryEnvironmentPort;
8
+ }): import("react").JSX.Element;
9
+ /**
10
+ * Without prior successful data, a disabled read hides cached errors so gesture-gated
11
+ * content cannot display a failure the user has not asked to retry. With prior data, retain
12
+ * a later background failure so callers can distinguish usable data from guaranteed freshness.
13
+ */
14
+ /** Disabled reads keep earlier data but suppress errors before any successful read. */
15
+ export declare function resolveFetchQueryStatus({ disabled, hasData, status }: {
16
+ disabled: boolean;
17
+ hasData: boolean;
18
+ status: 'pending' | 'error' | 'success';
19
+ }): QueryResult<unknown>['status'];
20
+ export declare function resolveFetchQueryError({ error, disabled, hasData }: {
21
+ error: unknown;
22
+ disabled: boolean;
23
+ hasData: boolean;
24
+ }): Error | null;
25
+ /** Reactive keyed read. Background refresh keeps cached data visible. */
26
+ export declare function useFetchQuery<T>(required: Pick<FetchQueryOptions<T>, "key" | "fetch">, optional?: Omit<FetchQueryOptions<T>, "key" | "fetch">): QueryResult<T>;
27
+ /** A write returns its rejection to awaiting callers and also handles discarded promises. */
28
+ export declare function useFetchMutation<TInput, TOutput>(required: Pick<FetchMutationOptions<TInput, TOutput>, "run">, optional?: Omit<FetchMutationOptions<TInput, TOutput>, "run">): MutationResult<TInput, TOutput>;
29
+ /** Promise loader sharing the provider cache; replace wins over an older in-flight read. */
30
+ export declare function useCachedLoader<T>({ key, fetch }: Pick<CachedLoaderOptions<T>, "key" | "fetch">, { staleTime }?: Omit<CachedLoaderOptions<T>, "key" | "fetch">): CachedLoader<T>;
31
+ /** Prefix invalidation refreshes every currently enabled read under that key. */
32
+ export declare function useInvalidate(): (required: {
33
+ key: QueryKey;
34
+ }) => void;
35
+ //# sourceMappingURL=adapter.react.d.ts.map
@@ -0,0 +1,122 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
3
+ import { DEFAULT_STALE_TIME, FetchQueryCache, toQueryError } from './cache.js';
4
+ import { browserFetchQueryEnvironment } from './environment.browser.js';
5
+ const CacheContext = createContext(null);
6
+ /** Isolated cache scope; no external provider or query-library singleton is needed. */
7
+ export function FetchQueryProvider({ children, environment = browserFetchQueryEnvironment }) {
8
+ // A module singleton would leak cache values between independent providers/tests,
9
+ // producing cases that pass alone but fail together. Scope ownership to this provider.
10
+ const cache = useMemo(() => new FetchQueryCache({}, { environment }), [environment]);
11
+ useEffect(() => {
12
+ cache.activate();
13
+ return () => cache.dispose();
14
+ }, [cache]);
15
+ return _jsx(CacheContext.Provider, { value: cache, children: children });
16
+ }
17
+ function useCache() {
18
+ const cache = useContext(CacheContext);
19
+ if (!cache)
20
+ throw new Error('Fetch-query hooks require FetchQueryProvider');
21
+ return cache;
22
+ }
23
+ /**
24
+ * Without prior successful data, a disabled read hides cached errors so gesture-gated
25
+ * content cannot display a failure the user has not asked to retry. With prior data, retain
26
+ * a later background failure so callers can distinguish usable data from guaranteed freshness.
27
+ */
28
+ // Keep status/error folds outside subscription wiring so their branches are directly
29
+ // testable without mounting observers; flat decisions avoid nested conditional review costs.
30
+ /** Disabled reads keep earlier data but suppress errors before any successful read. */
31
+ export function resolveFetchQueryStatus({ disabled, hasData, status }) {
32
+ if (disabled)
33
+ return hasData ? 'success' : 'loading';
34
+ return status === 'pending' ? 'loading' : status;
35
+ }
36
+ export function resolveFetchQueryError({ error, disabled, hasData }) {
37
+ if (!error || (disabled && !hasData))
38
+ return null;
39
+ return toQueryError(error);
40
+ }
41
+ /** Reactive keyed read. Background refresh keeps cached data visible. */
42
+ export function useFetchQuery(required, optional = {}) {
43
+ const cache = useCache();
44
+ const options = { ...optional, ...required };
45
+ const { key, enabled = true, staleTime = DEFAULT_STALE_TIME, refetchOnWindowFocus = false } = options;
46
+ const latest = useRef(options);
47
+ latest.current = options;
48
+ const entry = cache.entry({ key: key }, { staleTime: staleTime });
49
+ const subscribe = useCallback((listener) => cache.subscribe({ entry: entry, listener: listener }), [cache, entry]);
50
+ const snapshot = useCallback(() => entry.state, [entry]);
51
+ const state = useSyncExternalStore(subscribe, snapshot, snapshot);
52
+ const fetch = useCallback(() => latest.current.fetch(), []);
53
+ useEffect(() => {
54
+ if (!enabled)
55
+ return;
56
+ const release = cache.observe({ entry: entry, observer: { fetch, staleTime, focus: refetchOnWindowFocus } });
57
+ void cache.load({ entry: entry, fetch: fetch, staleTime: staleTime });
58
+ return release;
59
+ }, [cache, entry, enabled, staleTime, refetchOnWindowFocus, fetch]);
60
+ const refetch = useCallback(() => { void cache.load({ entry: entry, fetch: fetch, staleTime: staleTime }, { force: true }); }, [cache, entry, fetch, staleTime]);
61
+ const hasData = state.data !== undefined;
62
+ return {
63
+ data: state.data,
64
+ status: resolveFetchQueryStatus({ disabled: !enabled, hasData: hasData, status: state.status }),
65
+ error: resolveFetchQueryError({ error: state.error, disabled: !enabled, hasData: hasData }),
66
+ isFetching: state.isFetching, refetch,
67
+ };
68
+ }
69
+ /** A write returns its rejection to awaiting callers and also handles discarded promises. */
70
+ export function useFetchMutation(required, optional = {}) {
71
+ const cache = useCache();
72
+ const options = { ...optional, ...required };
73
+ const latest = useRef(options);
74
+ latest.current = options;
75
+ const generation = useRef(0);
76
+ const mounted = useRef(true);
77
+ useEffect(() => { mounted.current = true; return () => { mounted.current = false; }; }, []);
78
+ const [state, setState] = useState({ status: 'idle', error: null });
79
+ const mutate = useCallback(({ input }) => {
80
+ const current = ++generation.current;
81
+ const { run, invalidates } = latest.current;
82
+ setState({ status: 'pending', error: null });
83
+ // Surface a rejected write immediately instead of silently retrying authorization or
84
+ // validation failures that another identical attempt cannot fix.
85
+ const promise = cache.runOnline({ run: () => run({ input }) }).then(value => {
86
+ // Do not await dependent reads: the mutation promise means the write succeeded,
87
+ // not that every list finished reloading. Refetches proceed on their own schedule.
88
+ for (const key of invalidates ?? [])
89
+ cache.invalidate({ prefix: key });
90
+ if (mounted.current && current === generation.current)
91
+ setState({ status: 'success', error: null });
92
+ return value;
93
+ }, error => {
94
+ if (mounted.current && current === generation.current)
95
+ setState({ status: 'error', error: toQueryError(error) });
96
+ throw error;
97
+ });
98
+ // Handle this same promise for callers that discard it, while still returning it so
99
+ // await/catch observes the original rejection; discarding the derived promise is intentional.
100
+ void promise.catch(() => { });
101
+ return promise;
102
+ }, [cache]);
103
+ const reset = useCallback(() => { generation.current += 1; setState({ status: 'idle', error: null }); }, []);
104
+ return { ...state, mutate, reset };
105
+ }
106
+ /** Promise loader sharing the provider cache; replace wins over an older in-flight read. */
107
+ export function useCachedLoader({ key, fetch }, { staleTime = DEFAULT_STALE_TIME } = {}) {
108
+ const cache = useCache();
109
+ return useMemo(() => ({
110
+ peek: () => cache.entry({ key: key }, { staleTime: staleTime }).state.data,
111
+ load: () => cache.load({ entry: cache.entry({ key: key }, { staleTime: staleTime }), fetch: fetch, staleTime: staleTime }),
112
+ replace: ({ value }) => cache.replace({ entry: cache.entry({ key: key }, { staleTime: staleTime }), data: value }),
113
+ }), [cache, key, fetch, staleTime]);
114
+ }
115
+ // Imperative invalidation also covers externally delivered events, such as an SSE change
116
+ // feed, whose producer cannot call a React read hook or a component-local reload.
117
+ /** Prefix invalidation refreshes every currently enabled read under that key. */
118
+ export function useInvalidate() {
119
+ const cache = useCache();
120
+ return useCallback(({ key }) => cache.invalidate({ prefix: key }), [cache]);
121
+ }
122
+ //# sourceMappingURL=adapter.react.js.map
@@ -0,0 +1,123 @@
1
+ import type { Clock } from '@jini-ai/core/primitives';
2
+ import type { QueryKey } from './types.js';
3
+ /**
4
+ * Ten seconds covers reading, closing and reopening a record or bouncing between screens
5
+ * without paying for another identical request. Five seconds was too short for that read
6
+ * cycle; thirty seconds exposed more other-operator staleness than the conservative initial
7
+ * shared default should allow. There is no default polling/focus refresh, so this bounds
8
+ * the extra exposure on a quick revisit. Write invalidation bypasses freshness; reads that
9
+ * must be fresh on every mount can choose staleTime: 0 without lowering every query default.
10
+ */
11
+ export declare const DEFAULT_STALE_TIME = 10000;
12
+ export interface QueryCacheSchedulerPort {
13
+ schedule(required: {
14
+ callback: () => void;
15
+ delayMs: number;
16
+ }): unknown;
17
+ cancel(required: {
18
+ handle: unknown;
19
+ }): void;
20
+ }
21
+ /** Host connectivity and focus signals; the cache itself has no DOM dependency. */
22
+ export interface FetchQueryEnvironmentPort {
23
+ isOnline(): boolean;
24
+ subscribeOnline(required: {
25
+ listener: (online: boolean) => void;
26
+ }): () => void;
27
+ subscribeFocus(required: {
28
+ listener: () => void;
29
+ }): () => void;
30
+ }
31
+ export interface FetchQueryCacheOptions {
32
+ clock?: Clock;
33
+ scheduler?: QueryCacheSchedulerPort;
34
+ environment?: FetchQueryEnvironmentPort;
35
+ }
36
+ export interface QueryState {
37
+ data: unknown;
38
+ error: Error | null;
39
+ status: 'pending' | 'success' | 'error';
40
+ isFetching: boolean;
41
+ }
42
+ export interface QueryObserver {
43
+ fetch: () => Promise<unknown>;
44
+ staleTime: number;
45
+ focus: boolean;
46
+ }
47
+ export interface CacheEntry {
48
+ key: QueryKey;
49
+ state: QueryState;
50
+ updatedAt: number;
51
+ invalidated: boolean;
52
+ replacement: number;
53
+ pending: Promise<unknown> | undefined;
54
+ refreshAfterPending: boolean;
55
+ listeners: Set<() => void>;
56
+ observers: Set<QueryObserver>;
57
+ retention: number;
58
+ eviction: unknown;
59
+ }
60
+ export declare function toQueryError(value: unknown): Error;
61
+ /** One provider-owned cache. Requests are shared by structural primitive keys.
62
+ * Failed reads retain earlier data; replacement writes supersede older requests.
63
+ * Idle entries live for at least five minutes or their declared freshness period. */
64
+ export declare class FetchQueryCache {
65
+ private readonly entries;
66
+ private disposed;
67
+ private readonly clock;
68
+ private readonly scheduler;
69
+ private readonly environment;
70
+ private online;
71
+ private readonly onlineWaiters;
72
+ private releaseEnvironment;
73
+ constructor(_required?: Record<string, never>, { clock, scheduler, environment }?: FetchQueryCacheOptions);
74
+ entry({ key }: {
75
+ key: QueryKey;
76
+ }, { staleTime }?: {
77
+ staleTime?: number;
78
+ }): CacheEntry;
79
+ fresh({ entry, staleTime }: {
80
+ entry: CacheEntry;
81
+ staleTime: number;
82
+ }): boolean;
83
+ subscribe({ entry, listener }: {
84
+ entry: CacheEntry;
85
+ listener: () => void;
86
+ }): () => void;
87
+ observe({ entry, observer }: {
88
+ entry: CacheEntry;
89
+ observer: QueryObserver;
90
+ }): () => void;
91
+ /** Cache hits respect freshness; explicit refreshes restart background reads.
92
+ * Initial reads still deduplicate because no earlier successful data exists to refresh. */
93
+ load<T>({ entry, fetch, staleTime }: {
94
+ entry: CacheEntry;
95
+ fetch: () => Promise<T>;
96
+ staleTime: number;
97
+ }, { force }?: {
98
+ force?: boolean;
99
+ }): Promise<T>;
100
+ replace({ entry, data }: {
101
+ entry: CacheEntry;
102
+ data: unknown;
103
+ }): void;
104
+ invalidate({ prefix }: {
105
+ prefix: QueryKey;
106
+ }): void;
107
+ onFocus(): void;
108
+ /** Execute a read/write once connectivity returns; failures are not retried.
109
+ * @param required.run Operation to invoke online.
110
+ * @returns The operation's original result or rejection. */
111
+ runOnline<T>({ run }: {
112
+ run: () => Promise<T>;
113
+ }): Promise<T>;
114
+ /** Stop timers on provider disposal; reactivate for React's effect replay. */
115
+ activate(): void;
116
+ dispose(): void;
117
+ private onOnline;
118
+ private refresh;
119
+ private publish;
120
+ private cancelEviction;
121
+ private scheduleEviction;
122
+ }
123
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Ten seconds covers reading, closing and reopening a record or bouncing between screens
3
+ * without paying for another identical request. Five seconds was too short for that read
4
+ * cycle; thirty seconds exposed more other-operator staleness than the conservative initial
5
+ * shared default should allow. There is no default polling/focus refresh, so this bounds
6
+ * the extra exposure on a quick revisit. Write invalidation bypasses freshness; reads that
7
+ * must be fresh on every mount can choose staleTime: 0 without lowering every query default.
8
+ */
9
+ export const DEFAULT_STALE_TIME = 10_000;
10
+ const IDLE_RETENTION = 5 * 60_000;
11
+ const browserScheduler = {
12
+ schedule: ({ callback, delayMs }) => setTimeout(callback, delayMs),
13
+ cancel: ({ handle }) => clearTimeout(handle),
14
+ };
15
+ // Normalize unknown promise rejections once so consumers receive Error without repeating
16
+ // the same narrowing boilerplate at every read and write call site.
17
+ export function toQueryError(value) {
18
+ return value instanceof Error ? value : new Error(typeof value === 'string' && value.trim() ? value : 'request failed');
19
+ }
20
+ /** One provider-owned cache. Requests are shared by structural primitive keys.
21
+ * Failed reads retain earlier data; replacement writes supersede older requests.
22
+ * Idle entries live for at least five minutes or their declared freshness period. */
23
+ export class FetchQueryCache {
24
+ entries = new Map();
25
+ disposed = false;
26
+ clock;
27
+ scheduler;
28
+ environment;
29
+ online;
30
+ onlineWaiters = new Set();
31
+ releaseEnvironment;
32
+ constructor(_required = {}, { clock = { nowMs: () => Date.now() }, scheduler = browserScheduler, environment } = {}) {
33
+ this.clock = clock;
34
+ this.scheduler = scheduler;
35
+ this.environment = environment;
36
+ this.online = environment?.isOnline() ?? true;
37
+ }
38
+ entry({ key }, { staleTime = DEFAULT_STALE_TIME } = {}) {
39
+ const hash = JSON.stringify(key);
40
+ let entry = this.entries.get(hash);
41
+ if (!entry) {
42
+ entry = {
43
+ key: [...key], state: { data: undefined, error: null, status: 'pending', isFetching: false },
44
+ updatedAt: 0, invalidated: false, replacement: 0, pending: undefined,
45
+ refreshAfterPending: false, listeners: new Set(), observers: new Set(),
46
+ retention: IDLE_RETENTION, eviction: undefined,
47
+ };
48
+ this.entries.set(hash, entry);
49
+ }
50
+ // An imperative load has no standing observer: idle eviction must not drop a value
51
+ // earlier than its declared freshness and unexpectedly force another network request.
52
+ entry.retention = Math.max(entry.retention, staleTime);
53
+ return entry;
54
+ }
55
+ fresh({ entry, staleTime }) {
56
+ return entry.state.data !== undefined && !entry.invalidated && this.clock.nowMs() - entry.updatedAt < staleTime;
57
+ }
58
+ subscribe({ entry, listener }) {
59
+ this.cancelEviction(entry);
60
+ entry.listeners.add(listener);
61
+ return () => { entry.listeners.delete(listener); this.scheduleEviction(entry); };
62
+ }
63
+ observe({ entry, observer }) {
64
+ entry.observers.add(observer);
65
+ return () => { entry.observers.delete(observer); this.scheduleEviction(entry); };
66
+ }
67
+ /** Cache hits respect freshness; explicit refreshes restart background reads.
68
+ * Initial reads still deduplicate because no earlier successful data exists to refresh. */
69
+ load({ entry, fetch, staleTime }, { force = false } = {}) {
70
+ this.cancelEviction(entry);
71
+ if (entry.pending && (!force || entry.state.data === undefined))
72
+ return entry.pending;
73
+ if (!force && this.fresh({ entry: entry, staleTime: staleTime })) {
74
+ this.scheduleEviction(entry);
75
+ return Promise.resolve(entry.state.data);
76
+ }
77
+ // Shared per key across loader instances: a replacement while this request is out
78
+ // must win over its older answer, not just protect the instance that issued the write.
79
+ const replacement = entry.replacement;
80
+ const run = () => {
81
+ // A queued offline refresh may have been superseded before reconnection.
82
+ if (entry.pending !== pending)
83
+ return (entry.pending ?? Promise.resolve(entry.state.data));
84
+ this.publish(entry, { ...entry.state, isFetching: true });
85
+ return fetch();
86
+ };
87
+ const pending = Promise.resolve().then(() => {
88
+ if (this.online)
89
+ return run();
90
+ this.publish(entry, { ...entry.state, isFetching: false });
91
+ return this.runOnline({ run });
92
+ }).then(value => {
93
+ const data = replacement === entry.replacement ? value : entry.state.data;
94
+ // Undefined is never successful query data, including an initial or background read.
95
+ if (data === undefined)
96
+ throw new Error(`${JSON.stringify(entry.key)} data is undefined`);
97
+ return data;
98
+ }).then(data => {
99
+ // Only the current request may publish or clear invalidation. An older transport
100
+ // need not support abort: its callers follow the replacement request instead.
101
+ if (entry.pending !== pending)
102
+ return (entry.pending ?? entry.state.data);
103
+ entry.updatedAt = this.clock.nowMs();
104
+ entry.invalidated = false;
105
+ this.publish(entry, { data, error: null, status: 'success', isFetching: false });
106
+ return data;
107
+ }, error => {
108
+ if (entry.pending !== pending)
109
+ return (entry.pending ?? entry.state.data);
110
+ // A replacement write is newer than this read's failure as well as its data.
111
+ // Keep the write's timestamp and freshness; only settle the obsolete fetch flag.
112
+ if (replacement !== entry.replacement) {
113
+ this.publish(entry, { ...entry.state, isFetching: false });
114
+ return entry.state.data;
115
+ }
116
+ entry.invalidated = true;
117
+ this.publish(entry, { ...entry.state, error: toQueryError(error), status: 'error', isFetching: false });
118
+ throw error;
119
+ }).finally(() => {
120
+ if (entry.pending !== pending)
121
+ return;
122
+ entry.pending = undefined;
123
+ if (entry.refreshAfterPending) {
124
+ entry.refreshAfterPending = false;
125
+ this.refresh(entry);
126
+ }
127
+ this.scheduleEviction(entry);
128
+ });
129
+ entry.pending = pending;
130
+ // Mark handled even when a UI caller deliberately discards the promise.
131
+ void pending.catch(() => { });
132
+ // Like TanStack's background refetches, retain the last error until success clears it
133
+ // or another failure replaces it. Extend that rule to retries without cached data:
134
+ // starting a request is not evidence of recovery; isFetching reports its progress.
135
+ const state = entry.state.data === undefined ? { ...entry.state, status: 'pending' } : entry.state;
136
+ this.publish(entry, { ...state, isFetching: this.online });
137
+ return pending;
138
+ }
139
+ replace({ entry, data }) {
140
+ entry.replacement += 1;
141
+ entry.updatedAt = this.clock.nowMs();
142
+ entry.invalidated = false;
143
+ this.publish(entry, { data, error: null, status: 'success', isFetching: entry.state.isFetching });
144
+ this.scheduleEviction(entry);
145
+ }
146
+ invalidate({ prefix }) {
147
+ for (const entry of this.entries.values()) {
148
+ if (!prefix.every((part, index) => entry.key[index] === part))
149
+ continue;
150
+ entry.invalidated = true;
151
+ this.refresh(entry);
152
+ }
153
+ }
154
+ onFocus() {
155
+ for (const entry of this.entries.values()) {
156
+ const observer = [...entry.observers].find(value => value.focus && !this.fresh({ entry: entry, staleTime: value.staleTime }));
157
+ // Environmental refreshes share a request already underway, unlike an explicit gesture.
158
+ if (observer && !entry.pending)
159
+ void this.load({ entry: entry, fetch: observer.fetch, staleTime: observer.staleTime });
160
+ }
161
+ }
162
+ /** Execute a read/write once connectivity returns; failures are not retried.
163
+ * @param required.run Operation to invoke online.
164
+ * @returns The operation's original result or rejection. */
165
+ runOnline({ run }) {
166
+ if (this.online)
167
+ return Promise.resolve().then(() => {
168
+ // Connectivity may change between queuing the operation and its invocation.
169
+ if (!this.online)
170
+ return this.runOnline({ run });
171
+ return run();
172
+ });
173
+ return new Promise(resolve => { this.onlineWaiters.add(resolve); }).then(() => this.runOnline({ run }));
174
+ }
175
+ /** Stop timers on provider disposal; reactivate for React's effect replay. */
176
+ activate() {
177
+ this.disposed = false;
178
+ if (!this.environment || this.releaseEnvironment)
179
+ return;
180
+ const releaseOnline = this.environment.subscribeOnline({ listener: online => this.onOnline({ online }) });
181
+ const releaseFocus = this.environment.subscribeFocus({ listener: () => this.onFocus() });
182
+ this.releaseEnvironment = () => { releaseOnline(); releaseFocus(); };
183
+ this.onOnline({ online: this.environment.isOnline() });
184
+ }
185
+ dispose() {
186
+ this.disposed = true;
187
+ this.releaseEnvironment?.();
188
+ this.releaseEnvironment = undefined;
189
+ for (const entry of this.entries.values())
190
+ this.cancelEviction(entry);
191
+ }
192
+ onOnline({ online }) {
193
+ const reconnect = online && !this.online;
194
+ this.online = online;
195
+ if (!online)
196
+ return;
197
+ for (const resume of this.onlineWaiters)
198
+ resume();
199
+ this.onlineWaiters.clear();
200
+ if (!reconnect)
201
+ return;
202
+ for (const entry of this.entries.values()) {
203
+ const observer = [...entry.observers].find(value => !this.fresh({ entry, staleTime: value.staleTime }));
204
+ // A paused request already owns its resumption; restarting it here would double-fetch.
205
+ if (observer && !entry.pending)
206
+ void this.load({ entry, fetch: observer.fetch, staleTime: observer.staleTime });
207
+ }
208
+ }
209
+ refresh(entry) {
210
+ const observer = entry.observers.values().next().value;
211
+ if (observer)
212
+ void this.load({ entry: entry, fetch: observer.fetch, staleTime: observer.staleTime }, { force: true });
213
+ }
214
+ publish(entry, state) {
215
+ entry.state = state;
216
+ for (const listener of entry.listeners)
217
+ listener();
218
+ }
219
+ cancelEviction(entry) {
220
+ if (entry.eviction !== undefined)
221
+ this.scheduler.cancel({ handle: entry.eviction });
222
+ entry.eviction = undefined;
223
+ }
224
+ scheduleEviction(entry) {
225
+ this.cancelEviction(entry);
226
+ if (this.disposed || entry.listeners.size || entry.observers.size || entry.pending || !Number.isFinite(entry.retention))
227
+ return;
228
+ entry.eviction = this.scheduler.schedule({ callback: () => this.entries.delete(JSON.stringify(entry.key)), delayMs: entry.retention });
229
+ }
230
+ }
231
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1,4 @@
1
+ import type { FetchQueryEnvironmentPort } from './cache.js';
2
+ /** Browser-only adapter: subscriptions are owned by the provider effect, never module scope. */
3
+ export declare const browserFetchQueryEnvironment: FetchQueryEnvironmentPort;
4
+ //# sourceMappingURL=environment.browser.d.ts.map