@jini-ai/admin 0.3.10 → 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 (399) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +71 -37
  3. package/dist/agent-plugins/adapters/http.d.ts +7 -0
  4. package/dist/agent-plugins/adapters/http.js +15 -0
  5. package/dist/agent-plugins/adapters/memory.d.ts +8 -0
  6. package/dist/agent-plugins/adapters/memory.js +25 -0
  7. package/dist/agent-plugins/agent-plugins.module.d.ts +51 -0
  8. package/dist/agent-plugins/agent-plugins.module.js +6 -0
  9. package/dist/agent-plugins/conformance/agent-plugins-api.conformance.d.ts +12 -0
  10. package/dist/agent-plugins/conformance/agent-plugins-api.conformance.js +47 -0
  11. package/dist/agent-plugins/controllers/agent-plugin-files.controller.d.ts +20 -0
  12. package/dist/agent-plugins/controllers/agent-plugin-files.controller.js +43 -0
  13. package/dist/agent-plugins/controllers/agent-plugins.controller.d.ts +25 -0
  14. package/dist/agent-plugins/controllers/agent-plugins.controller.js +91 -0
  15. package/dist/agent-plugins/index.d.ts +9 -0
  16. package/dist/agent-plugins/index.js +9 -0
  17. package/dist/agent-plugins/messages.en.d.ts +23 -0
  18. package/dist/agent-plugins/messages.en.js +14 -0
  19. package/dist/agent-plugins/models.d.ts +57 -0
  20. package/dist/agent-plugins/models.js +2 -0
  21. package/dist/agent-plugins/package-file-tree.d.ts +111 -0
  22. package/dist/agent-plugins/package-file-tree.js +188 -0
  23. package/dist/agent-plugins/ports.d.ts +18 -0
  24. package/dist/agent-plugins/ports.js +3 -0
  25. package/dist/agent-plugins/react/components/AgentPluginFileContent.d.ts +5 -0
  26. package/dist/agent-plugins/react/components/AgentPluginFileContent.js +9 -0
  27. package/dist/agent-plugins/react/components/AgentPluginFileTree.d.ts +9 -0
  28. package/dist/agent-plugins/react/components/AgentPluginFileTree.js +7 -0
  29. package/dist/agent-plugins/react/components/AgentPluginInspector.d.ts +3 -0
  30. package/dist/agent-plugins/react/components/AgentPluginInspector.js +11 -0
  31. package/dist/agent-plugins/react/components/AgentPluginListPanel.d.ts +6 -0
  32. package/dist/agent-plugins/react/components/AgentPluginListPanel.js +10 -0
  33. package/dist/agent-plugins/react/components/AgentPluginRow.d.ts +5 -0
  34. package/dist/agent-plugins/react/components/AgentPluginRow.js +8 -0
  35. package/dist/agent-plugins/react/hooks/AgentPluginInspector.hooks.d.ts +90 -0
  36. package/dist/agent-plugins/react/hooks/AgentPluginInspector.hooks.js +74 -0
  37. package/dist/agent-plugins/react/hooks/AgentPluginPanel.hooks.d.ts +67 -0
  38. package/dist/agent-plugins/react/hooks/AgentPluginPanel.hooks.js +50 -0
  39. package/dist/agent-plugins/react/hooks/AgentPluginRow.hooks.d.ts +55 -0
  40. package/dist/agent-plugins/react/hooks/AgentPluginRow.hooks.js +6 -0
  41. package/dist/agent-plugins/react/hooks/AgentPluginsPage.hooks.d.ts +64 -0
  42. package/dist/agent-plugins/react/hooks/AgentPluginsPage.hooks.js +39 -0
  43. package/dist/agent-plugins/react/hooks/AgentPluginsPorts.hooks.d.ts +7 -0
  44. package/dist/agent-plugins/react/hooks/AgentPluginsPorts.hooks.js +10 -0
  45. package/dist/agent-plugins/react/hooks/MarketplaceTab.hooks.d.ts +6 -0
  46. package/dist/agent-plugins/react/hooks/MarketplaceTab.hooks.js +3 -0
  47. package/dist/agent-plugins/react/index.d.ts +245 -0
  48. package/dist/agent-plugins/react/index.js +13 -0
  49. package/dist/agent-plugins/react/pages/AgentPluginsPage.d.ts +4 -0
  50. package/dist/agent-plugins/react/pages/AgentPluginsPage.js +12 -0
  51. package/dist/agent-plugins/react/tabs/DownloadedTab.d.ts +4 -0
  52. package/dist/agent-plugins/react/tabs/DownloadedTab.js +5 -0
  53. package/dist/agent-plugins/react/tabs/InstalledTab.d.ts +4 -0
  54. package/dist/agent-plugins/react/tabs/InstalledTab.js +5 -0
  55. package/dist/agent-plugins/react/tabs/MarketplaceTab.d.ts +4 -0
  56. package/dist/agent-plugins/react/tabs/MarketplaceTab.js +10 -0
  57. package/dist/agent-plugins/rules.d.ts +33 -0
  58. package/dist/agent-plugins/rules.js +51 -0
  59. package/dist/browser/index.d.ts +1 -0
  60. package/dist/browser/index.js +1 -0
  61. package/dist/browser/navigation.d.ts +19 -4
  62. package/dist/browser/navigation.js +8 -8
  63. package/dist/browser/shell-navigation.d.ts +12 -0
  64. package/dist/browser/shell-navigation.js +16 -0
  65. package/dist/contracts/credential-management.d.ts +8 -0
  66. package/dist/contracts/credential-management.js +3 -0
  67. package/dist/contracts/media-picker.d.ts +17 -0
  68. package/dist/contracts/media-picker.js +5 -0
  69. package/dist/contracts/playground-render-target.d.ts +18 -0
  70. package/dist/contracts/playground-render-target.js +3 -0
  71. package/dist/core/entities/rules.d.ts +138 -0
  72. package/dist/core/entities/rules.js +344 -0
  73. package/dist/core/gated/types.d.ts +8 -4
  74. package/dist/core/index.d.ts +4 -0
  75. package/dist/core/index.js +1 -0
  76. package/dist/core/manifest/rules.d.ts +24 -6
  77. package/dist/core/manifest/rules.js +12 -11
  78. package/dist/core/module/controller-store.d.ts +22 -0
  79. package/dist/core/module/controller-store.js +32 -0
  80. package/dist/core/module/create-admin.d.ts +41 -0
  81. package/dist/core/module/create-admin.js +187 -0
  82. package/dist/core/module/define-admin-module.d.ts +4 -0
  83. package/dist/core/module/define-admin-module.js +5 -0
  84. package/dist/core/module/index.d.ts +7 -0
  85. package/dist/core/module/index.js +4 -0
  86. package/dist/core/module/token.d.ts +19 -0
  87. package/dist/core/module/token.js +4 -0
  88. package/dist/core/module/types.d.ts +79 -0
  89. package/dist/core/module/types.js +2 -0
  90. package/dist/core/permissions/rules.d.ts +4 -1
  91. package/dist/core/permissions/rules.js +1 -1
  92. package/dist/core/ports/analytics.d.ts +1 -1
  93. package/dist/core/ports/auth.d.ts +2 -2
  94. package/dist/core/ports/comments.d.ts +9 -6
  95. package/dist/core/ports/database.d.ts +13 -10
  96. package/dist/core/ports/entities.d.ts +302 -0
  97. package/dist/core/ports/entities.js +47 -0
  98. package/dist/core/ports/forms.d.ts +19 -7
  99. package/dist/core/ports/identity.d.ts +42 -17
  100. package/dist/core/ports/index.d.ts +2 -0
  101. package/dist/core/ports/integrations.d.ts +9 -4
  102. package/dist/core/ports/media.d.ts +16 -7
  103. package/dist/core/ports/members.d.ts +7 -3
  104. package/dist/core/ports/menus.d.ts +43 -0
  105. package/dist/core/ports/menus.js +43 -0
  106. package/dist/core/ports/plugins.d.ts +3 -2
  107. package/dist/core/ports/recovery.d.ts +10 -6
  108. package/dist/core/ports/redirects.d.ts +17 -7
  109. package/dist/core/ports/seo.d.ts +12 -6
  110. package/dist/core/ports/shell.d.ts +41 -0
  111. package/dist/core/ports/shell.js +2 -0
  112. package/dist/core/ports/workspace.d.ts +3 -3
  113. package/dist/core/routing/rules.d.ts +17 -4
  114. package/dist/core/routing/rules.js +4 -4
  115. package/dist/core/transport/errors.d.ts +13 -4
  116. package/dist/core/transport/errors.js +4 -4
  117. package/dist/core/transport/http.d.ts +26 -16
  118. package/dist/core/transport/http.js +59 -21
  119. package/dist/core/transport/types.d.ts +26 -14
  120. package/dist/core/transport/types.js +9 -7
  121. package/dist/media/adapters/http.d.ts +27 -0
  122. package/dist/media/adapters/http.js +44 -0
  123. package/dist/media/adapters/memory.d.ts +11 -0
  124. package/dist/media/adapters/memory.js +139 -0
  125. package/dist/media/conformance/media-api.conformance.d.ts +7 -0
  126. package/dist/media/conformance/media-api.conformance.js +69 -0
  127. package/dist/media/controllers/edit-media.controller.d.ts +24 -0
  128. package/dist/media/controllers/edit-media.controller.js +69 -0
  129. package/dist/media/controllers/library.controller.d.ts +47 -0
  130. package/dist/media/controllers/library.controller.js +173 -0
  131. package/dist/media/controllers/providers.controller.d.ts +30 -0
  132. package/dist/media/controllers/providers.controller.js +76 -0
  133. package/dist/media/html-attributes.d.ts +82 -0
  134. package/dist/media/html-attributes.js +204 -0
  135. package/dist/media/index.d.ts +12 -0
  136. package/dist/media/index.js +9 -0
  137. package/dist/media/media.module.d.ts +83 -0
  138. package/dist/media/media.module.js +43 -0
  139. package/dist/media/messages.en.d.ts +24 -0
  140. package/dist/media/messages.en.js +24 -0
  141. package/dist/media/models.d.ts +72 -0
  142. package/dist/media/models.js +2 -0
  143. package/dist/media/ports.d.ts +75 -0
  144. package/dist/media/ports.js +7 -0
  145. package/dist/media/react/components/EditMediaPanel.d.ts +3 -0
  146. package/dist/media/react/components/EditMediaPanel.js +10 -0
  147. package/dist/media/react/components/MediaCard.d.ts +5 -0
  148. package/dist/media/react/components/MediaCard.js +17 -0
  149. package/dist/media/react/components/MediaDialog.d.ts +3 -0
  150. package/dist/media/react/components/MediaDialog.js +8 -0
  151. package/dist/media/react/components/MediaGrid.d.ts +4 -0
  152. package/dist/media/react/components/MediaGrid.js +8 -0
  153. package/dist/media/react/components/MediaIcons.d.ts +14 -0
  154. package/dist/media/react/components/MediaIcons.js +39 -0
  155. package/dist/media/react/components/MediaLightbox.d.ts +5 -0
  156. package/dist/media/react/components/MediaLightbox.js +12 -0
  157. package/dist/media/react/components/MediaPicker.d.ts +3 -0
  158. package/dist/media/react/components/MediaPicker.js +10 -0
  159. package/dist/media/react/components/MediaPurgeDialog.d.ts +4 -0
  160. package/dist/media/react/components/MediaPurgeDialog.js +9 -0
  161. package/dist/media/react/components/UploadButton.d.ts +3 -0
  162. package/dist/media/react/components/UploadButton.js +8 -0
  163. package/dist/media/react/hooks/EditMediaPanel.hooks.d.ts +84 -0
  164. package/dist/media/react/hooks/EditMediaPanel.hooks.js +105 -0
  165. package/dist/media/react/hooks/LibraryTab.hooks.d.ts +103 -0
  166. package/dist/media/react/hooks/LibraryTab.hooks.js +164 -0
  167. package/dist/media/react/hooks/MediaCard.hooks.d.ts +79 -0
  168. package/dist/media/react/hooks/MediaCard.hooks.js +63 -0
  169. package/dist/media/react/hooks/MediaDialog.hooks.d.ts +10 -0
  170. package/dist/media/react/hooks/MediaDialog.hooks.js +20 -0
  171. package/dist/media/react/hooks/MediaGrid.hooks.d.ts +28 -0
  172. package/dist/media/react/hooks/MediaGrid.hooks.js +6 -0
  173. package/dist/media/react/hooks/MediaLightbox.hooks.d.ts +27 -0
  174. package/dist/media/react/hooks/MediaLightbox.hooks.js +64 -0
  175. package/dist/media/react/hooks/MediaPage.hooks.d.ts +68 -0
  176. package/dist/media/react/hooks/MediaPage.hooks.js +68 -0
  177. package/dist/media/react/hooks/MediaPicker.hooks.d.ts +26 -0
  178. package/dist/media/react/hooks/MediaPicker.hooks.js +25 -0
  179. package/dist/media/react/hooks/MediaPorts.hooks.d.ts +9 -0
  180. package/dist/media/react/hooks/MediaPorts.hooks.js +10 -0
  181. package/dist/media/react/hooks/MediaPurgeDialog.hooks.d.ts +22 -0
  182. package/dist/media/react/hooks/MediaPurgeDialog.hooks.js +6 -0
  183. package/dist/media/react/hooks/ProvidersTab.hooks.d.ts +55 -0
  184. package/dist/media/react/hooks/ProvidersTab.hooks.js +124 -0
  185. package/dist/media/react/hooks/UploadButton.hooks.d.ts +48 -0
  186. package/dist/media/react/hooks/UploadButton.hooks.js +118 -0
  187. package/dist/media/react/index.d.ts +373 -0
  188. package/dist/media/react/index.js +73 -0
  189. package/dist/media/react/pages/MediaPage.d.ts +4 -0
  190. package/dist/media/react/pages/MediaPage.js +9 -0
  191. package/dist/media/react/tabs/LibraryTab.d.ts +4 -0
  192. package/dist/media/react/tabs/LibraryTab.js +14 -0
  193. package/dist/media/react/tabs/ProvidersTab.d.ts +4 -0
  194. package/dist/media/react/tabs/ProvidersTab.js +10 -0
  195. package/dist/media/rules.d.ts +80 -0
  196. package/dist/media/rules.js +127 -0
  197. package/dist/media/styles.d.ts +4 -0
  198. package/dist/media/styles.js +5 -0
  199. package/dist/playground/adapters/http.d.ts +8 -0
  200. package/dist/playground/adapters/http.js +4 -0
  201. package/dist/playground/adapters/memory.d.ts +10 -0
  202. package/dist/playground/adapters/memory.js +30 -0
  203. package/dist/playground/conformance/playground-api.conformance.d.ts +6 -0
  204. package/dist/playground/conformance/playground-api.conformance.js +37 -0
  205. package/dist/playground/controllers/playground.controller.d.ts +16 -0
  206. package/dist/playground/controllers/playground.controller.js +21 -0
  207. package/dist/playground/index.d.ts +7 -0
  208. package/dist/playground/index.js +5 -0
  209. package/dist/playground/messages.en.d.ts +9 -0
  210. package/dist/playground/messages.en.js +2 -0
  211. package/dist/playground/models.d.ts +4 -0
  212. package/dist/playground/models.js +2 -0
  213. package/dist/playground/playground.module.d.ts +31 -0
  214. package/dist/playground/playground.module.js +5 -0
  215. package/dist/playground/ports.d.ts +5 -0
  216. package/dist/playground/ports.js +2 -0
  217. package/dist/playground/react/components/Canvas.d.ts +3 -0
  218. package/dist/playground/react/components/Canvas.js +9 -0
  219. package/dist/playground/react/hooks/Canvas.hooks.d.ts +7 -0
  220. package/dist/playground/react/hooks/Canvas.hooks.js +18 -0
  221. package/dist/playground/react/hooks/PlaygroundPage.hooks.d.ts +8 -0
  222. package/dist/playground/react/hooks/PlaygroundPage.hooks.js +2 -0
  223. package/dist/playground/react/hooks/PlaygroundPorts.hooks.d.ts +4 -0
  224. package/dist/playground/react/hooks/PlaygroundPorts.hooks.js +6 -0
  225. package/dist/playground/react/index.d.ts +136 -0
  226. package/dist/playground/react/index.js +10 -0
  227. package/dist/playground/react/pages/PlaygroundPage.d.ts +4 -0
  228. package/dist/playground/react/pages/PlaygroundPage.js +11 -0
  229. package/dist/playground/react/tabs/CanvasTab.d.ts +4 -0
  230. package/dist/playground/react/tabs/CanvasTab.js +5 -0
  231. package/dist/playground/rules.d.ts +4 -0
  232. package/dist/playground/rules.js +2 -0
  233. package/dist/react/OverlayHost.d.ts +3 -0
  234. package/dist/react/OverlayHost.hooks.d.ts +9 -0
  235. package/dist/react/OverlayHost.hooks.js +9 -0
  236. package/dist/react/OverlayHost.js +7 -0
  237. package/dist/react/bind-react.d.ts +46 -0
  238. package/dist/react/bind-react.js +28 -0
  239. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.d.ts +7 -1
  240. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.js +2 -2
  241. package/dist/react/components/ConfirmButton/ConfirmButton.js +1 -1
  242. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts +17 -3
  243. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js +3 -3
  244. package/dist/react/components/ConfirmDialog/ConfirmDialog.js +5 -5
  245. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.d.ts +6 -2
  246. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.js +7 -8
  247. package/dist/react/components/RowMenu/RowMenu.d.ts +5 -1
  248. package/dist/react/components/RowMenu/RowMenu.hooks.d.ts +8 -2
  249. package/dist/react/components/RowMenu/RowMenu.hooks.js +4 -4
  250. package/dist/react/components/RowMenu/RowMenu.js +6 -6
  251. package/dist/react/components/Sidebar.d.ts +1 -1
  252. package/dist/react/components/Sidebar.js +103 -7
  253. package/dist/react/entities/EntityCell.d.ts +10 -0
  254. package/dist/react/entities/EntityCell.js +18 -0
  255. package/dist/react/entities/EntityDetail.d.ts +3 -0
  256. package/dist/react/entities/EntityDetail.js +21 -0
  257. package/dist/react/entities/EntityEdit.d.ts +13 -0
  258. package/dist/react/entities/EntityEdit.js +45 -0
  259. package/dist/react/entities/EntityField.d.ts +20 -0
  260. package/dist/react/entities/EntityField.js +31 -0
  261. package/dist/react/entities/EntityIndex.d.ts +3 -0
  262. package/dist/react/entities/EntityIndex.js +10 -0
  263. package/dist/react/entities/EntityList.d.ts +7 -0
  264. package/dist/react/entities/EntityList.js +52 -0
  265. package/dist/react/entities/contribution.d.ts +26 -0
  266. package/dist/react/entities/contribution.js +78 -0
  267. package/dist/react/entities/index.d.ts +10 -0
  268. package/dist/react/entities/index.js +7 -0
  269. package/dist/react/entities/rules.d.ts +179 -0
  270. package/dist/react/entities/rules.js +224 -0
  271. package/dist/react/entities/types.d.ts +45 -0
  272. package/dist/react/entities/types.js +5 -0
  273. package/dist/react/entities/use-entity-edit.d.ts +35 -0
  274. package/dist/react/entities/use-entity-edit.js +98 -0
  275. package/dist/react/entities/use-entity-read.d.ts +22 -0
  276. package/dist/react/entities/use-entity-read.js +27 -0
  277. package/dist/react/hooks/use-nav-sections.d.ts +12 -3
  278. package/dist/react/hooks/use-nav-sections.js +14 -14
  279. package/dist/react/hooks/use-sidebar-rail.d.ts +7 -1
  280. package/dist/react/hooks/use-sidebar-rail.js +11 -11
  281. package/dist/react/index.d.ts +3 -1
  282. package/dist/react/index.js +5 -2
  283. package/dist/react/kit/Kit.hooks.d.ts +13 -0
  284. package/dist/react/kit/Kit.hooks.js +10 -0
  285. package/dist/react/kit/Native.hooks.d.ts +38 -0
  286. package/dist/react/kit/Native.hooks.js +65 -0
  287. package/dist/react/kit/index.d.ts +12 -0
  288. package/dist/react/kit/index.js +21 -0
  289. package/dist/react/kit/native.d.ts +3 -0
  290. package/dist/react/kit/native.js +21 -0
  291. package/dist/react/kit/types.d.ts +40 -0
  292. package/dist/react/kit/types.js +2 -0
  293. package/dist/react/overlay.d.ts +36 -0
  294. package/dist/react/overlay.js +35 -0
  295. package/dist/react/overlays.d.ts +38 -0
  296. package/dist/react/overlays.js +46 -0
  297. package/dist/react/shell/AdminShell.d.ts +9 -0
  298. package/dist/react/shell/AdminShell.hooks.d.ts +15 -0
  299. package/dist/react/shell/AdminShell.hooks.js +27 -0
  300. package/dist/react/shell/AdminShell.js +46 -0
  301. package/dist/react/shell/index.d.ts +7 -0
  302. package/dist/react/shell/index.js +5 -0
  303. package/dist/react/shell/model.d.ts +25 -0
  304. package/dist/react/shell/model.js +29 -0
  305. package/dist/react/shell/theme-ports.d.ts +28 -0
  306. package/dist/react/shell/theme-ports.js +2 -0
  307. package/dist/react/shell/types.d.ts +99 -0
  308. package/dist/react/shell/types.js +2 -0
  309. package/dist/react/shell/use-admin-shell-session.d.ts +13 -0
  310. package/dist/react/shell/use-admin-shell-session.js +81 -0
  311. package/dist/react/shell/use-admin-theme.d.ts +16 -0
  312. package/dist/react/shell/use-admin-theme.js +57 -0
  313. package/dist/react/types.d.ts +6 -4
  314. package/dist/react/types.js +2 -2
  315. package/dist/react/use-controller.d.ts +16 -0
  316. package/dist/react/use-controller.js +18 -0
  317. package/dist/security/adapters/http.d.ts +16 -0
  318. package/dist/security/adapters/http.js +94 -0
  319. package/dist/security/adapters/memory.d.ts +15 -0
  320. package/dist/security/adapters/memory.js +60 -0
  321. package/dist/security/conformance/security-api.conformance.d.ts +10 -0
  322. package/dist/security/conformance/security-api.conformance.js +48 -0
  323. package/dist/security/controllers/access-tokens.controller.d.ts +44 -0
  324. package/dist/security/controllers/access-tokens.controller.js +112 -0
  325. package/dist/security/controllers/other-credentials.controller.d.ts +30 -0
  326. package/dist/security/controllers/other-credentials.controller.js +74 -0
  327. package/dist/security/controllers/root-key.controller.d.ts +35 -0
  328. package/dist/security/controllers/root-key.controller.js +90 -0
  329. package/dist/security/index.d.ts +9 -0
  330. package/dist/security/index.js +9 -0
  331. package/dist/security/messages.en.d.ts +12 -0
  332. package/dist/security/messages.en.js +2 -0
  333. package/dist/security/models.d.ts +112 -0
  334. package/dist/security/models.js +2 -0
  335. package/dist/security/ports.d.ts +58 -0
  336. package/dist/security/ports.js +5 -0
  337. package/dist/security/react/components/CredentialEditor.d.ts +3 -0
  338. package/dist/security/react/components/CredentialEditor.js +8 -0
  339. package/dist/security/react/hooks/AccessTokensTab.hooks.d.ts +94 -0
  340. package/dist/security/react/hooks/AccessTokensTab.hooks.js +36 -0
  341. package/dist/security/react/hooks/CredentialEditor.hooks.d.ts +49 -0
  342. package/dist/security/react/hooks/CredentialEditor.hooks.js +14 -0
  343. package/dist/security/react/hooks/RootKeyTab.hooks.d.ts +29 -0
  344. package/dist/security/react/hooks/RootKeyTab.hooks.js +19 -0
  345. package/dist/security/react/hooks/SecurityPage.hooks.d.ts +17 -0
  346. package/dist/security/react/hooks/SecurityPage.hooks.js +12 -0
  347. package/dist/security/react/hooks/SecurityPorts.hooks.d.ts +9 -0
  348. package/dist/security/react/hooks/SecurityPorts.hooks.js +6 -0
  349. package/dist/security/react/index.d.ts +215 -0
  350. package/dist/security/react/index.js +10 -0
  351. package/dist/security/react/pages/SecurityPage.d.ts +4 -0
  352. package/dist/security/react/pages/SecurityPage.js +10 -0
  353. package/dist/security/react/tabs/AccessTokensTab.d.ts +4 -0
  354. package/dist/security/react/tabs/AccessTokensTab.js +10 -0
  355. package/dist/security/react/tabs/RootKeyTab.d.ts +4 -0
  356. package/dist/security/react/tabs/RootKeyTab.js +9 -0
  357. package/dist/security/rules.d.ts +57 -0
  358. package/dist/security/rules.js +63 -0
  359. package/dist/security/security.module.d.ts +45 -0
  360. package/dist/security/security.module.js +5 -0
  361. package/dist/source-control/adapters/http.d.ts +6 -0
  362. package/dist/source-control/adapters/http.js +13 -0
  363. package/dist/source-control/adapters/memory.d.ts +9 -0
  364. package/dist/source-control/adapters/memory.js +35 -0
  365. package/dist/source-control/conformance/source-control-api.conformance.d.ts +10 -0
  366. package/dist/source-control/conformance/source-control-api.conformance.js +48 -0
  367. package/dist/source-control/controllers/source-control.controller.d.ts +26 -0
  368. package/dist/source-control/controllers/source-control.controller.js +70 -0
  369. package/dist/source-control/index.d.ts +8 -0
  370. package/dist/source-control/index.js +6 -0
  371. package/dist/source-control/messages.en.d.ts +11 -0
  372. package/dist/source-control/messages.en.js +2 -0
  373. package/dist/source-control/models.d.ts +70 -0
  374. package/dist/source-control/models.js +2 -0
  375. package/dist/source-control/ports.d.ts +23 -0
  376. package/dist/source-control/ports.js +3 -0
  377. package/dist/source-control/react/components/SourceControlCredentialFields.d.ts +5 -0
  378. package/dist/source-control/react/components/SourceControlCredentialFields.js +8 -0
  379. package/dist/source-control/react/components/SourceControlProviderRow.d.ts +5 -0
  380. package/dist/source-control/react/components/SourceControlProviderRow.js +7 -0
  381. package/dist/source-control/react/hooks/ProvidersTab.hooks.d.ts +45 -0
  382. package/dist/source-control/react/hooks/ProvidersTab.hooks.js +20 -0
  383. package/dist/source-control/react/hooks/SourceControlCredentialFields.hooks.d.ts +43 -0
  384. package/dist/source-control/react/hooks/SourceControlCredentialFields.hooks.js +9 -0
  385. package/dist/source-control/react/hooks/SourceControlPage.hooks.d.ts +17 -0
  386. package/dist/source-control/react/hooks/SourceControlPage.hooks.js +5 -0
  387. package/dist/source-control/react/hooks/SourceControlPorts.hooks.d.ts +9 -0
  388. package/dist/source-control/react/hooks/SourceControlPorts.hooks.js +6 -0
  389. package/dist/source-control/react/index.d.ts +156 -0
  390. package/dist/source-control/react/index.js +10 -0
  391. package/dist/source-control/react/pages/SourceControlPage.d.ts +4 -0
  392. package/dist/source-control/react/pages/SourceControlPage.js +11 -0
  393. package/dist/source-control/react/tabs/ProvidersTab.d.ts +4 -0
  394. package/dist/source-control/react/tabs/ProvidersTab.js +10 -0
  395. package/dist/source-control/rules.d.ts +32 -0
  396. package/dist/source-control/rules.js +35 -0
  397. package/dist/source-control/source-control.module.d.ts +36 -0
  398. package/dist/source-control/source-control.module.js +6 -0
  399. package/package.json +207 -4
@@ -0,0 +1,84 @@
1
+ import type { MediaApiPort } from '../../ports.js';
2
+ import type { MediaAsset, MediaMetadataPatch, UploadInput } from '../../models.js';
3
+ export interface EditMediaPanelProps {
4
+ readonly api: MediaApiPort;
5
+ readonly item: MediaAsset;
6
+ readonly onSaved: (required?: {
7
+ message?: string;
8
+ }) => void | Promise<void>;
9
+ readonly onClose: () => void;
10
+ }
11
+ export declare function useEditMediaPanel(props: EditMediaPanelProps, _optional?: Record<string, never>): {
12
+ snapshot: Readonly<{
13
+ draft: MediaMetadataPatch;
14
+ saving: boolean;
15
+ error: string | null;
16
+ }> | null;
17
+ fields: {
18
+ value: string;
19
+ attrs: {
20
+ 'aria-invalid'?: boolean;
21
+ 'data-jini-autofocus'?: boolean;
22
+ 'data-jini-part': string;
23
+ 'data-agent-element': string;
24
+ };
25
+ onValueChange: ({ value }: {
26
+ value: string;
27
+ }, _optional?: Record<string, never>) => void;
28
+ placeholder?: string;
29
+ type: "number" | "text";
30
+ ref?: import("react").RefObject<HTMLInputElement | null>;
31
+ fieldId: string;
32
+ label: string;
33
+ }[];
34
+ fieldRows: {
35
+ id: number;
36
+ className: string;
37
+ fields: {
38
+ value: string;
39
+ attrs: {
40
+ 'aria-invalid'?: boolean;
41
+ 'data-jini-autofocus'?: boolean;
42
+ 'data-jini-part': string;
43
+ 'data-agent-element': string;
44
+ };
45
+ onValueChange: ({ value }: {
46
+ value: string;
47
+ }, _optional?: Record<string, never>) => void;
48
+ placeholder?: string;
49
+ type: "number" | "text";
50
+ ref?: import("react").RefObject<HTMLInputElement | null>;
51
+ fieldId: string;
52
+ label: string;
53
+ }[];
54
+ }[];
55
+ copies: {
56
+ isLink: boolean;
57
+ buttonLabel: string;
58
+ attrs: {
59
+ 'data-agent-element': string;
60
+ 'aria-label': string;
61
+ };
62
+ copy(): Promise<void>;
63
+ id: string;
64
+ label: string;
65
+ value: string;
66
+ noun: string;
67
+ }[];
68
+ hint: string | null;
69
+ saving: boolean;
70
+ title: string;
71
+ canReplace: boolean;
72
+ onSave(): Promise<void>;
73
+ replace({ input }: {
74
+ input: UploadInput;
75
+ }, _optional?: Record<string, never>): Promise<boolean>;
76
+ close(): void;
77
+ api: MediaApiPort;
78
+ item: MediaAsset;
79
+ onSaved: (required?: {
80
+ message?: string;
81
+ }) => void | Promise<void>;
82
+ onClose: () => void;
83
+ };
84
+ //# sourceMappingURL=EditMediaPanel.hooks.d.ts.map
@@ -0,0 +1,105 @@
1
+ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
2
+ import { useController } from '../../../react/use-controller.js';
3
+ import { createEditMediaController } from '../../controllers/edit-media.controller.js';
4
+ import { canReplaceMedia, mediaEmbedSnippet, parseOptionalPixelSize, safeMediaUrl } from '../../rules.js';
5
+ import { parseMediaHtmlAttributes, describeMediaHtmlAttributeError } from '../../html-attributes.js';
6
+ export function useEditMediaPanel(props, _optional = {}) {
7
+ const { controller, snapshot } = useController({
8
+ create: () => createEditMediaController({ api: props.api, item: props.item }),
9
+ dependencies: [props.api, props.item.id],
10
+ });
11
+ const [copied, setCopied] = useState({});
12
+ const timers = useRef(new Map());
13
+ const mounted = useRef(false);
14
+ useEffect(() => {
15
+ mounted.current = true;
16
+ return () => { mounted.current = false; for (const timer of timers.current.values())
17
+ clearTimeout(timer); timers.current.clear(); };
18
+ }, []);
19
+ const saving = !snapshot || snapshot.saving;
20
+ const titleRef = useRef(null);
21
+ const ready = !!snapshot;
22
+ useLayoutEffect(() => {
23
+ // The controller attaches after the first render. Title is initially disabled;
24
+ // focus it once the draft is ready, rather than letting a later copy button win.
25
+ if (!ready)
26
+ return;
27
+ titleRef.current?.focus({ preventScroll: true });
28
+ const dialog = titleRef.current?.closest('dialog');
29
+ if (dialog)
30
+ dialog.scrollTop = 0;
31
+ }, [ready]);
32
+ // Live hint ONLY: invalid attributes must never gate saving unrelated dirty metadata.
33
+ // The server revalidates atomically and reports errors through the usual save banner.
34
+ const parsed = parseMediaHtmlAttributes({ text: snapshot?.draft.htmlAttributes ?? '' });
35
+ const hint = parsed.error ? describeMediaHtmlAttributeError({ error: parsed.error }) : null;
36
+ const fields = [
37
+ { key: 'title', label: 'Title', handle: 'title' },
38
+ { key: 'alt', label: 'Alt', handle: 'alt' },
39
+ { key: 'slug', label: 'Slug', handle: 'slug' },
40
+ { key: 'caption', label: 'Caption', handle: 'caption' },
41
+ { key: 'credit', label: 'Credit', handle: 'credit' },
42
+ { key: 'width', label: 'Width (px)', handle: 'width' },
43
+ { key: 'height', label: 'Height (px)', handle: 'height' },
44
+ { key: 'cssClass', label: 'CSS class (optional)', handle: 'css-class' },
45
+ { key: 'htmlAttributes', label: 'HTML attributes (optional)', handle: 'html-attributes' },
46
+ ].map(({ key, label, handle }) => ({
47
+ fieldId: key, label, ...(key === 'title' ? { ref: titleRef } : {}), type: key === 'width' || key === 'height' ? 'number' : 'text',
48
+ ...(key === 'width' || key === 'height' ? { placeholder: 'native' } : {}),
49
+ value: String(snapshot?.draft[key] ?? ''),
50
+ attrs: { 'data-jini-part': `media.editor.${key}`, 'data-agent-element': `media-edit-${handle}`,
51
+ ...(key === 'title' ? { 'data-jini-autofocus': true } : {}),
52
+ ...(key === 'htmlAttributes' ? { 'aria-invalid': !!hint } : {}) },
53
+ onValueChange: ({ value }, _optional = {}) => {
54
+ const next = key === 'width' || key === 'height' ? parseOptionalPixelSize({ value })
55
+ : key === 'cssClass' || key === 'htmlAttributes' ? value.trim() === '' ? null : value : value;
56
+ controller?.setDraft({ patch: { [key]: next } });
57
+ },
58
+ }));
59
+ // Server-computed public URL, never the authenticated original route. Trashed assets
60
+ // and hosts without a public transform expose no link or copy action at all.
61
+ const publicUrl = props.item.status === 'active' && props.item.publicUrl
62
+ ? safeMediaUrl({ url: props.item.publicUrl }) : undefined;
63
+ const embed = mediaEmbedSnippet({ slug: props.item.slug });
64
+ // Visible text is the legacy "Copy"/"Copied" on every row; the accessible name keeps
65
+ // the value's noun so three identical buttons stay distinguishable, even mid-feedback.
66
+ const copies = [
67
+ { id: 'url', label: 'File URL', value: publicUrl, noun: 'URL' },
68
+ { id: 'embed', label: 'Embed code', value: embed, noun: 'embed code' },
69
+ { id: 'hash', label: 'sha256', value: props.item.sha256, noun: 'hash' },
70
+ ].filter((row) => !!row.value)
71
+ .map(row => ({ ...row, isLink: row.id === 'url', buttonLabel: copied[row.id] ? 'Copied' : 'Copy',
72
+ attrs: { 'data-agent-element': `media-edit-copy-${row.id}`,
73
+ 'aria-label': `${copied[row.id] ? 'Copied' : 'Copy'} ${row.noun}` },
74
+ async copy() {
75
+ try {
76
+ await navigator.clipboard.writeText(row.value);
77
+ if (!mounted.current)
78
+ return;
79
+ setCopied(current => ({ ...current, [row.id]: true }));
80
+ clearTimeout(timers.current.get(row.id));
81
+ timers.current.set(row.id, setTimeout(() => {
82
+ timers.current.delete(row.id);
83
+ setCopied(current => ({ ...current, [row.id]: false }));
84
+ }, 1500));
85
+ }
86
+ catch {
87
+ // Clipboard may be denied/insecure. The full value stays selectable for manual copy.
88
+ }
89
+ },
90
+ }));
91
+ const fieldRows = [[0, 1], [2], [3, 4], [5, 6], [7], [8]].map((indexes, index) => ({ id: index, className: indexes.length > 1 ? 'jini-field-row' : 'jini-field-group-row', fields: indexes.map(i => fields[i]) }));
92
+ return { ...props, snapshot, fields, fieldRows, copies, hint, saving, title: `Editing "${props.item.title}"`,
93
+ canReplace: canReplaceMedia({ api: props.api }),
94
+ async onSave() { if (await controller?.save())
95
+ await props.onSaved(); },
96
+ async replace({ input }, _optional = {}) {
97
+ const result = (await controller?.replace({ upload: input })) ?? false;
98
+ if (result)
99
+ await props.onSaved({ message: `Replaced ${props.item.title}` });
100
+ return result;
101
+ },
102
+ close() { if (!saving)
103
+ props.onClose(); }, };
104
+ }
105
+ //# sourceMappingURL=EditMediaPanel.hooks.js.map
@@ -0,0 +1,103 @@
1
+ import type { TabViewProps } from '../../../react/bind-react.js';
2
+ import { createLibraryController } from '../../controllers/library.controller.js';
3
+ import type { MediaAsset } from '../../models.js';
4
+ export declare function useLibraryTab({ params, permissions }: TabViewProps, _optional?: Record<string, never>): {
5
+ emptyLabel: string;
6
+ canUpload: boolean;
7
+ success: string | null;
8
+ gridRef: import("react").RefObject<HTMLDivElement | null>;
9
+ onRetry: () => void;
10
+ statusFilter: string;
11
+ onStatus: ({ value }: {
12
+ value: string;
13
+ }) => void;
14
+ canPurge: boolean;
15
+ controller: {
16
+ getSnapshot: () => Readonly<import("../../index.js").LibraryState>;
17
+ subscribe: ({ listener }: {
18
+ listener: () => void;
19
+ }) => () => void;
20
+ load: (_required?: Record<string, never>, _optional?: Record<string, never>) => Promise<void>;
21
+ setQuery({ query }: {
22
+ query: import("../../models.js").MediaQuery;
23
+ }, _optional?: Record<string, never>): Promise<void>;
24
+ upload({ input, alt }: {
25
+ input: import("../../models.js").UploadInput;
26
+ alt?: string;
27
+ }, _optional?: Record<string, never>): Promise<boolean>;
28
+ trash({ id }: {
29
+ id: string;
30
+ }, _optional?: Record<string, never>): Promise<boolean>;
31
+ restore({ id }: {
32
+ id: string;
33
+ }, _optional?: Record<string, never>): Promise<boolean>;
34
+ requestPurge({ item }: {
35
+ item: MediaAsset;
36
+ }, _optional?: Record<string, never>): void;
37
+ cancelPurge(_required?: Record<string, never>, _optional?: Record<string, never>): void;
38
+ confirmPurge({ confirmed }: {
39
+ confirmed: boolean;
40
+ }, _optional?: Record<string, never>): Promise<boolean>;
41
+ dispose(_required?: Record<string, never>, _optional?: Record<string, never>): void;
42
+ } | null;
43
+ snapshot: import("../../index.js").LibraryState | null;
44
+ actions: {
45
+ onPurge?: () => void | undefined;
46
+ onRestore?: () => void;
47
+ onTrash?: () => void;
48
+ onPreview: () => void;
49
+ onEdit?: () => void;
50
+ item: MediaAsset;
51
+ busy: boolean;
52
+ }[];
53
+ items: readonly MediaAsset[];
54
+ mediaApi: import("../../ports.js").MediaApiPort;
55
+ editing: MediaAsset | null;
56
+ closeEdit: () => void;
57
+ saved: ({ message }?: {
58
+ message?: string;
59
+ }) => Promise<void>;
60
+ lightboxIndex: number | null;
61
+ onNavigate: import("react").Dispatch<import("react").SetStateAction<number | null>>;
62
+ closeLightbox: () => void;
63
+ onSearch: ({ value: search }: {
64
+ value: string;
65
+ }) => void;
66
+ orderBy: import("../../models.js").MediaOrderBy;
67
+ onOrder: ({ value }: {
68
+ value: string;
69
+ }) => void;
70
+ onOrderCreated: () => void;
71
+ onOrderAlphabetical: () => void;
72
+ search: string;
73
+ loading: boolean;
74
+ busy: boolean;
75
+ untyped: boolean;
76
+ upload({ input, alt }: Parameters<ReturnType<typeof createLibraryController>["upload"]>[0]): Promise<boolean>;
77
+ cancelPurge: () => void | undefined;
78
+ confirmPurge: () => Promise<void> | undefined;
79
+ t: {
80
+ readonly media: "Media";
81
+ readonly all: "All";
82
+ readonly images: "Images";
83
+ readonly videos: "Videos";
84
+ readonly providers: "External Providers";
85
+ readonly upload: "Upload";
86
+ readonly title: "Title";
87
+ readonly alt: "Alt text";
88
+ readonly save: "Save";
89
+ readonly cancel: "Cancel";
90
+ readonly empty: "No media found";
91
+ readonly loading: "Loading media…";
92
+ readonly choose: "Choose media";
93
+ readonly trash: "Trash";
94
+ readonly purge: "Delete permanently";
95
+ readonly purgeWarning: "This permanently deletes the file. This cannot be undone.";
96
+ readonly edit: "Edit metadata";
97
+ readonly preview: "View larger";
98
+ readonly replace: "Replace file";
99
+ readonly unavailable: "Provider service unavailable";
100
+ readonly untyped: "Some assets have no recorded content type and only appear under All.";
101
+ };
102
+ };
103
+ //# sourceMappingURL=LibraryTab.hooks.d.ts.map
@@ -0,0 +1,164 @@
1
+ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
2
+ import { useController } from '../../../react/use-controller.js';
3
+ import { createLibraryController } from '../../controllers/library.controller.js';
4
+ import { useSharedMediaLibrary } from './MediaPage.hooks.js';
5
+ import { useMediaPorts } from './MediaPorts.hooks.js';
6
+ import { mediaMessagesEn } from '../../messages.en.js';
7
+ import { canRestoreMedia } from '../../rules.js';
8
+ export function useLibraryTab({ params, permissions = [] }, _optional = {}) {
9
+ const { mediaApi, mediaEvents } = useMediaPorts();
10
+ const filter = params.filter === 'images' || params.filter === 'videos' ? params.filter : 'all';
11
+ const shared = useSharedMediaLibrary();
12
+ const local = useController({
13
+ create: () => createLibraryController({ api: mediaApi }, { query: { filter } }),
14
+ dependencies: [mediaApi, filter],
15
+ }, {
16
+ start: ({ controller }) => {
17
+ if (!shared)
18
+ void controller.load();
19
+ },
20
+ });
21
+ const { controller, snapshot } = shared ?? local;
22
+ useEffect(() => !shared ? mediaEvents?.subscribe({ onRefresh: () => { void controller?.load(); } }) : undefined, [mediaEvents, controller, shared]);
23
+ const gridRef = useRef(null);
24
+ const [success, setSuccess] = useState(null);
25
+ const [focusAfterAction, setFocusAfterAction] = useState(null);
26
+ useLayoutEffect(() => {
27
+ if (!focusAfterAction || snapshot?.busy || snapshot?.loading)
28
+ return;
29
+ const cards = Array.from(gridRef.current?.querySelectorAll('[data-jini-part="media.card"]') ?? []);
30
+ const target = cards.find(card => card.dataset.mediaId === focusAfterAction.id) ?? cards[Math.min(focusAfterAction.index, cards.length - 1)] ?? gridRef.current;
31
+ target?.focus({ preventScroll: true });
32
+ setFocusAfterAction(null);
33
+ }, [focusAfterAction, snapshot?.busy, snapshot?.loading, snapshot?.items]);
34
+ const [focusAfterPurge, setFocusAfterPurge] = useState(null);
35
+ useLayoutEffect(() => {
36
+ if (focusAfterPurge === null || snapshot?.pendingPurge || snapshot?.busy)
37
+ return;
38
+ const grid = gridRef.current;
39
+ const cards = grid?.querySelectorAll('[data-jini-part="media.card"]');
40
+ const target = cards?.[Math.min(focusAfterPurge, cards.length - 1)] ?? grid;
41
+ target?.focus({ preventScroll: true });
42
+ setFocusAfterPurge(null);
43
+ }, [focusAfterPurge, snapshot?.pendingPurge, snapshot?.busy, snapshot?.items]);
44
+ useEffect(() => {
45
+ // A shared page controller survives tab unmounts. Re-entering after an error must
46
+ // be a recovery opportunity even when its cached filter already matches this tab.
47
+ if (controller?.getSnapshot().error && !controller.getSnapshot().loading)
48
+ void controller.load();
49
+ }, [controller]);
50
+ const [editing, setEditing] = useState(null);
51
+ // Lightbox — an index into the list, not the item itself, so arrow-key/navigation
52
+ // buttons move the number without re-deriving "what's next" from an item reference.
53
+ const [lightboxIndex, setLightboxIndex] = useState(null);
54
+ const items = snapshot?.items ?? [];
55
+ const canUpload = permissions.includes('media.upload');
56
+ const canEdit = permissions.includes('media.update');
57
+ const canTrash = permissions.includes('media.trash');
58
+ const canRestore = permissions.includes('media.restore') && canRestoreMedia({ api: mediaApi });
59
+ const canPurge = permissions.includes('media.delete.force');
60
+ const actions = items.map((item, index) => ({
61
+ item,
62
+ busy: snapshot?.pendingIds.includes(item.id) ?? false,
63
+ ...(canEdit ? { onEdit: () => setEditing(item) } : {}),
64
+ onPreview: () => setLightboxIndex(index),
65
+ ...(canTrash
66
+ ? {
67
+ onTrash: () => {
68
+ void controller?.trash({ id: item.id }).then(saved => { if (saved) {
69
+ setSuccess(`Trashed ${item.title}`);
70
+ setFocusAfterAction({ id: item.id, index });
71
+ } });
72
+ },
73
+ }
74
+ : {}),
75
+ ...(canRestore ? { onRestore: () => { void controller?.restore({ id: item.id }).then(saved => { if (saved) {
76
+ setSuccess(`Restored ${item.title}`);
77
+ setFocusAfterAction({ id: item.id, index });
78
+ } }); } } : {}),
79
+ ...(canPurge ? { onPurge: () => controller?.requestPurge({ item }) } : {}),
80
+ }));
81
+ function closeEdit() {
82
+ setEditing(null);
83
+ }
84
+ async function saved({ message } = {}) {
85
+ const item = editing;
86
+ closeEdit();
87
+ // Reread the authoritative version after replacement before announcing completion;
88
+ // both card and lightbox obtain their versioned byte URL from the refreshed rows.
89
+ await controller?.load();
90
+ if (message)
91
+ setSuccess(message);
92
+ if (item)
93
+ setFocusAfterAction({ id: item.id, index: Math.max(0, items.findIndex(row => row.id === item.id)) });
94
+ }
95
+ return {
96
+ emptyLabel: filter === 'images' ? 'No images yet. Upload an image to see it here.'
97
+ : filter === 'videos' ? 'No videos yet. Upload a video to see it here.' : 'No media found',
98
+ canUpload,
99
+ success,
100
+ gridRef,
101
+ onRetry: () => { void controller?.load(); },
102
+ statusFilter: snapshot?.query.status ?? 'all',
103
+ onStatus: ({ value }) => {
104
+ const { status: _status, ...query } = controller?.getSnapshot().query ?? {};
105
+ void controller?.setQuery({ query: { ...query, ...(value === 'active' || value === 'trashed' ? { status: value } : {}) } });
106
+ },
107
+ canPurge,
108
+ controller,
109
+ snapshot,
110
+ actions,
111
+ items,
112
+ mediaApi,
113
+ editing,
114
+ closeEdit,
115
+ saved,
116
+ lightboxIndex,
117
+ onNavigate: setLightboxIndex,
118
+ closeLightbox: () => setLightboxIndex(null),
119
+ onSearch: ({ value: search }) => {
120
+ void controller?.setQuery({ query: { ...controller.getSnapshot().query, search } });
121
+ },
122
+ orderBy: snapshot?.query.orderBy ?? 'created',
123
+ onOrder: ({ value }) => {
124
+ void controller?.setQuery({ query: { ...controller.getSnapshot().query, orderBy: value === 'alphabetical' ? 'alphabetical' : 'created' } });
125
+ },
126
+ onOrderCreated: () => {
127
+ void controller?.setQuery({
128
+ query: { ...controller.getSnapshot().query, orderBy: 'created' },
129
+ });
130
+ },
131
+ onOrderAlphabetical: () => {
132
+ void controller?.setQuery({
133
+ query: { ...controller.getSnapshot().query, orderBy: 'alphabetical' },
134
+ });
135
+ },
136
+ search: snapshot?.query.search ?? '',
137
+ loading: !snapshot || (snapshot.items === null && snapshot.loading && !snapshot.error),
138
+ busy: snapshot?.busy ?? false,
139
+ untyped: filter !== 'all' && snapshot?.hasUntyped === true,
140
+ async upload({ input, alt }) {
141
+ if (!canUpload)
142
+ return false;
143
+ const result = await controller?.upload({ input, ...(alt === undefined ? {} : { alt }) }) ?? false;
144
+ if (result)
145
+ gridRef.current?.focus({ preventScroll: true });
146
+ return result;
147
+ },
148
+ cancelPurge: () => controller?.cancelPurge(),
149
+ confirmPurge: () => {
150
+ if (!canPurge || !controller)
151
+ return;
152
+ const item = controller.getSnapshot().pendingPurge;
153
+ const index = items.findIndex(row => row.id === item?.id);
154
+ return controller.confirmPurge({ confirmed: true }).then(saved => {
155
+ if (saved) {
156
+ setSuccess(item ? `Deleted permanently ${item.title}` : 'Deleted permanently');
157
+ setFocusAfterPurge(Math.max(0, index));
158
+ }
159
+ });
160
+ },
161
+ t: mediaMessagesEn,
162
+ };
163
+ }
164
+ //# sourceMappingURL=LibraryTab.hooks.js.map
@@ -0,0 +1,79 @@
1
+ import type { MediaAsset } from '../../models.js';
2
+ import type { MediaApiPort } from '../../ports.js';
3
+ export interface MediaCardProps {
4
+ readonly item: MediaAsset;
5
+ readonly handleBase?: string;
6
+ readonly api: MediaApiPort;
7
+ readonly busy?: boolean;
8
+ readonly onEdit?: () => void;
9
+ readonly onPreview?: () => void;
10
+ readonly onTrash?: () => void;
11
+ readonly onRestore?: () => void;
12
+ readonly onPurge?: () => void;
13
+ readonly onChoose?: () => void;
14
+ }
15
+ export declare function useMediaCard(props: MediaCardProps, _optional?: Record<string, never>): {
16
+ busy: boolean;
17
+ byteSize: string | null;
18
+ preview: () => void | undefined;
19
+ canPreview: boolean;
20
+ imagePreview: boolean;
21
+ handles: {
22
+ expand: string;
23
+ edit: string;
24
+ menu: string;
25
+ };
26
+ previewAttrs: {
27
+ 'data-jini-part': string;
28
+ 'data-agent-element': string;
29
+ 'data-agent-label': string;
30
+ 'aria-label': string;
31
+ };
32
+ editAttrs: {
33
+ 'data-jini-part': string;
34
+ 'data-agent-element': string;
35
+ 'data-agent-label': string;
36
+ 'aria-label': string;
37
+ };
38
+ menuLabel: string;
39
+ menuAttrs: {
40
+ 'data-agent-element': string;
41
+ 'data-agent-label': string;
42
+ };
43
+ menuItems: ({
44
+ id: string;
45
+ label: string;
46
+ onPress: () => void;
47
+ disabled: boolean;
48
+ attrs?: never;
49
+ } | {
50
+ id: string;
51
+ label: string;
52
+ attrs: {
53
+ 'data-jini-variant': string;
54
+ };
55
+ onPress: () => void;
56
+ disabled: boolean;
57
+ })[];
58
+ src: string | undefined;
59
+ stage: "image" | "video" | "unsupported";
60
+ image: boolean | "" | undefined;
61
+ video: boolean | "" | undefined;
62
+ onImageError: () => void;
63
+ onVideoError: () => void;
64
+ alt: string;
65
+ statusClassName: string;
66
+ statusLabel: "active" | "trashed";
67
+ statusTone: "success" | "warning";
68
+ trashed: boolean;
69
+ item: MediaAsset;
70
+ handleBase?: string;
71
+ api: MediaApiPort;
72
+ onEdit?: () => void;
73
+ onPreview?: () => void;
74
+ onTrash?: () => void;
75
+ onRestore?: () => void;
76
+ onPurge?: () => void;
77
+ onChoose?: () => void;
78
+ };
79
+ //# sourceMappingURL=MediaCard.hooks.d.ts.map
@@ -0,0 +1,63 @@
1
+ import { useState } from 'react';
2
+ import { safeMediaUrl, formatByteSize, mediaRowHandles } from '../../rules.js';
3
+ export function useMediaCard(props, _optional = {}) {
4
+ /** Historical preview rationale, retained with the ported fallback chain:
5
+ * The hard problem this rewrite had to solve: **the media list response carried no content type**
6
+ * (neither `media` nor `asset_blobs` stored one — upload validated `contentType` then discarded
7
+ * it), so nothing in `AdminMedia` told the client whether a given asset was an image, a video, or
8
+ * something unpreviewable. `MediaPreview` below resolves this client-side with an optimistic
9
+ * render-and-fall-back chain (`<img>` → onError → `<video>` → onError → placeholder) rather than a
10
+ * HEAD probe per card. Chosen over the HEAD approach because: (1) the byte route's documented
11
+ * contract covers GET — sniffing/Range were specified for that, not for HEAD, so building on HEAD
12
+ * would be assuming a behavior nobody confirmed; (2) a HEAD-first design means every card blocks on
13
+ * a round trip before any pixel paints, working against the fixed-aspect-box + lazy-loading this
14
+ * grid needs anyway, whereas the optimistic path costs nothing extra for the common case (a real
15
+ * image just loads) and only "wastes" a request for the video/unsupported minority — and even then,
16
+ * a browser's image decoder typically fails off the header bytes rather than pulling the whole
17
+ * file; (3) it composes for free with the server's security defusal: a sniffed HTML/SVG comes back
18
+ * as `application/octet-stream` with `Content-Disposition: attachment`, which is not a valid image
19
+ * OR video MIME, so it fails both probes and lands on the placeholder with zero special-casing —
20
+ * this file never needs to detect "is this the defused case" itself.
21
+ */
22
+ const src = safeMediaUrl({ url: props.api.originalUrl({ id: props.item.id, version: props.item.version }) });
23
+ const [probe, setProbe] = useState({ src, stage: 'image' });
24
+ // New bytes can change media type under the same id. Retry the fallback from image
25
+ // immediately when the versioned URL changes, including in an already-open lightbox.
26
+ const stage = probe.src === src ? probe.stage : 'image';
27
+ const handleBase = props.handleBase ?? mediaRowHandles({ media: [props.item] })[0];
28
+ return {
29
+ ...props,
30
+ busy: props.busy === true,
31
+ byteSize: props.item.byteSize === undefined ? null : formatByteSize({ bytes: props.item.byteSize }),
32
+ preview: () => props.onPreview?.(),
33
+ canPreview: !!props.onPreview && !!src && stage !== 'unsupported',
34
+ imagePreview: !!props.onPreview && !!src && stage === 'image',
35
+ handles: { expand: `${handleBase}-expand`, edit: `${handleBase}-edit`, menu: `${handleBase}-menu` },
36
+ previewAttrs: { 'data-jini-part': 'media.preview', 'data-agent-element': `${handleBase}-expand`,
37
+ 'data-agent-label': 'Open this asset larger in the lightbox', 'aria-label': `View "${props.item.title}" larger` },
38
+ editAttrs: { 'data-jini-part': 'media.edit', 'data-agent-element': `${handleBase}-edit`,
39
+ 'data-agent-label': 'Open the edit form for this asset as a modal', 'aria-label': `Edit "${props.item.title}"` },
40
+ menuLabel: `Actions for "${props.item.title}"`,
41
+ menuAttrs: { 'data-agent-element': `${handleBase}-menu`, 'data-agent-label': `Actions for "${props.item.title}"` },
42
+ menuItems: [
43
+ ...(props.onEdit ? [{ id: 'edit', label: 'Edit metadata', onPress: props.onEdit, disabled: props.busy === true }] : []),
44
+ ...(props.onTrash && props.item.status !== 'trashed' ? [{ id: 'trash', label: 'Trash', onPress: props.onTrash, disabled: props.busy === true }] : []),
45
+ // Restore is owner-requested beyond legacy; it lives only in a trashed card's menu, so
46
+ // the card itself keeps the legacy look and active cards' menus stay legacy-identical.
47
+ ...(props.onRestore && props.item.status === 'trashed' ? [{ id: 'restore', label: 'Restore', onPress: props.onRestore, disabled: props.busy === true }] : []),
48
+ ...(props.onPurge && props.item.status === 'trashed' ? [{ id: 'purge', label: 'Delete permanently', attrs: { 'data-jini-variant': 'danger' }, onPress: props.onPurge, disabled: props.busy === true }] : []),
49
+ ],
50
+ src,
51
+ stage,
52
+ image: src && stage === 'image',
53
+ video: src && stage === 'video',
54
+ onImageError: () => setProbe({ src, stage: 'video' }),
55
+ onVideoError: () => setProbe({ src, stage: 'unsupported' }),
56
+ alt: props.item.alt || props.item.title || 'Untitled asset',
57
+ statusClassName: `jini-status jini-status-${props.item.status}`,
58
+ statusLabel: props.item.status,
59
+ statusTone: props.item.status === 'trashed' ? 'warning' : 'success',
60
+ trashed: props.item.status === 'trashed',
61
+ };
62
+ }
63
+ //# sourceMappingURL=MediaCard.hooks.js.map
@@ -0,0 +1,10 @@
1
+ import type { RefObject } from 'react';
2
+ import type { DialogProps } from '@jini-ai/ui-kit/react';
3
+ export interface MediaDialogProps extends Omit<DialogProps, 'ref'> {
4
+ readonly dialogRef?: RefObject<HTMLDialogElement | null>;
5
+ }
6
+ export declare function useMediaDialog(props: MediaDialogProps, _optional?: Record<string, never>): {
7
+ open: boolean;
8
+ dialogProps: DialogProps;
9
+ };
10
+ //# sourceMappingURL=MediaDialog.hooks.d.ts.map
@@ -0,0 +1,20 @@
1
+ import { useLayoutEffect, useRef } from 'react';
2
+ export function useMediaDialog(props, _optional = {}) {
3
+ const localRef = useRef(null);
4
+ const ref = props.dialogRef ?? localRef;
5
+ useLayoutEffect(() => {
6
+ const dialog = ref.current;
7
+ if (!props.open || !dialog)
8
+ return;
9
+ // The kit default contributes a Close even when a feature provides its guarded,
10
+ // agent-addressable Cancel/Close. Hide only that known default marker; custom kit
11
+ // views keep their own structure. Retain the kit's modal/pending/focus lifecycle.
12
+ const duplicate = dialog.querySelector('[data-jini-part="kit.dialog-close"]');
13
+ if (duplicate)
14
+ duplicate.hidden = true;
15
+ dialog.querySelector('[data-jini-autofocus]')?.focus({ preventScroll: true });
16
+ dialog.scrollTop = 0;
17
+ }, [props.open, ref]);
18
+ return { open: props.open, dialogProps: { ...props, ref } };
19
+ }
20
+ //# sourceMappingURL=MediaDialog.hooks.js.map
@@ -0,0 +1,28 @@
1
+ import type { Ref } from 'react';
2
+ import type { MediaCardProps } from './MediaCard.hooks.js';
3
+ export interface MediaGridProps {
4
+ readonly gridRef?: Ref<HTMLDivElement>;
5
+ readonly actions: readonly Omit<MediaCardProps, 'api'>[];
6
+ readonly api: MediaCardProps['api'];
7
+ readonly busy?: boolean;
8
+ readonly emptyLabel?: string;
9
+ }
10
+ export declare function useMediaGrid(props: MediaGridProps, _optional?: Record<string, never>): {
11
+ actions: {
12
+ handleBase: string;
13
+ busy?: boolean;
14
+ item: import("../../models.js").MediaAsset;
15
+ onEdit?: () => void;
16
+ onPreview?: () => void;
17
+ onTrash?: () => void;
18
+ onRestore?: () => void;
19
+ onPurge?: () => void;
20
+ onChoose?: () => void;
21
+ }[];
22
+ gridRef?: Ref<HTMLDivElement>;
23
+ api: MediaCardProps["api"];
24
+ busy?: boolean;
25
+ emptyLabel?: string;
26
+ className: string;
27
+ };
28
+ //# sourceMappingURL=MediaGrid.hooks.d.ts.map