@antelopejs/dms 0.11.0 → 0.12.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 (1582) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/bin/control/base.mjs +78 -0
  3. package/bin/control/browser-client.mjs +44 -0
  4. package/bin/control/browser.mjs +291 -0
  5. package/bin/control/commands-stack.mjs +191 -0
  6. package/bin/control/commands-verify.mjs +185 -0
  7. package/bin/control/doctor.mjs +223 -0
  8. package/bin/control/git.mjs +35 -0
  9. package/bin/control/journey.mjs +380 -0
  10. package/bin/control/mail.mjs +163 -0
  11. package/bin/control/mongo.mjs +156 -0
  12. package/bin/control/processes.mjs +325 -0
  13. package/bin/control/run-state.mjs +111 -0
  14. package/bin/control/session.mjs +219 -0
  15. package/bin/control/stack.mjs +480 -0
  16. package/bin/control/tab.mjs +226 -0
  17. package/bin/control/verify/behaviour.mjs +145 -0
  18. package/bin/control/verify/behaviour.test.mjs +351 -0
  19. package/bin/control/verify/doors.mjs +44 -0
  20. package/bin/control/verify/emit.mjs +413 -0
  21. package/bin/control/verify/formal.mjs +208 -0
  22. package/bin/control/verify/formal.test.mjs +120 -0
  23. package/bin/control/verify/judgement.mjs +83 -0
  24. package/bin/control/verify/map.mjs +211 -0
  25. package/bin/control/verify/publish.mjs +180 -0
  26. package/bin/control/verify/seeded.mjs +168 -0
  27. package/bin/control/verify/skill.mjs +130 -0
  28. package/bin/control/verify/verdict.mjs +308 -0
  29. package/bin/dms-control.mjs +87 -0
  30. package/dist/attachments/access.d.ts +1 -1
  31. package/dist/attachments/access.js +2 -2
  32. package/dist/attachments/access.js.map +1 -1
  33. package/dist/attachments/bindings.js.map +1 -1
  34. package/dist/attachments/fields.d.ts +2 -2
  35. package/dist/attachments/fields.js.map +1 -1
  36. package/dist/attachments/index.d.ts +6 -0
  37. package/dist/attachments/index.js +23 -0
  38. package/dist/attachments/index.js.map +1 -0
  39. package/dist/attachments/read.js +3 -1
  40. package/dist/attachments/read.js.map +1 -1
  41. package/dist/attachments/registry.js +3 -3
  42. package/dist/attachments/registry.js.map +1 -1
  43. package/dist/attachments/save.d.ts +1 -1
  44. package/dist/attachments/save.js.map +1 -1
  45. package/dist/attachments/table-view.d.ts +2 -1
  46. package/dist/attachments/table-view.js +2 -2
  47. package/dist/attachments/table-view.js.map +1 -1
  48. package/dist/attachments/uploads.d.ts +1 -1
  49. package/dist/attachments/uploads.js +2 -2
  50. package/dist/attachments/uploads.js.map +1 -1
  51. package/dist/automation/actions.js.map +1 -1
  52. package/dist/automation/events.d.ts +2 -1
  53. package/dist/automation/events.js.map +1 -1
  54. package/dist/automation/index.d.ts +4 -0
  55. package/dist/automation/index.js +5 -1
  56. package/dist/automation/index.js.map +1 -1
  57. package/dist/automation/send-notification.js +2 -1
  58. package/dist/automation/send-notification.js.map +1 -1
  59. package/dist/automation/sources.js.map +1 -1
  60. package/dist/automation/triggers.js +9 -6
  61. package/dist/automation/triggers.js.map +1 -1
  62. package/dist/{client-origin-cors.js → config/client-origin-cors.js} +2 -2
  63. package/dist/config/client-origin-cors.js.map +1 -0
  64. package/dist/config/index.d.ts +1 -0
  65. package/dist/config/index.js +18 -0
  66. package/dist/config/index.js.map +1 -0
  67. package/dist/{config.d.ts → config/internal/state.d.ts} +1 -1
  68. package/dist/{config.js → config/internal/state.js} +1 -1
  69. package/dist/config/internal/state.js.map +1 -0
  70. package/dist/config/session-handoff.d.ts +1 -0
  71. package/dist/config/session-handoff.js +5 -0
  72. package/dist/config/session-handoff.js.map +1 -0
  73. package/dist/{startup-config.js → config/startup-config.js} +4 -4
  74. package/dist/config/startup-config.js.map +1 -0
  75. package/dist/crons/cleanup-user-invites.js.map +1 -1
  76. package/dist/crons/sweep-expired-sessions.js.map +1 -1
  77. package/dist/crons/sweep-stale-exports.js.map +1 -1
  78. package/dist/db/guard-row.d.ts +3 -0
  79. package/dist/db/guard-row.js +13 -0
  80. package/dist/db/guard-row.js.map +1 -0
  81. package/dist/db/index.d.ts +1 -0
  82. package/dist/db/index.js +1 -0
  83. package/dist/db/index.js.map +1 -1
  84. package/dist/db/models/index.d.ts +1 -0
  85. package/dist/db/models/index.js +1 -0
  86. package/dist/db/models/index.js.map +1 -1
  87. package/dist/db/models/notification-feed-filter.js +2 -1
  88. package/dist/db/models/notification-feed-filter.js.map +1 -1
  89. package/dist/db/models/signInAttempts.model.js.map +1 -1
  90. package/dist/db/models/userNotificationPreferences.model.js +2 -2
  91. package/dist/db/models/userNotificationPreferences.model.js.map +1 -1
  92. package/dist/db/models/userNotifications.model.js +3 -3
  93. package/dist/db/models/userNotifications.model.js.map +1 -1
  94. package/dist/db/tables/signInAttempts.table.d.ts +2 -1
  95. package/dist/db/tables/signInAttempts.table.js.map +1 -1
  96. package/dist/dev/index.d.ts +1 -0
  97. package/dist/dev/index.js +18 -0
  98. package/dist/dev/index.js.map +1 -0
  99. package/dist/dev/module-update-notifications.js +2 -2
  100. package/dist/dev/module-update-notifications.js.map +1 -1
  101. package/dist/frontend-module.js +4 -3
  102. package/dist/frontend-module.js.map +1 -1
  103. package/dist/hooks/index.d.ts +5 -0
  104. package/dist/hooks/index.js +22 -0
  105. package/dist/hooks/index.js.map +1 -0
  106. package/dist/{utils → hooks/internal}/sign-in-monitor.d.ts +1 -1
  107. package/dist/{utils → hooks/internal}/sign-in-monitor.js +17 -22
  108. package/dist/hooks/internal/sign-in-monitor.js.map +1 -0
  109. package/dist/{utils → hooks/internal}/workspace-notifications.js +24 -26
  110. package/dist/hooks/internal/workspace-notifications.js.map +1 -0
  111. package/dist/hooks/invite-extensions.js.map +1 -1
  112. package/dist/hooks/workspace-notifications.js +5 -2
  113. package/dist/hooks/workspace-notifications.js.map +1 -1
  114. package/dist/implementations/dms/attachments.d.ts +3 -3
  115. package/dist/implementations/dms/attachments.js +6 -6
  116. package/dist/implementations/dms/attachments.js.map +1 -1
  117. package/dist/implementations/dms/client-ip.js +2 -2
  118. package/dist/implementations/dms/client-ip.js.map +1 -1
  119. package/dist/implementations/dms/dev-handshake.js +2 -2
  120. package/dist/implementations/dms/dev-handshake.js.map +1 -1
  121. package/dist/implementations/dms/guards.js.map +1 -1
  122. package/dist/implementations/dms/invite-extensions.js +3 -3
  123. package/dist/implementations/dms/invite-extensions.js.map +1 -1
  124. package/dist/implementations/dms/layout-banners.d.ts +1 -1
  125. package/dist/implementations/dms/layout-banners.js +3 -3
  126. package/dist/implementations/dms/layout-banners.js.map +1 -1
  127. package/dist/implementations/dms/menu-categories.js.map +1 -1
  128. package/dist/implementations/dms/nav-badges.js.map +1 -1
  129. package/dist/implementations/dms/page/access.d.ts +16 -0
  130. package/dist/implementations/dms/page/access.js +162 -0
  131. package/dist/implementations/dms/page/access.js.map +1 -0
  132. package/dist/implementations/dms/page/controller.d.ts +21 -0
  133. package/dist/implementations/dms/page/controller.js +172 -0
  134. package/dist/implementations/dms/page/controller.js.map +1 -0
  135. package/dist/implementations/dms/page/dynamic-menu.d.ts +32 -0
  136. package/dist/implementations/dms/page/dynamic-menu.js +241 -0
  137. package/dist/implementations/dms/page/dynamic-menu.js.map +1 -0
  138. package/dist/implementations/dms/page/module-catalog.d.ts +13 -0
  139. package/dist/implementations/dms/page/module-catalog.js +115 -0
  140. package/dist/implementations/dms/page/module-catalog.js.map +1 -0
  141. package/dist/implementations/dms/page/notifications.d.ts +13 -0
  142. package/dist/implementations/dms/page/notifications.js +80 -0
  143. package/dist/implementations/dms/page/notifications.js.map +1 -0
  144. package/dist/implementations/dms/page/payloads.d.ts +24 -0
  145. package/dist/implementations/dms/page/payloads.js +162 -0
  146. package/dist/implementations/dms/page/payloads.js.map +1 -0
  147. package/dist/implementations/dms/page/preview-cache.d.ts +9 -0
  148. package/dist/implementations/dms/page/preview-cache.js +19 -0
  149. package/dist/implementations/dms/page/preview-cache.js.map +1 -0
  150. package/dist/implementations/dms/page/preview-menu.d.ts +16 -0
  151. package/dist/implementations/dms/page/preview-menu.js +210 -0
  152. package/dist/implementations/dms/page/preview-menu.js.map +1 -0
  153. package/dist/implementations/dms/page/preview-models.d.ts +13 -0
  154. package/dist/implementations/dms/page/preview-models.js +47 -0
  155. package/dist/implementations/dms/page/preview-models.js.map +1 -0
  156. package/dist/implementations/dms/page/preview-pages.d.ts +17 -0
  157. package/dist/implementations/dms/page/preview-pages.js +96 -0
  158. package/dist/implementations/dms/page/preview-pages.js.map +1 -0
  159. package/dist/implementations/dms/page/quick-action-access.d.ts +12 -0
  160. package/dist/implementations/dms/page/quick-action-access.js +114 -0
  161. package/dist/implementations/dms/page/quick-action-access.js.map +1 -0
  162. package/dist/implementations/dms/page/registry.d.ts +50 -0
  163. package/dist/implementations/dms/page/registry.js +305 -0
  164. package/dist/implementations/dms/page/registry.js.map +1 -0
  165. package/dist/implementations/dms/page/state.d.ts +10 -0
  166. package/dist/implementations/dms/page/state.js +20 -0
  167. package/dist/implementations/dms/page/state.js.map +1 -0
  168. package/dist/implementations/dms/page/types.d.ts +148 -0
  169. package/dist/implementations/dms/page/types.js +3 -0
  170. package/dist/implementations/dms/page/types.js.map +1 -0
  171. package/dist/implementations/dms/page.d.ts +38 -144
  172. package/dist/implementations/dms/page.js +32 -1570
  173. package/dist/implementations/dms/page.js.map +1 -1
  174. package/dist/implementations/dms/permission-preview.js +4 -6
  175. package/dist/implementations/dms/permission-preview.js.map +1 -1
  176. package/dist/implementations/dms/permissions.js.map +1 -1
  177. package/dist/implementations/dms/realtime.js.map +1 -1
  178. package/dist/implementations/dms/resolver-timeout.js.map +1 -1
  179. package/dist/implementations/dms/route-params.js.map +1 -1
  180. package/dist/implementations/dms/services.d.ts +3 -0
  181. package/dist/implementations/dms/services.js +20 -0
  182. package/dist/implementations/dms/services.js.map +1 -0
  183. package/dist/implementations/dms/uploads.d.ts +1 -1
  184. package/dist/implementations/dms/uploads.js +4 -4
  185. package/dist/implementations/dms/uploads.js.map +1 -1
  186. package/dist/implementations/dms-auth/email-templates.d.ts +9 -0
  187. package/dist/implementations/dms-auth/email-templates.js +7 -0
  188. package/dist/implementations/dms-auth/email-templates.js.map +1 -0
  189. package/dist/implementations/dms-auth/index.d.ts +3 -3
  190. package/dist/implementations/dms-auth/index.js +20 -18
  191. package/dist/implementations/dms-auth/index.js.map +1 -1
  192. package/dist/implementations/dms-auth/services.d.ts +2 -0
  193. package/dist/implementations/dms-auth/services.js +19 -0
  194. package/dist/implementations/dms-auth/services.js.map +1 -0
  195. package/dist/implementations/dms-auth/session-handoff.js +3 -4
  196. package/dist/implementations/dms-auth/session-handoff.js.map +1 -1
  197. package/dist/implementations/dms-auth/token-session.d.ts +1 -1
  198. package/dist/implementations/dms-auth/token-session.js.map +1 -1
  199. package/dist/implementations/dms-base/bulk-selection.d.ts +4 -1
  200. package/dist/implementations/dms-base/bulk-selection.js +2 -2
  201. package/dist/implementations/dms-base/bulk-selection.js.map +1 -1
  202. package/dist/implementations/dms-base/export-jobs.d.ts +2 -2
  203. package/dist/implementations/dms-base/export-jobs.js +9 -9
  204. package/dist/implementations/dms-base/export-jobs.js.map +1 -1
  205. package/dist/implementations/dms-base/filter-tokens.js.map +1 -1
  206. package/dist/implementations/dms-base/footer-summary.d.ts +3 -2
  207. package/dist/implementations/dms-base/footer-summary.js +14 -8
  208. package/dist/implementations/dms-base/footer-summary.js.map +1 -1
  209. package/dist/implementations/dms-base/search-route.d.ts +2 -2
  210. package/dist/implementations/dms-base/search-route.js.map +1 -1
  211. package/dist/implementations/dms-base/services.d.ts +3 -0
  212. package/dist/implementations/dms-base/services.js +20 -0
  213. package/dist/implementations/dms-base/services.js.map +1 -0
  214. package/dist/implementations/dms-base/table-view.d.ts +3 -2
  215. package/dist/implementations/dms-base/table-view.js +6 -10
  216. package/dist/implementations/dms-base/table-view.js.map +1 -1
  217. package/dist/implementations/dms-base/tenant-export-archive.d.ts +1 -1
  218. package/dist/implementations/dms-base/tenant-export-archive.js +3 -3
  219. package/dist/implementations/dms-base/tenant-export-archive.js.map +1 -1
  220. package/dist/implementations/dms-html-render/index.js +3 -3
  221. package/dist/implementations/dms-html-render/index.js.map +1 -1
  222. package/dist/implementations/dms-html-render/service-jwt.js.map +1 -1
  223. package/dist/implementations/dms-html-render/services.d.ts +1 -0
  224. package/dist/implementations/dms-html-render/services.js +18 -0
  225. package/dist/implementations/dms-html-render/services.js.map +1 -0
  226. package/dist/implementations/dms-notifications/delivery-dedupe.js.map +1 -1
  227. package/dist/implementations/dms-notifications/delivery-guard.js.map +1 -1
  228. package/dist/implementations/dms-notifications/index.d.ts +2 -2
  229. package/dist/implementations/dms-notifications/index.js +22 -24
  230. package/dist/implementations/dms-notifications/index.js.map +1 -1
  231. package/dist/implementations/dms-notifications/services.d.ts +2 -0
  232. package/dist/implementations/dms-notifications/services.js +19 -0
  233. package/dist/implementations/dms-notifications/services.js.map +1 -0
  234. package/dist/index.d.ts +1 -0
  235. package/dist/index.js +25 -28
  236. package/dist/index.js.map +1 -1
  237. package/dist/page-extensions/index.d.ts +1 -0
  238. package/dist/page-extensions/index.js +18 -0
  239. package/dist/page-extensions/index.js.map +1 -0
  240. package/dist/page-extensions/pending-report.js.map +1 -1
  241. package/dist/pages/account.d.ts +13 -0
  242. package/dist/pages/account.js +30 -0
  243. package/dist/pages/account.js.map +1 -0
  244. package/dist/pages/members.d.ts +9 -0
  245. package/dist/pages/members.js +26 -0
  246. package/dist/pages/members.js.map +1 -0
  247. package/dist/pages/permissions.d.ts +5 -0
  248. package/dist/pages/permissions.js +22 -0
  249. package/dist/pages/permissions.js.map +1 -0
  250. package/dist/pages/preview.d.ts +2 -0
  251. package/dist/pages/preview.js +19 -0
  252. package/dist/pages/preview.js.map +1 -0
  253. package/dist/pages/public/index.d.ts +1 -1
  254. package/dist/pages/public/index.js +1 -1
  255. package/dist/pages/public/index.js.map +1 -1
  256. package/dist/pages/public/preview/block-types.d.ts +2 -1
  257. package/dist/pages/public/preview/fixtures.js.map +1 -1
  258. package/dist/pages/public/preview/index.js.map +1 -1
  259. package/dist/pages/settings/overview/account-summary.js.map +1 -1
  260. package/dist/pages/settings/settings-index.js.map +1 -1
  261. package/dist/pages/settings/users/account-activity-feed.js.map +1 -1
  262. package/dist/pages/settings/users/account-activity-store.js.map +1 -1
  263. package/dist/pages/settings/users/account-activity.js +11 -9
  264. package/dist/pages/settings/users/account-activity.js.map +1 -1
  265. package/dist/pages/settings/users/account-credentials.d.ts +2 -1
  266. package/dist/pages/settings/users/account-credentials.js +10 -11
  267. package/dist/pages/settings/users/account-credentials.js.map +1 -1
  268. package/dist/pages/settings/users/account-data-store.d.ts +2 -1
  269. package/dist/pages/settings/users/account-data-store.js +4 -4
  270. package/dist/pages/settings/users/account-data-store.js.map +1 -1
  271. package/dist/pages/settings/users/account-data.js.map +1 -1
  272. package/dist/pages/settings/users/category.js.map +1 -1
  273. package/dist/pages/settings/users/current-password.js +8 -8
  274. package/dist/pages/settings/users/current-password.js.map +1 -1
  275. package/dist/pages/settings/users/email-change.d.ts +3 -2
  276. package/dist/pages/settings/users/email-change.js +17 -19
  277. package/dist/pages/settings/users/email-change.js.map +1 -1
  278. package/dist/pages/settings/users/invite-extension-routes.d.ts +2 -1
  279. package/dist/pages/settings/users/invite-extension-routes.js.map +1 -1
  280. package/dist/pages/settings/users/invite-resend.js.map +1 -1
  281. package/dist/pages/settings/users/invites.js +2 -2
  282. package/dist/pages/settings/users/invites.js.map +1 -1
  283. package/dist/pages/settings/users/member-change-notifications.js +6 -6
  284. package/dist/pages/settings/users/member-change-notifications.js.map +1 -1
  285. package/dist/pages/settings/users/member-invite-batch.d.ts +1 -1
  286. package/dist/pages/settings/users/member-invite-batch.js +3 -3
  287. package/dist/pages/settings/users/member-invite-batch.js.map +1 -1
  288. package/dist/pages/settings/users/member-invite-form.js +3 -3
  289. package/dist/pages/settings/users/member-invite-form.js.map +1 -1
  290. package/dist/pages/settings/users/member-roles-field.js.map +1 -1
  291. package/dist/pages/settings/users/members.d.ts +3 -2
  292. package/dist/pages/settings/users/members.js +7 -8
  293. package/dist/pages/settings/users/members.js.map +1 -1
  294. package/dist/pages/settings/users/notifications.d.ts +3 -2
  295. package/dist/pages/settings/users/notifications.js +7 -7
  296. package/dist/pages/settings/users/notifications.js.map +1 -1
  297. package/dist/pages/settings/users/permission-tree-nodes.js.map +1 -1
  298. package/dist/pages/settings/users/profile-access.js.map +1 -1
  299. package/dist/pages/settings/users/profile-helpers.js.map +1 -1
  300. package/dist/pages/settings/users/profile.d.ts +3 -3
  301. package/dist/pages/settings/users/profile.js +2 -3
  302. package/dist/pages/settings/users/profile.js.map +1 -1
  303. package/dist/pages/settings/users/quick-actions.js.map +1 -1
  304. package/dist/pages/settings/users/region-form.js.map +1 -1
  305. package/dist/pages/settings/users/region.d.ts +3 -1
  306. package/dist/pages/settings/users/region.js +2 -2
  307. package/dist/pages/settings/users/region.js.map +1 -1
  308. package/dist/pages/settings/users/regional-preferences.d.ts +1 -1
  309. package/dist/pages/settings/users/regional-preferences.js +2 -1
  310. package/dist/pages/settings/users/regional-preferences.js.map +1 -1
  311. package/dist/pages/settings/users/role-editor-store.d.ts +1 -1
  312. package/dist/pages/settings/users/role-editor-store.js +4 -4
  313. package/dist/pages/settings/users/role-editor-store.js.map +1 -1
  314. package/dist/pages/settings/users/role-editor.js.map +1 -1
  315. package/dist/pages/settings/users/role-preview.d.ts +1 -1
  316. package/dist/pages/settings/users/role-preview.js.map +1 -1
  317. package/dist/pages/settings/users/roles.d.ts +5 -4
  318. package/dist/pages/settings/users/roles.js +7 -7
  319. package/dist/pages/settings/users/roles.js.map +1 -1
  320. package/dist/pages/settings/users/security-attention.js +2 -2
  321. package/dist/pages/settings/users/security-attention.js.map +1 -1
  322. package/dist/pages/settings/users/security.d.ts +12 -9
  323. package/dist/pages/settings/users/security.js.map +1 -1
  324. package/dist/pages/settings/users/two-factor-operations.d.ts +9 -6
  325. package/dist/pages/settings/users/two-factor-operations.js +21 -23
  326. package/dist/pages/settings/users/two-factor-operations.js.map +1 -1
  327. package/dist/realtime/broker.js.map +1 -1
  328. package/dist/realtime/current.js.map +1 -1
  329. package/dist/realtime/index.d.ts +4 -4
  330. package/dist/realtime/index.js +2 -0
  331. package/dist/realtime/index.js.map +1 -1
  332. package/dist/realtime/presence.js +21 -12
  333. package/dist/realtime/presence.js.map +1 -1
  334. package/dist/realtime/redis-broker.js +2 -0
  335. package/dist/realtime/redis-broker.js.map +1 -1
  336. package/dist/realtime/registry.js.map +1 -1
  337. package/dist/realtime/sessions.js.map +1 -1
  338. package/dist/realtime/sse.js.map +1 -1
  339. package/dist/realtime/table-view/index.d.ts +1 -0
  340. package/dist/realtime/table-view/index.js +18 -0
  341. package/dist/realtime/table-view/index.js.map +1 -0
  342. package/dist/realtime/table-view.js.map +1 -1
  343. package/dist/routes/auth/forgot-password.d.ts +2 -1
  344. package/dist/routes/auth/forgot-password.js +4 -4
  345. package/dist/routes/auth/forgot-password.js.map +1 -1
  346. package/dist/routes/auth/index.d.ts +2 -2
  347. package/dist/routes/auth/index.js +2 -2
  348. package/dist/routes/auth/index.js.map +1 -1
  349. package/dist/routes/auth/login.d.ts +3 -2
  350. package/dist/routes/auth/login.js +9 -9
  351. package/dist/routes/auth/login.js.map +1 -1
  352. package/dist/routes/auth/logout.d.ts +2 -1
  353. package/dist/routes/auth/logout.js +4 -4
  354. package/dist/routes/auth/logout.js.map +1 -1
  355. package/dist/routes/auth/oauth/callback.d.ts +1 -1
  356. package/dist/routes/auth/oauth/callback.js +4 -4
  357. package/dist/routes/auth/oauth/callback.js.map +1 -1
  358. package/dist/routes/auth/oauth/config.js +1 -1
  359. package/dist/routes/auth/oauth/config.js.map +1 -1
  360. package/dist/routes/auth/oauth/identity-resolution.js +3 -3
  361. package/dist/routes/auth/oauth/identity-resolution.js.map +1 -1
  362. package/dist/routes/auth/oauth/linking-policy.js.map +1 -1
  363. package/dist/routes/auth/oauth/providers.js +1 -1
  364. package/dist/routes/auth/oauth/providers.js.map +1 -1
  365. package/dist/routes/auth/oauth/state.js +9 -1
  366. package/dist/routes/auth/oauth/state.js.map +1 -1
  367. package/dist/routes/auth/oauth/token-exchange.js +1 -1
  368. package/dist/routes/auth/oauth/token-exchange.js.map +1 -1
  369. package/dist/routes/auth/refresh.d.ts +2 -1
  370. package/dist/routes/auth/refresh.js +5 -5
  371. package/dist/routes/auth/refresh.js.map +1 -1
  372. package/dist/routes/auth/request-2fa-email.d.ts +2 -1
  373. package/dist/routes/auth/request-2fa-email.js +4 -5
  374. package/dist/routes/auth/request-2fa-email.js.map +1 -1
  375. package/dist/routes/auth/reset-code.js +2 -2
  376. package/dist/routes/auth/reset-code.js.map +1 -1
  377. package/dist/routes/auth/reset-password.d.ts +2 -1
  378. package/dist/routes/auth/reset-password.js +6 -6
  379. package/dist/routes/auth/reset-password.js.map +1 -1
  380. package/dist/routes/auth/session-handoff.d.ts +2 -1
  381. package/dist/routes/auth/session-handoff.js +4 -4
  382. package/dist/routes/auth/session-handoff.js.map +1 -1
  383. package/dist/routes/auth/session-response.d.ts +1 -1
  384. package/dist/routes/auth/session-response.js +2 -2
  385. package/dist/routes/auth/session-response.js.map +1 -1
  386. package/dist/routes/auth/signup.d.ts +3 -2
  387. package/dist/routes/auth/signup.js +7 -7
  388. package/dist/routes/auth/signup.js.map +1 -1
  389. package/dist/routes/auth/switch-tenant.d.ts +13 -1
  390. package/dist/routes/auth/switch-tenant.js.map +1 -1
  391. package/dist/routes/auth/two-factor-throttle.js +9 -9
  392. package/dist/routes/auth/two-factor-throttle.js.map +1 -1
  393. package/dist/routes/auth/validate-forgot-password-token.d.ts +2 -1
  394. package/dist/routes/auth/validate-forgot-password-token.js +2 -2
  395. package/dist/routes/auth/validate-forgot-password-token.js.map +1 -1
  396. package/dist/routes/auth/validate-invite-token.d.ts +2 -1
  397. package/dist/routes/auth/validate-invite-token.js +2 -2
  398. package/dist/routes/auth/validate-invite-token.js.map +1 -1
  399. package/dist/routes/auth/verify-2fa.d.ts +3 -2
  400. package/dist/routes/auth/verify-2fa.js +10 -12
  401. package/dist/routes/auth/verify-2fa.js.map +1 -1
  402. package/dist/routes/auth/verify-email.d.ts +2 -1
  403. package/dist/routes/auth/verify-email.js +2 -2
  404. package/dist/routes/auth/verify-email.js.map +1 -1
  405. package/dist/routes/auth.d.ts +15 -14
  406. package/dist/routes/auth.js +2 -2
  407. package/dist/routes/auth.js.map +1 -1
  408. package/dist/routes/authentication.d.ts +3 -0
  409. package/dist/routes/authentication.js +20 -0
  410. package/dist/routes/authentication.js.map +1 -0
  411. package/dist/routes/block-preview.d.ts +1 -1
  412. package/dist/routes/block-preview.js +2 -2
  413. package/dist/routes/block-preview.js.map +1 -1
  414. package/dist/routes/files.d.ts +2 -1
  415. package/dist/routes/files.js +9 -11
  416. package/dist/routes/files.js.map +1 -1
  417. package/dist/routes/oauth-config.d.ts +1 -0
  418. package/dist/routes/oauth-config.js +18 -0
  419. package/dist/routes/oauth-config.js.map +1 -0
  420. package/dist/routes/oauth.d.ts +7 -0
  421. package/dist/routes/oauth.js +24 -0
  422. package/dist/routes/oauth.js.map +1 -0
  423. package/dist/routes/onboarding.d.ts +2 -1
  424. package/dist/routes/onboarding.js +2 -2
  425. package/dist/routes/onboarding.js.map +1 -1
  426. package/dist/routes/realtime.js +19 -20
  427. package/dist/routes/realtime.js.map +1 -1
  428. package/dist/routes/store.d.ts +8 -7
  429. package/dist/routes/store.js +9 -10
  430. package/dist/routes/store.js.map +1 -1
  431. package/dist/routes/system-state.js.map +1 -1
  432. package/dist/store/catalog.d.ts +7 -2
  433. package/dist/store/catalog.js +2 -4
  434. package/dist/store/catalog.js.map +1 -1
  435. package/dist/store/compatibility.js.map +1 -1
  436. package/dist/store/declarations.js +3 -3
  437. package/dist/store/declarations.js.map +1 -1
  438. package/dist/store/frontend-compatibility.js +3 -5
  439. package/dist/store/frontend-compatibility.js.map +1 -1
  440. package/dist/store/frontend.d.ts +6 -0
  441. package/dist/store/frontend.js +23 -0
  442. package/dist/store/frontend.js.map +1 -0
  443. package/dist/store/index.d.ts +10 -0
  444. package/dist/store/index.js +27 -0
  445. package/dist/store/index.js.map +1 -0
  446. package/dist/store/interfaces.js +5 -6
  447. package/dist/store/interfaces.js.map +1 -1
  448. package/dist/store/internal/frontend/dev-reload.js.map +1 -0
  449. package/dist/store/internal/frontend/frontend-backend-proxies.js.map +1 -0
  450. package/dist/{implementations/dms → store/internal/frontend}/frontend-bootstrap.d.ts +1 -1
  451. package/dist/{implementations/dms → store/internal/frontend}/frontend-bootstrap.js +1 -1
  452. package/dist/store/internal/frontend/frontend-bootstrap.js.map +1 -0
  453. package/dist/{implementations/dms → store/internal/frontend}/frontend-modules.js +5 -5
  454. package/dist/store/internal/frontend/frontend-modules.js.map +1 -0
  455. package/dist/store/internal/frontend/frontend-public-endpoints.js.map +1 -0
  456. package/dist/store/internal/frontend/frontend-ready.d.ts +45 -0
  457. package/dist/store/internal/frontend/frontend-ready.js.map +1 -0
  458. package/dist/{implementations/dms → store/internal/frontend}/manifest.d.ts +6 -5
  459. package/dist/{implementations/dms → store/internal/frontend}/manifest.js +7 -7
  460. package/dist/store/internal/frontend/manifest.js.map +1 -0
  461. package/dist/store/internal/frontend/warn-once.js.map +1 -0
  462. package/dist/store/listing.js +2 -2
  463. package/dist/store/listing.js.map +1 -1
  464. package/dist/store/operations.js +1 -1
  465. package/dist/store/operations.js.map +1 -1
  466. package/dist/store/registry.js +2 -1
  467. package/dist/store/registry.js.map +1 -1
  468. package/dist/store/runtime.js.map +1 -1
  469. package/dist/types/index.d.ts +2 -0
  470. package/dist/types/index.js +19 -0
  471. package/dist/types/index.js.map +1 -0
  472. package/dist/types/realtime.d.ts +4 -0
  473. package/dist/types/realtime.js +3 -0
  474. package/dist/types/realtime.js.map +1 -0
  475. package/dist/types/sign-in-attempt.d.ts +1 -0
  476. package/dist/types/sign-in-attempt.js +3 -0
  477. package/dist/types/sign-in-attempt.js.map +1 -0
  478. package/dist/utils/account-notifications.js.map +1 -1
  479. package/dist/utils/admin-invite-email.js.map +1 -1
  480. package/dist/utils/attempt-limiter.js.map +1 -1
  481. package/dist/{routes/auth/constants.js → utils/auth-constants.js} +1 -1
  482. package/dist/utils/auth-constants.js.map +1 -0
  483. package/dist/utils/client-ip/index.d.ts +1 -0
  484. package/dist/utils/client-ip/index.js +18 -0
  485. package/dist/utils/client-ip/index.js.map +1 -0
  486. package/dist/{routes/auth → utils}/client-ip.d.ts +1 -1
  487. package/dist/utils/client-ip.js.map +1 -0
  488. package/dist/utils/email-subjects.js.map +1 -1
  489. package/dist/utils/export-jobs-run.js +1 -2
  490. package/dist/utils/export-jobs-run.js.map +1 -1
  491. package/dist/utils/export-jobs.js.map +1 -1
  492. package/dist/utils/failed-sign-ins.d.ts +1 -1
  493. package/dist/utils/failed-sign-ins.js.map +1 -1
  494. package/dist/utils/index.d.ts +26 -0
  495. package/dist/utils/index.js +26 -0
  496. package/dist/utils/index.js.map +1 -1
  497. package/dist/utils/jwt-claims.d.ts +2 -0
  498. package/dist/utils/jwt-claims.js +7 -0
  499. package/dist/utils/jwt-claims.js.map +1 -0
  500. package/dist/{routes/auth → utils}/login-throttle.js +1 -1
  501. package/dist/utils/login-throttle.js.map +1 -0
  502. package/dist/utils/notification-registry/index.d.ts +1 -0
  503. package/dist/utils/notification-registry/index.js +18 -0
  504. package/dist/utils/notification-registry/index.js.map +1 -0
  505. package/dist/{implementations/dms-notifications/registry.js → utils/notification-registry.js} +1 -1
  506. package/dist/utils/notification-registry.js.map +1 -0
  507. package/dist/utils/notification-rules.js.map +1 -1
  508. package/dist/utils/notification-tones.js.map +1 -1
  509. package/dist/utils/one-time-code.js.map +1 -1
  510. package/dist/utils/page-access.d.ts +13 -0
  511. package/dist/utils/page-access.js +56 -0
  512. package/dist/utils/page-access.js.map +1 -0
  513. package/dist/utils/request-email-verification/index.d.ts +1 -0
  514. package/dist/utils/request-email-verification/index.js +18 -0
  515. package/dist/utils/request-email-verification/index.js.map +1 -0
  516. package/dist/{routes/auth → utils}/request-email-verification.js +1 -1
  517. package/dist/utils/request-email-verification.js.map +1 -0
  518. package/dist/utils/row-action-rule-evaluator.js.map +1 -1
  519. package/dist/utils/run-in-batches/index.d.ts +1 -0
  520. package/dist/utils/run-in-batches/index.js +18 -0
  521. package/dist/utils/run-in-batches/index.js.map +1 -0
  522. package/dist/utils/sign-in-country.js +1 -1
  523. package/dist/utils/sign-in-country.js.map +1 -1
  524. package/dist/utils/sign-in-devices.js.map +1 -1
  525. package/dist/utils/tenant-export-archive.js.map +1 -1
  526. package/dist/utils/tenant-instances.js.map +1 -1
  527. package/dist/utils/two-factor-codes.js +3 -3
  528. package/dist/utils/two-factor-codes.js.map +1 -1
  529. package/dist/utils/upload-constraints.js.map +1 -1
  530. package/dist/utils/upload-token.js +2 -1
  531. package/dist/utils/upload-token.js.map +1 -1
  532. package/dist/utils/user-activity.js.map +1 -1
  533. package/dist/utils/user-agent.js.map +1 -1
  534. package/dist/validation/auth.schema.d.ts +16 -16
  535. package/dist/validation/auth.schema.js.map +1 -1
  536. package/dist/validation/file.schema.d.ts +2 -2
  537. package/dist/validation/file.schema.js.map +1 -1
  538. package/dist/validation/index.d.ts +12 -0
  539. package/dist/validation/index.js +29 -0
  540. package/dist/validation/index.js.map +1 -0
  541. package/dist/validation/issue-message.js.map +1 -1
  542. package/dist/validation/member-invite.schema.js.map +1 -1
  543. package/dist/validation/onboarding/register-admin.schema.d.ts +3 -3
  544. package/dist/validation/security.schema.js.map +1 -1
  545. package/frontend-vue/build/backend-boundary.ts +91 -0
  546. package/frontend-vue/dms.frontend.build.ts +2 -2
  547. package/frontend-vue/dms.frontend.ts +31 -37
  548. package/frontend-vue/dms.server.ts +6 -21
  549. package/frontend-vue/eslint-test-quality.mjs +62 -0
  550. package/frontend-vue/layers/dms-auth/app/build/components/AuthNewPasswordField.vue +1 -1
  551. package/frontend-vue/layers/dms-auth/app/build/composables/useAuthFormError.ts +12 -6
  552. package/frontend-vue/layers/dms-auth/app/build/utils/authStyles.ts +1 -1
  553. package/frontend-vue/layers/dms-auth/app/components/OAuthButtons.vue +4 -2
  554. package/frontend-vue/layers/dms-auth/app/composables/useOAuthErrorToast.ts +6 -2
  555. package/frontend-vue/layers/dms-auth/app/composables/usePostLoginRedirect.ts +6 -4
  556. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/2fa.vue +5 -9
  557. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/accounts.vue +2 -2
  558. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/backup.vue +2 -6
  559. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/forgot-validation.vue +6 -8
  560. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/forgot.vue +1 -2
  561. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/login.vue +6 -10
  562. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/oauth-complete.vue +20 -20
  563. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/recover-success.vue +1 -1
  564. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/recover.vue +1 -2
  565. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/signup.vue +18 -22
  566. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/validate.vue +5 -7
  567. package/frontend-vue/layers/dms-auth/app/entries/component-registry.ts +12 -0
  568. package/frontend-vue/layers/dms-auth/app/entries/components/AuthFormAlert.ts +2 -0
  569. package/frontend-vue/layers/dms-auth/app/entries/components/AuthNewPasswordField.ts +2 -0
  570. package/frontend-vue/layers/dms-auth/app/entries/composables/useAuthFormError.ts +1 -0
  571. package/frontend-vue/layers/dms-auth/app/entries/server/accounts.ts +1 -0
  572. package/frontend-vue/layers/dms-auth/app/entries/server/actions.ts +1 -0
  573. package/frontend-vue/layers/dms-auth/app/entries/server/oauth.ts +1 -0
  574. package/frontend-vue/layers/dms-auth/app/entries/server/session.ts +1 -0
  575. package/frontend-vue/layers/dms-auth/app/middleware/auth.ts +5 -7
  576. package/frontend-vue/layers/dms-auth/server/accounts.ts +10 -5
  577. package/frontend-vue/layers/dms-auth/server/actions.ts +9 -10
  578. package/frontend-vue/layers/dms-auth/server/oauth.ts +15 -18
  579. package/frontend-vue/layers/dms-auth/server/session.ts +5 -2
  580. package/frontend-vue/layers/dms-auth/shared/oauth.ts +6 -2
  581. package/frontend-vue/layers/dms-core/app/build/composables/auth/usePermissionPreview.ts +53 -46
  582. package/frontend-vue/layers/dms-core/app/build/composables/renderNow.ts +2 -1
  583. package/frontend-vue/layers/dms-core/app/build/composables/user/preferencesCookie.ts +15 -7
  584. package/frontend-vue/layers/dms-core/app/build/composables/user/tablePreferences.ts +49 -34
  585. package/frontend-vue/layers/dms-core/app/build/utils/crossTab.ts +9 -8
  586. package/frontend-vue/layers/dms-core/app/build/utils/permission-preview.ts +10 -13
  587. package/frontend-vue/layers/dms-core/app/build/utils/sharedRealtimeConnection.ts +17 -13
  588. package/frontend-vue/layers/dms-core/app/composables/auth/useApiData.ts +4 -7
  589. package/frontend-vue/layers/dms-core/app/composables/auth/useAuthFetch.ts +38 -16
  590. package/frontend-vue/layers/dms-core/app/composables/auth/useMultiAccount.ts +8 -16
  591. package/frontend-vue/layers/dms-core/app/composables/auth/usePermissions.ts +1 -15
  592. package/frontend-vue/layers/dms-core/app/composables/auth/useSessionRecovery.ts +3 -8
  593. package/frontend-vue/layers/dms-core/app/composables/components/useComponentEvent.ts +5 -1
  594. package/frontend-vue/layers/dms-core/app/composables/data-types/useDataType.ts +5 -1
  595. package/frontend-vue/layers/dms-core/app/composables/functions/useDefinedFunction.ts +7 -1
  596. package/frontend-vue/layers/{dms-layout → dms-core}/app/composables/page/useSiteLayout.ts +113 -110
  597. package/frontend-vue/layers/dms-core/app/composables/period/compareResolvers.ts +1 -7
  598. package/frontend-vue/layers/dms-core/app/composables/period/periodClock.ts +2 -3
  599. package/frontend-vue/layers/dms-core/app/composables/period/periodLink.ts +16 -14
  600. package/frontend-vue/layers/dms-core/app/composables/period/presetResolvers.ts +0 -2
  601. package/frontend-vue/layers/dms-core/app/composables/period/usePeriod.ts +1 -3
  602. package/frontend-vue/layers/dms-core/app/composables/period/usePeriodScope.ts +0 -2
  603. package/frontend-vue/layers/dms-core/app/composables/realtime/usePageRealtime.ts +0 -1
  604. package/frontend-vue/layers/dms-core/app/composables/realtime/useSseStream.ts +8 -5
  605. package/frontend-vue/layers/dms-core/app/composables/realtime/useUserRealtime.ts +58 -65
  606. package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +0 -1
  607. package/frontend-vue/layers/dms-core/app/composables/translation/useTranslation.ts +15 -12
  608. package/frontend-vue/layers/dms-core/app/composables/useApiError.ts +19 -12
  609. package/frontend-vue/layers/dms-core/app/composables/useEventedAction.ts +10 -4
  610. package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +93 -73
  611. package/frontend-vue/layers/dms-core/app/composables/useFormValidation.ts +31 -14
  612. package/frontend-vue/layers/dms-core/app/composables/useTrailingDeduper.ts +5 -4
  613. package/frontend-vue/layers/dms-core/app/composables/user/usePreferences.ts +11 -10
  614. package/frontend-vue/layers/dms-core/app/composables/user/useRegionalFormat.ts +21 -10
  615. package/frontend-vue/layers/dms-core/app/composables/user/useUserRegionalPreferences.ts +1 -2
  616. package/frontend-vue/layers/dms-core/app/composables/watch/useWatch.ts +18 -13
  617. package/frontend-vue/layers/dms-core/app/entries/composables/auth/usePermissionPreview.ts +1 -0
  618. package/frontend-vue/layers/dms-core/app/entries/composables/renderNow.ts +1 -0
  619. package/frontend-vue/layers/dms-core/app/entries/composables/user/preferencesCookie.ts +1 -0
  620. package/frontend-vue/layers/dms-core/app/entries/composables/user/tablePreferences.ts +1 -0
  621. package/frontend-vue/layers/dms-core/app/entries/i18n/locales/core-en-GB.json.ts +1 -0
  622. package/frontend-vue/layers/dms-core/app/entries/i18n/locales/core-fr-FR.json.ts +1 -0
  623. package/frontend-vue/layers/dms-core/app/entries/shared/types/app-config.ts +1 -0
  624. package/frontend-vue/layers/dms-core/app/entries/shared/types/runtime-config.ts +1 -0
  625. package/frontend-vue/layers/dms-core/app/entries/types/block-action.ts +12 -0
  626. package/frontend-vue/layers/dms-core/app/entries/utils/asyncDataScope.ts +1 -0
  627. package/frontend-vue/layers/dms-core/app/entries/utils/crossTab.ts +1 -0
  628. package/frontend-vue/layers/dms-core/app/entries/utils/permission-preview.ts +1 -0
  629. package/frontend-vue/layers/dms-core/app/plugins/async-data-scope.ts +1 -1
  630. package/frontend-vue/layers/dms-core/app/types/composed-text.ts +6 -4
  631. package/frontend-vue/layers/dms-core/app/types/confirm-dialog.ts +3 -1
  632. package/frontend-vue/layers/{dms-ui → dms-core}/app/types/live.ts +3 -1
  633. package/frontend-vue/layers/dms-core/app/types/menu.ts +2 -1
  634. package/frontend-vue/layers/{dms-layout → dms-core}/app/types/module-store.ts +1 -0
  635. package/frontend-vue/layers/{dms-layout → dms-core}/app/types/page.ts +18 -11
  636. package/frontend-vue/layers/dms-core/app/types/row-action-operators.ts +5 -1
  637. package/frontend-vue/layers/dms-core/app/types/row-action.ts +31 -10
  638. package/frontend-vue/layers/dms-core/app/types/watch.ts +2 -0
  639. package/frontend-vue/layers/dms-core/app/utils/composedText.ts +18 -24
  640. package/frontend-vue/layers/dms-core/app/utils/dedupedRefresh.ts +2 -0
  641. package/frontend-vue/layers/dms-core/app/utils/formatter.ts +24 -22
  642. package/frontend-vue/layers/dms-core/app/utils/menu.ts +76 -94
  643. package/frontend-vue/layers/{dms-layout → dms-core}/app/utils/pageQuery.ts +3 -5
  644. package/frontend-vue/layers/dms-core/app/utils/pageRoutes.ts +3 -3
  645. package/frontend-vue/layers/dms-core/app/utils/query-validation.ts +3 -2
  646. package/frontend-vue/layers/dms-core/app/utils/regional.ts +23 -12
  647. package/frontend-vue/layers/dms-core/app/utils/row-action-rule-evaluator.ts +19 -8
  648. package/frontend-vue/layers/dms-core/app/utils/stringTypeParser.ts +7 -6
  649. package/frontend-vue/layers/dms-core/app/utils/type-check.ts +4 -1
  650. package/frontend-vue/layers/dms-core/app/utils/url-interpolation.ts +18 -21
  651. package/frontend-vue/layers/dms-core/shared/types/app-config.ts +2 -2
  652. package/frontend-vue/layers/dms-layout/app/app.config.ts +16 -42
  653. package/frontend-vue/layers/dms-layout/app/assets/css/foundation.css +108 -0
  654. package/frontend-vue/layers/dms-layout/app/assets/css/main.css +1 -108
  655. package/frontend-vue/layers/dms-layout/app/build/components/layout/CommandPaletteAssistantAnswer.vue +2 -4
  656. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +1 -3
  657. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardFrame.vue +10 -20
  658. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +13 -24
  659. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardPageBody.vue +2 -8
  660. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidePanel.vue +4 -9
  661. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidebar.vue +21 -50
  662. package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +3 -7
  663. package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +3 -11
  664. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeader.vue +1 -4
  665. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionBar.vue +23 -44
  666. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionsOutlet.vue +8 -10
  667. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageSkeleton.vue +0 -4
  668. package/frontend-vue/layers/dms-layout/app/build/components/layout/QuickActionsPopover.vue +4 -7
  669. package/frontend-vue/layers/dms-layout/app/build/components/layout/RolePreviewBar.vue +3 -6
  670. package/frontend-vue/layers/dms-layout/app/build/components/layout/SidePanelHost.vue +1 -1
  671. package/frontend-vue/layers/dms-layout/app/build/components/layout/SidebarUserMenu.vue +1 -8
  672. package/frontend-vue/layers/dms-layout/app/build/components/layout/UserIdentity.vue +0 -4
  673. package/frontend-vue/layers/dms-layout/app/build/components/notification/NotificationPopover.vue +9 -19
  674. package/frontend-vue/layers/dms-layout/app/build/components/notification/widgetRequest.ts +2 -2
  675. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleCatalogTile.vue +3 -13
  676. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleManageMenu.vue +1 -5
  677. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleSourceLabel.vue +1 -4
  678. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreBanners.vue +2 -6
  679. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreDependencyPicker.vue +7 -3
  680. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreOperation.vue +3 -7
  681. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreRequirements.vue +2 -2
  682. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreTile.vue +1 -6
  683. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTile.vue +6 -11
  684. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTileSkeleton.vue +0 -5
  685. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/members/MemberRolePicker.vue +7 -12
  686. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxDisplay.vue +5 -17
  687. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxItem.vue +1 -6
  688. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationMatrixSubject.vue +0 -3
  689. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationPreferencesForm.vue +3 -9
  690. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/notificationDisplay.ts +3 -3
  691. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfilePersonalInfo.vue +5 -8
  692. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileSecuritySummary.vue +4 -8
  693. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileSummaryRow.vue +4 -7
  694. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionFormatPreview.vue +0 -3
  695. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionTimeZoneInput.vue +0 -3
  696. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/timeZones.ts +1 -8
  697. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RoleEditor.vue +3 -9
  698. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePanelHead.vue +2 -4
  699. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionArea.vue +1 -5
  700. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionGroup.vue +1 -1
  701. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionLeaf.vue +2 -10
  702. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionTree.vue +1 -3
  703. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolesList.vue +2 -2
  704. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolesListItem.vue +0 -2
  705. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +0 -1
  706. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRoleEditor.ts +2 -6
  707. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRolesApi.ts +0 -2
  708. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityBackupCodesModal.vue +2 -3
  709. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityCodeModal.vue +2 -5
  710. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityDialogFrame.vue +1 -1
  711. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityEditPanel.vue +5 -9
  712. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityEmail.vue +14 -13
  713. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityPanelField.vue +4 -4
  714. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityPassword.vue +4 -8
  715. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityPasswordModal.vue +2 -2
  716. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecuritySessions.vue +9 -14
  717. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityStatus.vue +4 -4
  718. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityTotpSetupModal.vue +4 -7
  719. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityTwoFactor.vue +12 -13
  720. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shell/SettingsNav.vue +5 -21
  721. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shortcut/KeyboardShortcut.vue +0 -1
  722. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceAccessibility.vue +1 -1
  723. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceDeveloper.vue +0 -1
  724. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceOptionTile.vue +1 -4
  725. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/CssVariablesList.vue +18 -23
  726. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/ThemePreview.vue +1 -2
  727. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/useAppearanceSave.ts +9 -11
  728. package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/assistantGroups.ts +1 -4
  729. package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/useCommandPaletteAssistantMode.ts +1 -1
  730. package/frontend-vue/layers/dms-layout/app/build/composables/dev-reload/useDevReloadHolder.ts +16 -45
  731. package/frontend-vue/layers/dms-layout/app/build/composables/general/useGithubStarPrompt.ts +2 -6
  732. package/frontend-vue/layers/dms-layout/app/build/composables/layout/useHeaderActionControls.ts +7 -9
  733. package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +3 -4
  734. package/frontend-vue/layers/dms-layout/app/build/composables/navigation/useVisitNavBadges.ts +2 -1
  735. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationCatalog.ts +1 -2
  736. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +2 -1
  737. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationPreferences.ts +7 -7
  738. package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/preferencesSummary.ts +4 -6
  739. package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useAccountData.ts +84 -39
  740. package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useProfilePreferences.ts +9 -20
  741. package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useCodeFieldError.ts +1 -1
  742. package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useSecurityFormat.ts +7 -2
  743. package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useSecurityOverview.ts +3 -3
  744. package/frontend-vue/layers/dms-layout/app/build/composables/settings/useSettingsNavigation.ts +2 -2
  745. package/frontend-vue/layers/dms-layout/app/build/utils/dev-reload-stream.ts +2 -6
  746. package/frontend-vue/layers/dms-layout/app/build/utils/module-store-catalog.ts +9 -8
  747. package/frontend-vue/layers/dms-layout/app/build/utils/module-store-install.ts +7 -4
  748. package/frontend-vue/layers/dms-layout/app/build/utils/modules-catalog.ts +5 -4
  749. package/frontend-vue/layers/dms-layout/app/build/utils/pageValidationRedirect.ts +2 -2
  750. package/frontend-vue/layers/dms-layout/app/build/utils/publicErrorMessage.ts +0 -3
  751. package/frontend-vue/layers/dms-layout/app/components/layout/DashboardSearch.vue +2 -2
  752. package/frontend-vue/layers/dms-layout/app/components/navigation/AccordionItemSync.vue +1 -6
  753. package/frontend-vue/layers/dms-layout/app/components/navigation/CollapsedMenuItem.vue +4 -9
  754. package/frontend-vue/layers/dms-layout/app/components/navigation/NavigationMenu.vue +45 -52
  755. package/frontend-vue/layers/dms-layout/app/composables/general/useAccessibilityPreferences.ts +1 -1
  756. package/frontend-vue/layers/dms-layout/app/composables/general/useSystemState.ts +1 -1
  757. package/frontend-vue/layers/dms-layout/app/composables/layout/useLayoutBanners.ts +0 -1
  758. package/frontend-vue/layers/dms-layout/app/composables/layout/usePageHeaderActions.ts +1 -189
  759. package/frontend-vue/layers/dms-layout/app/composables/layout/useServedHeaderActions.ts +8 -9
  760. package/frontend-vue/layers/dms-layout/app/composables/notification/useNotifications.ts +95 -37
  761. package/frontend-vue/layers/dms-layout/app/composables/page/useFirstAccessiblePage.ts +0 -11
  762. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleHistory.ts +14 -11
  763. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStore.ts +3 -6
  764. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStoreActions.ts +22 -19
  765. package/frontend-vue/layers/dms-layout/app/composables/page/useModulesListing.ts +5 -2
  766. package/frontend-vue/layers/dms-layout/app/composables/page/usePageComponentPreload.ts +12 -13
  767. package/frontend-vue/layers/dms-layout/app/composables/page/usePageLayout.ts +4 -3
  768. package/frontend-vue/layers/dms-layout/app/composables/page/usePageRecordDeletion.ts +7 -11
  769. package/frontend-vue/layers/dms-layout/app/composables/page/useQuickActions.ts +1 -1
  770. package/frontend-vue/layers/dms-layout/app/composables/profile/useUserLanguage.ts +2 -1
  771. package/frontend-vue/layers/dms-layout/app/composables/useCommandPaletteAssistant.ts +3 -2
  772. package/frontend-vue/layers/dms-layout/app/composables/useCommandPaletteSources.ts +3 -2
  773. package/frontend-vue/layers/dms-layout/app/composables/useHeaderActions.ts +4 -15
  774. package/frontend-vue/layers/dms-layout/app/composables/useSidebarWidgets.ts +0 -2
  775. package/frontend-vue/layers/dms-layout/app/custom-layouts/EmptyLayout.vue +0 -3
  776. package/frontend-vue/layers/dms-layout/app/custom-pages/modules-store.vue +4 -14
  777. package/frontend-vue/layers/dms-layout/app/custom-pages/modules.vue +8 -28
  778. package/frontend-vue/layers/dms-layout/app/custom-pages/settings/roles.vue +8 -18
  779. package/frontend-vue/layers/dms-layout/app/custom-pages/settings/shortcuts.vue +5 -6
  780. package/frontend-vue/layers/dms-layout/app/emails/components/EmailLayout.vue +2 -16
  781. package/frontend-vue/layers/dms-layout/app/entries/component-registry.ts +12 -0
  782. package/frontend-vue/layers/dms-layout/app/entries/components/layout/DashboardBanners.ts +2 -0
  783. package/frontend-vue/layers/dms-layout/app/entries/components/layout/DashboardFrame.ts +2 -0
  784. package/frontend-vue/layers/dms-layout/app/entries/components/layout/DashboardHeader.ts +2 -0
  785. package/frontend-vue/layers/dms-layout/app/entries/components/layout/DashboardSidebar.ts +2 -0
  786. package/frontend-vue/layers/dms-layout/app/entries/components/layout/Footer.ts +2 -0
  787. package/frontend-vue/layers/dms-layout/app/entries/components/layout/GithubStarPrompt.ts +2 -0
  788. package/frontend-vue/layers/dms-layout/app/entries/components/layout/PageHeaderActionBar.ts +2 -0
  789. package/frontend-vue/layers/dms-layout/app/entries/components/layout/PageHeaderActionsOutlet.ts +2 -0
  790. package/frontend-vue/layers/dms-layout/app/entries/components/layout/SidePanelHost.ts +2 -0
  791. package/frontend-vue/layers/dms-layout/app/entries/components/layout/SidebarUserMenu.ts +2 -0
  792. package/frontend-vue/layers/dms-layout/app/entries/components/layout/StageCard.ts +2 -0
  793. package/frontend-vue/layers/dms-layout/app/entries/components/layout/sidebarState.ts +1 -0
  794. package/frontend-vue/layers/dms-layout/app/entries/components/notification/NotificationPopover.ts +2 -0
  795. package/frontend-vue/layers/dms-layout/app/entries/components/pages/modules/ModuleCatalogTile.ts +2 -0
  796. package/frontend-vue/layers/dms-layout/app/entries/components/pages/modules/ModuleSourceLabel.ts +2 -0
  797. package/frontend-vue/layers/dms-layout/app/entries/components/pages/modules/ModuleTile.ts +2 -0
  798. package/frontend-vue/layers/dms-layout/app/entries/components/pages/modules/ModuleTileSkeleton.ts +2 -0
  799. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/members/MemberRolePicker.ts +2 -0
  800. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/notification/NotificationInboxDisplay.ts +2 -0
  801. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/notification/NotificationInboxItem.ts +2 -0
  802. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/notification/NotificationPreferencesForm.ts +2 -0
  803. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/notification/notificationDisplay.ts +1 -0
  804. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/profile/ProfilePersonalInfo.ts +2 -0
  805. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/profile/ProfilePreferencesSummary.ts +2 -0
  806. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/profile/ProfileSecuritySummary.ts +2 -0
  807. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/region/timeZones.ts +1 -0
  808. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/roles/RoleEditor.ts +2 -0
  809. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/roles/RolePermissionTree.ts +2 -0
  810. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/roles/role-permissions.ts +1 -0
  811. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/roles/role-types.ts +1 -0
  812. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/security/SecurityEmail.ts +2 -0
  813. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/security/SecurityPassword.ts +2 -0
  814. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/security/SecurityPasswordModal.ts +2 -0
  815. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/security/SecuritySessions.ts +2 -0
  816. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/security/SecurityStatus.ts +2 -0
  817. package/frontend-vue/layers/dms-layout/app/entries/components/pages/settings/shell/SettingsNav.ts +2 -0
  818. package/frontend-vue/layers/dms-layout/app/entries/composables/dev-reload/useDevReloadHolder.ts +1 -0
  819. package/frontend-vue/layers/dms-layout/app/entries/composables/general/useGithubStarPrompt.ts +1 -0
  820. package/frontend-vue/layers/dms-layout/app/entries/composables/layout/useSidePanelWidth.ts +1 -0
  821. package/frontend-vue/layers/dms-layout/app/entries/composables/notification/useNotificationCatalog.ts +1 -0
  822. package/frontend-vue/layers/dms-layout/app/entries/composables/notification/useNotificationGroupsOpen.ts +1 -0
  823. package/frontend-vue/layers/dms-layout/app/entries/composables/notification/useNotificationPreferences.ts +1 -0
  824. package/frontend-vue/layers/dms-layout/app/entries/composables/security/useSessionHandoff.ts +1 -0
  825. package/frontend-vue/layers/dms-layout/app/entries/composables/settings/profile/preferencesSummary.ts +1 -0
  826. package/frontend-vue/layers/dms-layout/app/entries/composables/settings/security/useCodeFieldError.ts +1 -0
  827. package/frontend-vue/layers/dms-layout/app/entries/composables/settings/security/useRevealedBackupCodes.ts +1 -0
  828. package/frontend-vue/layers/dms-layout/app/entries/composables/settings/security/useSecurityOverview.ts +1 -0
  829. package/frontend-vue/layers/dms-layout/app/entries/composables/settings/useSettingsNavigation.ts +1 -0
  830. package/frontend-vue/layers/dms-layout/app/entries/i18n/locales/layout-en-GB.json.ts +1 -0
  831. package/frontend-vue/layers/dms-layout/app/entries/i18n/locales/layout-fr-FR.json.ts +1 -0
  832. package/frontend-vue/layers/dms-layout/app/entries/server/html-render.ts +1 -0
  833. package/frontend-vue/layers/dms-layout/app/entries/utils/dev-reload-stream.ts +1 -0
  834. package/frontend-vue/layers/dms-layout/app/entries/utils/github-repository.ts +1 -0
  835. package/frontend-vue/layers/dms-layout/app/entries/utils/module-store-catalog.ts +1 -0
  836. package/frontend-vue/layers/dms-layout/app/entries/utils/module-store-install.ts +1 -0
  837. package/frontend-vue/layers/dms-layout/app/entries/utils/modules-catalog.ts +1 -0
  838. package/frontend-vue/layers/dms-layout/app/entries/utils/pageValidationRedirect.ts +1 -0
  839. package/frontend-vue/layers/dms-layout/app/entries/utils/publicErrorMessage.ts +1 -0
  840. package/frontend-vue/layers/dms-layout/app/error.vue +4 -5
  841. package/frontend-vue/layers/dms-layout/app/middleware/module-routing.global.ts +1 -17
  842. package/frontend-vue/layers/dms-layout/app/middleware/page-leave-guard.global.ts +1 -3
  843. package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +21 -65
  844. package/frontend-vue/layers/dms-layout/app/plugins/accessibility.ts +1 -2
  845. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-navigation.client.ts +2 -2
  846. package/frontend-vue/layers/dms-layout/app/plugins/dms-dev-reload.client.ts +3 -4
  847. package/frontend-vue/layers/dms-layout/app/plugins/dms-menu-sync.client.ts +2 -12
  848. package/frontend-vue/layers/dms-layout/app/plugins/favicon.ts +11 -10
  849. package/frontend-vue/layers/dms-layout/app/plugins/font-preload.ts +0 -6
  850. package/frontend-vue/layers/dms-layout/app/plugins/notification-stream.client.ts +4 -4
  851. package/frontend-vue/layers/dms-layout/app/plugins/permission-preview-prepaint.ts +2 -3
  852. package/frontend-vue/layers/dms-layout/app/plugins/permission-preview.client.ts +2 -8
  853. package/frontend-vue/layers/dms-layout/app/plugins/profile-sync.client.ts +2 -0
  854. package/frontend-vue/layers/dms-layout/app/plugins/regional-preferences.ts +1 -2
  855. package/frontend-vue/layers/dms-layout/app/theme/actions.ts +10 -28
  856. package/frontend-vue/layers/dms-layout/app/theme/choice-controls.ts +210 -0
  857. package/frontend-vue/layers/dms-layout/app/theme/data.ts +1 -1
  858. package/frontend-vue/layers/dms-layout/app/theme/form-controls.ts +10 -265
  859. package/frontend-vue/layers/dms-layout/app/theme/navigation.ts +5 -9
  860. package/frontend-vue/layers/dms-layout/app/theme/pin-input.ts +50 -0
  861. package/frontend-vue/layers/dms-layout/app/theme/surfaces.ts +4 -9
  862. package/frontend-vue/layers/dms-layout/app/types/page-setup.ts +8 -5
  863. package/frontend-vue/layers/dms-layout/app/utils/account-menu.ts +1 -2
  864. package/frontend-vue/layers/dms-layout/app/utils/breadcrumb.ts +9 -7
  865. package/frontend-vue/layers/dms-layout/app/utils/favorites.ts +3 -5
  866. package/frontend-vue/layers/dms-layout/app/utils/moduleLanding.ts +1 -1
  867. package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +4 -0
  868. package/frontend-vue/layers/dms-layout/server/html-render.ts +4 -3
  869. package/frontend-vue/layers/dms-layout/server/render-token.ts +14 -13
  870. package/frontend-vue/layers/dms-onboarding/app/build/components/onboarding/StepIndicator.vue +2 -4
  871. package/frontend-vue/layers/dms-onboarding/app/build/components/onboarding/steps/platform.vue +1 -2
  872. package/frontend-vue/layers/dms-onboarding/app/build/components/onboarding/steps/ready.vue +6 -6
  873. package/frontend-vue/layers/dms-onboarding/app/components/onboarding/steps/register.vue +5 -7
  874. package/frontend-vue/layers/dms-onboarding/app/composables/onboarding/useOnboarding.ts +1 -6
  875. package/frontend-vue/layers/dms-onboarding/app/custom-pages/onboarding.vue +0 -6
  876. package/frontend-vue/layers/dms-onboarding/app/entries/component-registry.ts +12 -0
  877. package/frontend-vue/layers/dms-onboarding/app/entries/components/onboarding/steps/ready.ts +2 -0
  878. package/frontend-vue/layers/dms-onboarding/app/middleware/onboarding.global.ts +1 -13
  879. package/frontend-vue/layers/dms-ui/app/build/components/activity-feed/activityFeedDays.ts +7 -5
  880. package/frontend-vue/layers/dms-ui/app/build/components/blocks/BlockActions.vue +4 -16
  881. package/frontend-vue/layers/dms-ui/app/build/components/blocks/BlockInlineStatus.vue +0 -3
  882. package/frontend-vue/layers/dms-ui/app/build/components/blocks/BlockStatus.vue +0 -4
  883. package/frontend-vue/layers/dms-ui/app/build/components/chart/internal/ChartSkeleton.vue +1 -2
  884. package/frontend-vue/layers/{dms-layout/app/build/components/layout → dms-ui/app/build/components/containers}/RowSidePanel.vue +1 -3
  885. package/frontend-vue/layers/dms-ui/app/build/components/containers/TargetComponentTree.vue +0 -5
  886. package/frontend-vue/layers/dms-ui/app/build/components/containers/drawer/DynamicDrawer.vue +17 -47
  887. package/frontend-vue/layers/dms-ui/app/build/components/containers/modal/DynamicModal.vue +11 -17
  888. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowHeader.vue +1 -2
  889. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/drawerRowHeader.ts +3 -7
  890. package/frontend-vue/layers/dms-ui/app/build/components/form/ChipGroup.vue +0 -6
  891. package/frontend-vue/layers/dms-ui/app/build/components/form/FormEntries.vue +1 -3
  892. package/frontend-vue/layers/dms-ui/app/build/components/form/FormErrorSummary.vue +0 -2
  893. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldControl.vue +10 -13
  894. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldNotes.vue +8 -8
  895. package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +1 -5
  896. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSectionNav.vue +0 -4
  897. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSections.vue +2 -11
  898. package/frontend-vue/layers/dms-ui/app/build/components/form/OtpInput.vue +0 -6
  899. package/frontend-vue/layers/dms-ui/app/build/components/form/PasswordInput.vue +2 -8
  900. package/frontend-vue/layers/dms-ui/app/build/components/form/SearchInput.vue +0 -5
  901. package/frontend-vue/layers/dms-ui/app/build/components/form/UnsavedStatus.vue +0 -3
  902. package/frontend-vue/layers/dms-ui/app/build/components/modal/ModalEscHint.vue +0 -3
  903. package/frontend-vue/layers/dms-ui/app/build/components/period/PeriodRangeCalendar.vue +4 -14
  904. package/frontend-vue/layers/dms-ui/app/build/components/permission/PermissionVeil.vue +1 -15
  905. package/frontend-vue/layers/dms-ui/app/build/components/skeleton/RowSkeleton.vue +0 -4
  906. package/frontend-vue/layers/dms-ui/app/build/components/sortable/SortableList.vue +7 -6
  907. package/frontend-vue/layers/dms-ui/app/build/components/stat/StatCell.vue +4 -13
  908. package/frontend-vue/layers/dms-ui/app/build/components/table/Actions.vue +17 -37
  909. package/frontend-vue/layers/dms-ui/app/build/components/table/Empty.vue +2 -13
  910. package/frontend-vue/layers/dms-ui/app/build/components/table/FiltersRow.vue +17 -23
  911. package/frontend-vue/layers/dms-ui/app/build/components/table/Menu.vue +3 -3
  912. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuColumns.vue +7 -10
  913. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuDensity.vue +3 -3
  914. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuFilter.vue +5 -12
  915. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuImport.vue +3 -3
  916. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuPage.vue +3 -3
  917. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuRoot.vue +4 -6
  918. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuSort.vue +5 -11
  919. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuViewMode.vue +10 -9
  920. package/frontend-vue/layers/dms-ui/app/build/components/table/MonoCell.vue +0 -4
  921. package/frontend-vue/layers/dms-ui/app/build/components/table/Pagination.vue +8 -16
  922. package/frontend-vue/layers/dms-ui/app/build/components/table/RowSelection.vue +6 -18
  923. package/frontend-vue/layers/dms-ui/app/build/components/table/Table.types.ts +406 -0
  924. package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +156 -1324
  925. package/frontend-vue/layers/dms-ui/app/build/components/table/TableBody.types.ts +43 -0
  926. package/frontend-vue/layers/dms-ui/app/build/components/table/TableBody.vue +240 -0
  927. package/frontend-vue/layers/dms-ui/app/build/components/table/Tabs.vue +5 -9
  928. package/frontend-vue/layers/dms-ui/app/build/components/table/Views.vue +3 -7
  929. package/frontend-vue/layers/dms-ui/app/build/components/table/tableComponentFilters.ts +60 -0
  930. package/frontend-vue/layers/dms-ui/app/build/components/table/tableComponentGroups.ts +60 -0
  931. package/frontend-vue/layers/dms-ui/app/build/components/table/tableComponentHeader.ts +90 -0
  932. package/frontend-vue/layers/dms-ui/app/build/components/table/tableComponentPinning.ts +92 -0
  933. package/frontend-vue/layers/dms-ui/app/build/components/table/tableComponentPreferences.ts +85 -0
  934. package/frontend-vue/layers/dms-ui/app/build/components/table/tableComponentRows.ts +93 -0
  935. package/frontend-vue/layers/dms-ui/app/build/components/table/tableComponentScroll.ts +68 -0
  936. package/frontend-vue/layers/dms-ui/app/build/components/table/tableComponentTheme.ts +241 -0
  937. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardAvatar.vue +3 -2
  938. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardGridSkeleton.vue +0 -2
  939. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardRowActions.vue +0 -2
  940. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +3 -12
  941. package/frontend-vue/layers/dms-ui/app/build/components/table-view/ExpandedRowDetail.vue +4 -6
  942. package/frontend-vue/layers/dms-ui/app/build/components/table-view/IdentityCell.vue +5 -4
  943. package/frontend-vue/layers/dms-ui/app/build/components/table-view/LiveHoldBanner.vue +2 -5
  944. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetActions.ts +141 -0
  945. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetConfirmation.ts +63 -0
  946. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetContainers.ts +178 -0
  947. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetHandlers.ts +104 -0
  948. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetRequests.ts +152 -0
  949. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetRows.ts +139 -0
  950. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetSidePanel.ts +91 -0
  951. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetTypes.ts +43 -0
  952. package/frontend-vue/layers/dms-ui/app/build/composables/actions/actionTargetUrl.ts +25 -0
  953. package/frontend-vue/layers/dms-ui/app/build/composables/actions/bulkSelection.ts +8 -9
  954. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowComponentOptions.ts +11 -11
  955. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +19 -20
  956. package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +56 -881
  957. package/frontend-vue/layers/dms-ui/app/build/composables/block-preview/useBlockPreviewEmbed.ts +8 -10
  958. package/frontend-vue/layers/dms-ui/app/build/composables/blocks/useBlockItems.ts +2 -1
  959. package/frontend-vue/layers/dms-ui/app/build/composables/blocks/useGuard.ts +12 -7
  960. package/frontend-vue/layers/dms-ui/app/build/composables/blocks/useRefreshTriggers.ts +3 -5
  961. package/frontend-vue/layers/dms-ui/app/build/composables/chart/apexAxes.ts +89 -0
  962. package/frontend-vue/layers/dms-ui/app/build/composables/chart/apexHeatmap.ts +111 -0
  963. package/frontend-vue/layers/dms-ui/app/build/composables/chart/apexRawOptions.ts +49 -0
  964. package/frontend-vue/layers/dms-ui/app/build/composables/chart/apexSeriesStyle.ts +201 -0
  965. package/frontend-vue/layers/dms-ui/app/build/composables/chart/apexTheme.ts +21 -16
  966. package/frontend-vue/layers/dms-ui/app/build/composables/clipboard/useCopyFeedback.ts +2 -2
  967. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/actionError.ts +16 -13
  968. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/confirmDialogTexts.ts +12 -12
  969. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/useActionConfirm.ts +7 -16
  970. package/frontend-vue/layers/dms-ui/app/build/composables/containers/closingLayers.ts +7 -16
  971. package/frontend-vue/layers/dms-ui/app/build/composables/containers/drawerSize.ts +21 -21
  972. package/frontend-vue/layers/dms-ui/app/build/composables/containers/useResizableSize.ts +6 -4
  973. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/cellHelpers.ts +23 -16
  974. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/defaultChoiceTypes.ts +177 -0
  975. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/defaultDateCells.ts +108 -0
  976. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/defaultDisplayComponents.ts +33 -0
  977. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/defaultIdentityCells.ts +222 -0
  978. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/defaultLinkTypes.ts +116 -0
  979. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/defaultMediaTypes.ts +105 -0
  980. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/defaultPrimitiveTypes.ts +190 -0
  981. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/defaultRelationTypes.ts +166 -0
  982. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +28 -19
  983. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/numberSuffix.ts +8 -5
  984. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +22 -988
  985. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerFieldTypes.ts +13 -12
  986. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationBadges.ts +21 -6
  987. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationFilter.ts +9 -6
  988. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationRows.ts +12 -6
  989. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationValue.ts +32 -17
  990. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +12 -7
  991. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +33 -25
  992. package/frontend-vue/layers/dms-ui/app/build/composables/files/useFileMetadata.ts +3 -3
  993. package/frontend-vue/layers/dms-ui/app/build/composables/form/createFormFields.ts +4 -1
  994. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldSaved.ts +3 -2
  995. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldValueRule.ts +11 -5
  996. package/frontend-vue/layers/dms-ui/app/build/composables/form/floatingSaveBars.ts +0 -1
  997. package/frontend-vue/layers/dms-ui/app/build/composables/form/formComponentCancel.ts +49 -0
  998. package/frontend-vue/layers/dms-ui/app/build/composables/form/formComponentErrors.ts +106 -0
  999. package/frontend-vue/layers/dms-ui/app/build/composables/form/formComponentFocus.ts +70 -0
  1000. package/frontend-vue/layers/dms-ui/app/build/composables/form/formComponentRealtime.ts +149 -0
  1001. package/frontend-vue/layers/dms-ui/app/build/composables/form/formComponentSections.ts +117 -0
  1002. package/frontend-vue/layers/dms-ui/app/build/composables/form/formComponentValidation.ts +118 -0
  1003. package/frontend-vue/layers/dms-ui/app/build/composables/form/formEntryContext.ts +5 -2
  1004. package/frontend-vue/layers/dms-ui/app/build/composables/form/formLayout.ts +4 -33
  1005. package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +3 -1
  1006. package/frontend-vue/layers/dms-ui/app/build/composables/form/formState.ts +241 -0
  1007. package/frontend-vue/layers/dms-ui/app/build/composables/form/formValidation.ts +11 -12
  1008. package/frontend-vue/layers/dms-ui/app/build/composables/form/keyValueRows.ts +4 -4
  1009. package/frontend-vue/layers/dms-ui/app/build/composables/form/numberRange.ts +7 -4
  1010. package/frontend-vue/layers/dms-ui/app/build/composables/form/readonlyValue.ts +8 -5
  1011. package/frontend-vue/layers/dms-ui/app/build/composables/form/registerFormFunctions.ts +11 -6
  1012. package/frontend-vue/layers/dms-ui/app/build/composables/form/repeaterTable.ts +11 -8
  1013. package/frontend-vue/layers/dms-ui/app/build/composables/form/serverFieldErrors.ts +7 -3
  1014. package/frontend-vue/layers/dms-ui/app/build/composables/form/tagValues.ts +0 -1
  1015. package/frontend-vue/layers/dms-ui/app/build/composables/form/toasterClearance.ts +0 -4
  1016. package/frontend-vue/layers/dms-ui/app/build/composables/form/useFormModel.ts +431 -0
  1017. package/frontend-vue/layers/dms-ui/app/build/composables/form/useInstantForm.ts +12 -11
  1018. package/frontend-vue/layers/dms-ui/app/build/composables/global/searchShortcuts.ts +3 -3
  1019. package/frontend-vue/layers/dms-ui/app/build/composables/instant-save/useInstantSave.ts +39 -20
  1020. package/frontend-vue/layers/{dms-layout → dms-ui}/app/build/composables/layout/rowSidePanel.ts +1 -3
  1021. package/frontend-vue/layers/{dms-layout → dms-ui}/app/build/composables/layout/sidePanelState.ts +11 -10
  1022. package/frontend-vue/layers/dms-ui/app/build/composables/live/currentPageLive.ts +1 -8
  1023. package/frontend-vue/layers/dms-ui/app/build/composables/live/liveCadence.ts +4 -3
  1024. package/frontend-vue/layers/dms-ui/app/build/composables/live/liveHolds.ts +3 -2
  1025. package/frontend-vue/layers/dms-ui/app/build/composables/live/liveNotes.ts +1 -1
  1026. package/frontend-vue/layers/dms-ui/app/build/composables/live/liveStorage.ts +2 -1
  1027. package/frontend-vue/layers/dms-ui/app/build/composables/live/missedTally.ts +9 -6
  1028. package/frontend-vue/layers/dms-ui/app/build/composables/live/pageLiveController.ts +12 -10
  1029. package/frontend-vue/layers/dms-ui/app/build/composables/live/pageReadClock.ts +0 -3
  1030. package/frontend-vue/layers/dms-ui/app/build/composables/live/useLivePeriodSpan.ts +3 -1
  1031. package/frontend-vue/layers/dms-ui/app/build/composables/live/useLiveToggleShortcut.ts +0 -2
  1032. package/frontend-vue/layers/dms-ui/app/build/composables/live/usePageDataRefresh.ts +2 -4
  1033. package/frontend-vue/layers/dms-ui/app/build/composables/live/usePageLiveHost.ts +2 -6
  1034. package/frontend-vue/layers/dms-ui/app/build/composables/navigation/useNavBadges.ts +1 -1
  1035. package/frontend-vue/layers/dms-ui/app/build/composables/page/blockAnchors.ts +1 -4
  1036. package/frontend-vue/layers/dms-ui/app/build/composables/page/pageUrlValues.ts +1 -1
  1037. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/toolbarControlHeight.ts +4 -1
  1038. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodComparison.ts +1 -1
  1039. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodDisplay.ts +0 -10
  1040. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodQuery.ts +15 -10
  1041. package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodDraft.ts +0 -1
  1042. package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodLocation.ts +2 -3
  1043. package/frontend-vue/layers/dms-ui/app/build/composables/shortcuts/useShortcutRegistry.ts +0 -3
  1044. package/frontend-vue/layers/dms-ui/app/build/composables/table/constants.ts +0 -2
  1045. package/frontend-vue/layers/dms-ui/app/build/composables/table/tableColumnActionDescriptors.ts +306 -0
  1046. package/frontend-vue/layers/dms-ui/app/build/composables/table/tableColumnActionRendering.ts +141 -0
  1047. package/frontend-vue/layers/dms-ui/app/build/composables/table/tableColumnActionSizing.ts +149 -0
  1048. package/frontend-vue/layers/dms-ui/app/build/composables/table/tableColumnHeaders.ts +291 -0
  1049. package/frontend-vue/layers/dms-ui/app/build/composables/table/tableColumnStructure.ts +156 -0
  1050. package/frontend-vue/layers/dms-ui/app/build/composables/table/tableColumnTypes.ts +88 -0
  1051. package/frontend-vue/layers/dms-ui/app/build/composables/table/types.ts +18 -3
  1052. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRelationFilterLabels.ts +2 -3
  1053. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRowScrollAnchor.ts +1 -3
  1054. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +13 -21
  1055. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableColumns.ts +29 -931
  1056. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableConfigClipboard.ts +7 -7
  1057. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/archivedCount.ts +1 -1
  1058. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/clearTableFilters.ts +1 -8
  1059. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/filterEditorValue.ts +5 -9
  1060. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/formatFilterValue.ts +5 -10
  1061. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/scrollEdges.ts +0 -1
  1062. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/displayRegistry.ts +1 -2
  1063. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/registerDefaultFunctions.ts +10 -4
  1064. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableRowActionBulkConfirm.ts +227 -0
  1065. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableRowActionBulkRequests.ts +157 -0
  1066. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableRowActionContainers.ts +267 -0
  1067. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableRowActionEvents.ts +98 -0
  1068. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableRowActionNavigation.ts +117 -0
  1069. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableRowActionTypes.ts +73 -0
  1070. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableRowActionValues.ts +18 -0
  1071. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewActions.ts +275 -0
  1072. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewArrival.ts +111 -0
  1073. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewBindings.ts +90 -0
  1074. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewConfiguration.ts +78 -0
  1075. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewCounts.ts +151 -0
  1076. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewDeferred.ts +26 -0
  1077. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewDisplayContext.ts +159 -0
  1078. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewDisplays.ts +205 -0
  1079. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewEvents.ts +95 -0
  1080. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewExpansion.ts +100 -0
  1081. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewFilters.ts +218 -0
  1082. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewFooter.ts +66 -0
  1083. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewGrouping.ts +123 -0
  1084. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewListing.ts +203 -0
  1085. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewLive.ts +137 -0
  1086. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewNavigation.ts +133 -0
  1087. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewPersistence.ts +94 -0
  1088. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewPresence.ts +120 -0
  1089. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewQuickActions.ts +116 -0
  1090. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewQuickFilters.ts +82 -0
  1091. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewRealtime.ts +152 -0
  1092. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewRecordLink.ts +64 -0
  1093. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewScope.ts +202 -0
  1094. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewScopeResults.ts +125 -0
  1095. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewSelection.ts +119 -0
  1096. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewSetup.ts +206 -0
  1097. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewSorting.ts +245 -0
  1098. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewTabs.ts +168 -0
  1099. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewTypes.ts +17 -0
  1100. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/tableViewViews.ts +114 -0
  1101. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useCardFields.ts +6 -3
  1102. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useGroupedRows.ts +5 -9
  1103. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/usePersistedPagination.ts +3 -3
  1104. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useReorderHandles.ts +3 -6
  1105. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableFooter.ts +6 -8
  1106. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLinkedVisit.ts +5 -5
  1107. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableListData.ts +4 -4
  1108. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLiveHold.ts +5 -18
  1109. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTablePreferences.ts +8 -9
  1110. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRecordLink.ts +5 -6
  1111. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableReorder.ts +5 -1
  1112. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +29 -28
  1113. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableUrlTab.ts +4 -7
  1114. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewConfig.ts +3 -9
  1115. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +38 -805
  1116. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViews.ts +78 -18
  1117. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/bulkActions.ts +9 -14
  1118. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/card.ts +16 -19
  1119. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/chrome.ts +1 -2
  1120. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/compareValues.ts +10 -4
  1121. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/expandedRows.ts +1 -0
  1122. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/formTexts.ts +11 -10
  1123. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/groupedRows.ts +19 -11
  1124. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/linkedArrival.ts +15 -13
  1125. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/locateRow.ts +2 -3
  1126. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pageArrival.ts +2 -6
  1127. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/quickFilters.ts +4 -3
  1128. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +2 -1
  1129. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/reorder.ts +9 -4
  1130. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/sortableColumns.ts +17 -10
  1131. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableQuery.ts +7 -7
  1132. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/urlFilters.ts +6 -7
  1133. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +6 -6
  1134. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/writeError.ts +1 -1
  1135. package/frontend-vue/layers/dms-ui/app/build/composables/unsaved-changes/formValue.ts +15 -2
  1136. package/frontend-vue/layers/dms-ui/app/build/composables/unsaved-changes/registry.ts +11 -13
  1137. package/frontend-vue/layers/dms-ui/app/build/types/tree.ts +1 -13
  1138. package/frontend-vue/layers/dms-ui/app/build/utils/accessibilityPreferences.ts +18 -14
  1139. package/frontend-vue/layers/dms-ui/app/build/utils/addressSuggestions.ts +0 -5
  1140. package/frontend-vue/layers/dms-ui/app/build/utils/blockPreview.ts +31 -17
  1141. package/frontend-vue/layers/{dms-layout → dms-ui}/app/build/utils/categoryPages.ts +1 -1
  1142. package/frontend-vue/layers/dms-ui/app/build/utils/characterCount.ts +7 -2
  1143. package/frontend-vue/layers/dms-ui/app/build/utils/codeEditor.ts +4 -10
  1144. package/frontend-vue/layers/dms-ui/app/build/utils/codeHighlight.ts +4 -9
  1145. package/frontend-vue/layers/dms-ui/app/build/utils/codeLanguages.ts +8 -7
  1146. package/frontend-vue/layers/dms-ui/app/build/utils/dispatchQuickActionTarget.ts +5 -4
  1147. package/frontend-vue/layers/dms-ui/app/build/utils/fetchNotFound.ts +17 -10
  1148. package/frontend-vue/layers/dms-ui/app/build/utils/fieldOptionsI18n.ts +9 -9
  1149. package/frontend-vue/layers/dms-ui/app/build/utils/fieldTrigger.ts +0 -5
  1150. package/frontend-vue/layers/dms-ui/app/build/utils/fileDownload.ts +0 -1
  1151. package/frontend-vue/layers/dms-ui/app/build/utils/htmlGrammar.ts +7 -8
  1152. package/frontend-vue/layers/dms-ui/app/build/utils/link.ts +0 -5
  1153. package/frontend-vue/layers/dms-ui/app/build/utils/literalText.ts +9 -4
  1154. package/frontend-vue/layers/dms-ui/app/build/utils/navBadge.ts +1 -1
  1155. package/frontend-vue/layers/dms-ui/app/build/utils/numberAdjustment.ts +3 -4
  1156. package/frontend-vue/layers/dms-ui/app/build/utils/quickActionTargets.ts +0 -2
  1157. package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +4 -3
  1158. package/frontend-vue/layers/dms-ui/app/build/utils/responseWarning.ts +12 -6
  1159. package/frontend-vue/layers/dms-ui/app/build/utils/rowClickTrigger.ts +2 -6
  1160. package/frontend-vue/layers/dms-ui/app/build/utils/scrollWithin.ts +0 -5
  1161. package/frontend-vue/layers/dms-ui/app/build/utils/shellParser.ts +0 -3
  1162. package/frontend-vue/layers/dms-ui/app/build/utils/streamHighlight.ts +10 -14
  1163. package/frontend-vue/layers/dms-ui/app/build/utils/tone.ts +1 -7
  1164. package/frontend-vue/layers/dms-ui/app/build/utils/urlVariables.ts +9 -22
  1165. package/frontend-vue/layers/dms-ui/app/components/PasswordStrength.vue +2 -0
  1166. package/frontend-vue/layers/dms-ui/app/components/RecursiveComponent.vue +11 -11
  1167. package/frontend-vue/layers/dms-ui/app/components/activity/ActivityItem.vue +5 -10
  1168. package/frontend-vue/layers/dms-ui/app/components/activity-feed/ActivityFeed.vue +3 -18
  1169. package/frontend-vue/layers/dms-ui/app/components/banner/Banner.vue +4 -18
  1170. package/frontend-vue/layers/dms-ui/app/components/block-preview/BlockPreview.vue +6 -5
  1171. package/frontend-vue/layers/dms-ui/app/components/blocks/BannerBlock.vue +3 -15
  1172. package/frontend-vue/layers/dms-ui/app/components/blocks/CardBlock.vue +4 -8
  1173. package/frontend-vue/layers/dms-ui/app/components/blocks/CodeBlock.vue +2 -7
  1174. package/frontend-vue/layers/dms-ui/app/components/blocks/EmptyStateBlock.vue +1 -5
  1175. package/frontend-vue/layers/dms-ui/app/components/blocks/KeyValueListBlock.vue +5 -13
  1176. package/frontend-vue/layers/dms-ui/app/components/blocks/LiveToggleBlock.vue +1 -14
  1177. package/frontend-vue/layers/dms-ui/app/components/blocks/NavCardGridBlock.vue +5 -15
  1178. package/frontend-vue/layers/dms-ui/app/components/blocks/PageToolbarBlock.vue +0 -8
  1179. package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +0 -4
  1180. package/frontend-vue/layers/dms-ui/app/components/card/Card.vue +7 -18
  1181. package/frontend-vue/layers/dms-ui/app/components/card/NavCard.vue +3 -15
  1182. package/frontend-vue/layers/dms-ui/app/components/chart/ApexChartHost.vue +21 -25
  1183. package/frontend-vue/layers/dms-ui/app/components/chart/Chart.vue +14 -17
  1184. package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +12 -34
  1185. package/frontend-vue/layers/dms-ui/app/components/chart/internal/Sparkline.vue +4 -5
  1186. package/frontend-vue/layers/dms-ui/app/components/chart/internal/TrendBadge.vue +0 -1
  1187. package/frontend-vue/layers/dms-ui/app/components/check-list/CheckList.vue +6 -3
  1188. package/frontend-vue/layers/dms-ui/app/components/check-list/PasswordRules.vue +7 -5
  1189. package/frontend-vue/layers/dms-ui/app/components/code-snippet/CodeSnippet.vue +3 -11
  1190. package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +31 -31
  1191. package/frontend-vue/layers/dms-ui/app/components/container-footer/ContainerFooter.vue +0 -2
  1192. package/frontend-vue/layers/dms-ui/app/components/copy/CopyButton.vue +0 -2
  1193. package/frontend-vue/layers/dms-ui/app/components/empty-state/EmptyState.vue +6 -10
  1194. package/frontend-vue/layers/dms-ui/app/components/field-row/FieldRow.vue +9 -22
  1195. package/frontend-vue/layers/dms-ui/app/components/flow-canvas/FlowCanvas.vue +11 -47
  1196. package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +95 -568
  1197. package/frontend-vue/layers/dms-ui/app/components/form/LocalizedField.vue +11 -20
  1198. package/frontend-vue/layers/dms-ui/app/components/form/components/Calendar.vue +28 -27
  1199. package/frontend-vue/layers/dms-ui/app/components/form/components/Cascader.vue +4 -8
  1200. package/frontend-vue/layers/dms-ui/app/components/form/components/Checkbox.vue +0 -1
  1201. package/frontend-vue/layers/dms-ui/app/components/form/components/ChoiceCards.vue +1 -4
  1202. package/frontend-vue/layers/dms-ui/app/components/form/components/DatePicker.vue +35 -45
  1203. package/frontend-vue/layers/dms-ui/app/components/form/components/DatePickerRange.vue +1 -6
  1204. package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +7 -8
  1205. package/frontend-vue/layers/dms-ui/app/components/form/components/File.vue +6 -9
  1206. package/frontend-vue/layers/dms-ui/app/components/form/components/Image.vue +63 -570
  1207. package/frontend-vue/layers/dms-ui/app/components/form/components/ImagePresentation.vue +457 -0
  1208. package/frontend-vue/layers/dms-ui/app/components/form/components/InputAddress.vue +14 -53
  1209. package/frontend-vue/layers/dms-ui/app/components/form/components/InputCode.vue +2 -4
  1210. package/frontend-vue/layers/dms-ui/app/components/form/components/InputColor.vue +3 -5
  1211. package/frontend-vue/layers/dms-ui/app/components/form/components/InputNumber.vue +7 -17
  1212. package/frontend-vue/layers/dms-ui/app/components/form/components/InputPassword.vue +1 -2
  1213. package/frontend-vue/layers/dms-ui/app/components/form/components/InputPercentage.vue +7 -4
  1214. package/frontend-vue/layers/dms-ui/app/components/form/components/InputSecret.vue +2 -5
  1215. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTags.vue +3 -12
  1216. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTime.vue +1 -3
  1217. package/frontend-vue/layers/dms-ui/app/components/form/components/KeyValue.vue +4 -6
  1218. package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +10 -11
  1219. package/frontend-vue/layers/dms-ui/app/components/form/components/Repeater.vue +13 -17
  1220. package/frontend-vue/layers/dms-ui/app/components/form/components/RepeaterTable.vue +8 -11
  1221. package/frontend-vue/layers/dms-ui/app/components/form/components/RichText.vue +5 -15
  1222. package/frontend-vue/layers/dms-ui/app/components/form/components/SegmentedSelect.vue +0 -2
  1223. package/frontend-vue/layers/dms-ui/app/components/form/components/Select.vue +11 -15
  1224. package/frontend-vue/layers/dms-ui/app/components/form/components/imageItems.ts +122 -0
  1225. package/frontend-vue/layers/dms-ui/app/components/form/components/imagePresentation.ts +41 -0
  1226. package/frontend-vue/layers/dms-ui/app/components/grid/Grid.vue +0 -4
  1227. package/frontend-vue/layers/dms-ui/app/components/grid/GridRow.vue +2 -10
  1228. package/frontend-vue/layers/dms-ui/app/components/grid/columns.ts +1 -2
  1229. package/frontend-vue/layers/dms-ui/app/components/guard/Guard.vue +0 -7
  1230. package/frontend-vue/layers/dms-ui/app/components/icon-well/IconWell.vue +3 -4
  1231. package/frontend-vue/layers/dms-ui/app/components/key-value-list/KeyValueList.vue +15 -17
  1232. package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +8 -21
  1233. package/frontend-vue/layers/dms-ui/app/components/link/AutoLink.vue +2 -6
  1234. package/frontend-vue/layers/dms-ui/app/components/list-row/ListRow.vue +11 -23
  1235. package/frontend-vue/layers/dms-ui/app/components/master-detail/MasterDetail.vue +1 -8
  1236. package/frontend-vue/layers/dms-ui/app/components/meter/Meter.vue +4 -5
  1237. package/frontend-vue/layers/dms-ui/app/components/meter/MeterBlock.vue +5 -10
  1238. package/frontend-vue/layers/dms-ui/app/components/period/PeriodSelector.vue +71 -455
  1239. package/frontend-vue/layers/dms-ui/app/components/period/periodSelectorPresentation.ts +405 -0
  1240. package/frontend-vue/layers/dms-ui/app/components/period/usePeriodSelectorInteraction.ts +113 -0
  1241. package/frontend-vue/layers/dms-ui/app/components/record-card/RecordCard.vue +6 -6
  1242. package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +1 -9
  1243. package/frontend-vue/layers/dms-ui/app/components/section/Section.vue +6 -11
  1244. package/frontend-vue/layers/dms-ui/app/components/section-header/Eyebrow.vue +2 -5
  1245. package/frontend-vue/layers/dms-ui/app/components/section-header/SectionHeader.vue +6 -7
  1246. package/frontend-vue/layers/dms-ui/app/components/segmented/Segmented.vue +1 -15
  1247. package/frontend-vue/layers/dms-ui/app/components/stat-group/StatGroup.vue +4 -18
  1248. package/frontend-vue/layers/dms-ui/app/components/status/StatusSummary.vue +0 -6
  1249. package/frontend-vue/layers/dms-ui/app/components/status-pill/StatusPill.vue +4 -8
  1250. package/frontend-vue/layers/dms-ui/app/components/tab/Tab.vue +8 -29
  1251. package/frontend-vue/layers/dms-ui/app/components/table-view/CascaderPath.vue +2 -4
  1252. package/frontend-vue/layers/dms-ui/app/components/table-view/FilePreview.vue +0 -1
  1253. package/frontend-vue/layers/dms-ui/app/components/table-view/ImagePreview.vue +0 -1
  1254. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanBoard.vue +19 -56
  1255. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanDisplay.vue +4 -6
  1256. package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +69 -2323
  1257. package/frontend-vue/layers/dms-ui/app/components/top-list/TopListCard.vue +7 -32
  1258. package/frontend-vue/layers/dms-ui/app/components/top-list/internal/TopListRow.vue +1 -3
  1259. package/frontend-vue/layers/dms-ui/app/composables/chart/apexAnnotations.ts +2 -1
  1260. package/frontend-vue/layers/dms-ui/app/composables/chart/apexCategoryLabels.ts +2 -1
  1261. package/frontend-vue/layers/dms-ui/app/composables/chart/apexDatetimeBuckets.ts +13 -6
  1262. package/frontend-vue/layers/dms-ui/app/composables/chart/apexLocales.ts +13 -6
  1263. package/frontend-vue/layers/dms-ui/app/composables/chart/apexPlotOptions.ts +11 -10
  1264. package/frontend-vue/layers/dms-ui/app/composables/chart/apexYRange.ts +14 -8
  1265. package/frontend-vue/layers/dms-ui/app/composables/chart/donutRecords.ts +4 -9
  1266. package/frontend-vue/layers/dms-ui/app/composables/chart/events.ts +10 -9
  1267. package/frontend-vue/layers/dms-ui/app/composables/chart/localizeSeries.ts +13 -14
  1268. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.ts +49 -481
  1269. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.types.ts +5 -2
  1270. package/frontend-vue/layers/dms-ui/app/composables/chart/useChartFetch.ts +19 -29
  1271. package/frontend-vue/layers/dms-ui/app/composables/chart/useChartTheme.ts +15 -7
  1272. package/frontend-vue/layers/dms-ui/app/composables/confirm/types.ts +2 -1
  1273. package/frontend-vue/layers/dms-ui/app/composables/containers/openDynamicContainer.ts +6 -10
  1274. package/frontend-vue/layers/dms-ui/app/composables/containers/types.ts +4 -4
  1275. package/frontend-vue/layers/dms-ui/app/composables/containers/useDrawer.ts +7 -11
  1276. package/frontend-vue/layers/dms-ui/app/composables/form/types/field-saved.ts +5 -1
  1277. package/frontend-vue/layers/dms-ui/app/composables/form/types/props.ts +7 -1
  1278. package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +199 -779
  1279. package/frontend-vue/layers/dms-ui/app/composables/global/keyboardPlatform.ts +1 -1
  1280. package/frontend-vue/layers/{dms-layout → dms-ui}/app/composables/layout/useInstantSaveHeader.ts +0 -2
  1281. package/frontend-vue/layers/dms-ui/app/composables/layout/usePageHeaderActions.ts +183 -0
  1282. package/frontend-vue/layers/dms-ui/app/composables/live/usePageLive.ts +1 -5
  1283. package/frontend-vue/layers/dms-ui/app/composables/live/usePageLiveRefresh.ts +1 -3
  1284. package/frontend-vue/layers/dms-ui/app/composables/tab/shortcuts/tabBuildShortcuts.ts +1 -1
  1285. package/frontend-vue/layers/dms-ui/app/composables/tab/types/composable.ts +3 -1
  1286. package/frontend-vue/layers/dms-ui/app/composables/tab/types/props.ts +0 -2
  1287. package/frontend-vue/layers/dms-ui/app/composables/tab/useTab.ts +4 -5
  1288. package/frontend-vue/layers/dms-ui/app/composables/table-view/kanban.ts +5 -3
  1289. package/frontend-vue/layers/dms-ui/app/composables/table-view/shortcuts/index.ts +1 -2
  1290. package/frontend-vue/layers/dms-ui/app/composables/table-view/shortcuts/tableViewRowPanel.ts +0 -4
  1291. package/frontend-vue/layers/dms-ui/app/composables/table-view/shortcuts/tableViewShiftF.ts +1 -1
  1292. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +1 -0
  1293. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/column.ts +1 -0
  1294. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +6 -3
  1295. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +7 -4
  1296. package/frontend-vue/layers/dms-ui/app/composables/table-view/useTableViewDisplays.ts +3 -2
  1297. package/frontend-vue/layers/dms-ui/app/composables/table-view/useTableViewExport.ts +6 -1
  1298. package/frontend-vue/layers/dms-ui/app/composables/unsaved-changes/useUnsavedChanges.ts +2 -5
  1299. package/frontend-vue/layers/dms-ui/app/composables/useExportJob.ts +112 -53
  1300. package/frontend-vue/layers/dms-ui/app/composables/usePasswordStrength.ts +0 -2
  1301. package/frontend-vue/layers/dms-ui/app/entries/component-registry.ts +15 -0
  1302. package/frontend-vue/layers/dms-ui/app/entries/components/activity-feed/activityFeedDays.ts +1 -0
  1303. package/frontend-vue/layers/dms-ui/app/entries/components/blocks/BlockActions.ts +2 -0
  1304. package/frontend-vue/layers/dms-ui/app/entries/components/blocks/BlockStatus.ts +2 -0
  1305. package/frontend-vue/layers/dms-ui/app/entries/components/containers/RowSidePanel.ts +2 -0
  1306. package/frontend-vue/layers/dms-ui/app/entries/components/containers/TargetComponentTree.ts +2 -0
  1307. package/frontend-vue/layers/dms-ui/app/entries/components/containers/constants.ts +1 -0
  1308. package/frontend-vue/layers/dms-ui/app/entries/components/containers/drawer/DynamicDrawer.ts +2 -0
  1309. package/frontend-vue/layers/dms-ui/app/entries/components/containers/modal/DynamicModal.ts +2 -0
  1310. package/frontend-vue/layers/dms-ui/app/entries/components/containers/row/RowHeader.ts +2 -0
  1311. package/frontend-vue/layers/dms-ui/app/entries/components/containers/row/RowNotFound.ts +2 -0
  1312. package/frontend-vue/layers/dms-ui/app/entries/components/containers/row/drawerRowHeader.ts +1 -0
  1313. package/frontend-vue/layers/dms-ui/app/entries/components/form/ChipGroup.ts +2 -0
  1314. package/frontend-vue/layers/dms-ui/app/entries/components/form/FormEntries.ts +2 -0
  1315. package/frontend-vue/layers/dms-ui/app/entries/components/form/FormErrorSummary.ts +2 -0
  1316. package/frontend-vue/layers/dms-ui/app/entries/components/form/FormFieldControl.ts +2 -0
  1317. package/frontend-vue/layers/dms-ui/app/entries/components/form/FormFieldNotes.ts +2 -0
  1318. package/frontend-vue/layers/dms-ui/app/entries/components/form/FormLoadError.ts +2 -0
  1319. package/frontend-vue/layers/dms-ui/app/entries/components/form/FormSectionNav.ts +2 -0
  1320. package/frontend-vue/layers/dms-ui/app/entries/components/form/FormSections.ts +2 -0
  1321. package/frontend-vue/layers/dms-ui/app/entries/components/form/OtpInput.ts +2 -0
  1322. package/frontend-vue/layers/dms-ui/app/entries/components/form/PasswordInput.ts +2 -0
  1323. package/frontend-vue/layers/dms-ui/app/entries/components/form/SearchInput.ts +2 -0
  1324. package/frontend-vue/layers/dms-ui/app/entries/components/form/UnsavedStatus.ts +2 -0
  1325. package/frontend-vue/layers/dms-ui/app/entries/components/modal/ModalEscHint.ts +2 -0
  1326. package/frontend-vue/layers/dms-ui/app/entries/components/period/PeriodRangeCalendar.ts +2 -0
  1327. package/frontend-vue/layers/dms-ui/app/entries/components/permission/PermissionVeil.ts +2 -0
  1328. package/frontend-vue/layers/dms-ui/app/entries/components/skeleton/RowSkeleton.ts +2 -0
  1329. package/frontend-vue/layers/dms-ui/app/entries/components/sortable/SortableList.ts +2 -0
  1330. package/frontend-vue/layers/dms-ui/app/entries/components/table/Actions.ts +2 -0
  1331. package/frontend-vue/layers/dms-ui/app/entries/components/table/Empty.ts +2 -0
  1332. package/frontend-vue/layers/dms-ui/app/entries/components/table/FiltersRow.ts +2 -0
  1333. package/frontend-vue/layers/dms-ui/app/entries/components/table/MenuDensity.ts +2 -0
  1334. package/frontend-vue/layers/dms-ui/app/entries/components/table/MenuRoot.ts +2 -0
  1335. package/frontend-vue/layers/dms-ui/app/entries/components/table/MonoCell.ts +2 -0
  1336. package/frontend-vue/layers/dms-ui/app/entries/components/table/Pagination.ts +2 -0
  1337. package/frontend-vue/layers/dms-ui/app/entries/components/table/RowSelection.ts +2 -0
  1338. package/frontend-vue/layers/dms-ui/app/entries/components/table/Table.ts +2 -0
  1339. package/frontend-vue/layers/dms-ui/app/entries/components/table/Views.ts +2 -0
  1340. package/frontend-vue/layers/dms-ui/app/entries/components/table-view/CardGridSkeleton.ts +2 -0
  1341. package/frontend-vue/layers/dms-ui/app/entries/components/table-view/CardsDisplay.ts +2 -0
  1342. package/frontend-vue/layers/dms-ui/app/entries/components/table-view/ExpandedRowDetail.ts +2 -0
  1343. package/frontend-vue/layers/dms-ui/app/entries/components/table-view/IdentityCell.ts +2 -0
  1344. package/frontend-vue/layers/dms-ui/app/entries/components/table-view/LiveHoldBanner.ts +2 -0
  1345. package/frontend-vue/layers/dms-ui/app/entries/composables/actions/bulkSelection.ts +1 -0
  1346. package/frontend-vue/layers/dms-ui/app/entries/composables/actions/rowNavigation.ts +1 -0
  1347. package/frontend-vue/layers/dms-ui/app/entries/composables/actions/useActionTargets.ts +1 -0
  1348. package/frontend-vue/layers/dms-ui/app/entries/composables/block-preview/useBlockPreviewEmbed.ts +1 -0
  1349. package/frontend-vue/layers/dms-ui/app/entries/composables/blocks/registerBlockFunctions.ts +1 -0
  1350. package/frontend-vue/layers/dms-ui/app/entries/composables/blocks/useBlockItems.ts +1 -0
  1351. package/frontend-vue/layers/dms-ui/app/entries/composables/blocks/useGuard.ts +1 -0
  1352. package/frontend-vue/layers/dms-ui/app/entries/composables/blocks/useRefreshTriggers.ts +1 -0
  1353. package/frontend-vue/layers/dms-ui/app/entries/composables/clipboard/useCopyFeedback.ts +1 -0
  1354. package/frontend-vue/layers/dms-ui/app/entries/composables/confirm/actionError.ts +1 -0
  1355. package/frontend-vue/layers/dms-ui/app/entries/composables/confirm/confirmDialogTexts.ts +1 -0
  1356. package/frontend-vue/layers/dms-ui/app/entries/composables/confirm/confirmTextMatch.ts +1 -0
  1357. package/frontend-vue/layers/dms-ui/app/entries/composables/confirm/secondaryTarget.ts +1 -0
  1358. package/frontend-vue/layers/dms-ui/app/entries/composables/confirm/useActionConfirm.ts +1 -0
  1359. package/frontend-vue/layers/dms-ui/app/entries/composables/containers/closingLayers.ts +1 -0
  1360. package/frontend-vue/layers/dms-ui/app/entries/composables/containers/context.ts +1 -0
  1361. package/frontend-vue/layers/dms-ui/app/entries/composables/containers/drawerSize.ts +1 -0
  1362. package/frontend-vue/layers/dms-ui/app/entries/composables/containers/useResizableSize.ts +1 -0
  1363. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/cellHelpers.ts +1 -0
  1364. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/metricCells.ts +1 -0
  1365. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/numberSuffix.ts +1 -0
  1366. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/registerDefaults.ts +1 -0
  1367. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/registerFieldTypes.ts +1 -0
  1368. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/relationBadges.ts +1 -0
  1369. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/relationFilter.ts +1 -0
  1370. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/relationRows.ts +1 -0
  1371. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/relationValue.ts +1 -0
  1372. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/twoLineCell.ts +1 -0
  1373. package/frontend-vue/layers/dms-ui/app/entries/composables/data-types/useColumnValueRenderer.ts +1 -0
  1374. package/frontend-vue/layers/dms-ui/app/entries/composables/files/useFileMetadata.ts +1 -0
  1375. package/frontend-vue/layers/dms-ui/app/entries/composables/form/createFormFields.ts +1 -0
  1376. package/frontend-vue/layers/dms-ui/app/entries/composables/form/enclosingForm.ts +1 -0
  1377. package/frontend-vue/layers/dms-ui/app/entries/composables/form/fieldSaved.ts +1 -0
  1378. package/frontend-vue/layers/dms-ui/app/entries/composables/form/fieldValueRule.ts +1 -0
  1379. package/frontend-vue/layers/dms-ui/app/entries/composables/form/floatingSaveBars.ts +1 -0
  1380. package/frontend-vue/layers/dms-ui/app/entries/composables/form/formControlErrors.ts +1 -0
  1381. package/frontend-vue/layers/dms-ui/app/entries/composables/form/formEntryContext.ts +1 -0
  1382. package/frontend-vue/layers/dms-ui/app/entries/composables/form/formEntryOrder.ts +1 -0
  1383. package/frontend-vue/layers/dms-ui/app/entries/composables/form/formFooter.ts +1 -0
  1384. package/frontend-vue/layers/dms-ui/app/entries/composables/form/formLayout.ts +1 -0
  1385. package/frontend-vue/layers/dms-ui/app/entries/composables/form/formRecordLoad.ts +1 -0
  1386. package/frontend-vue/layers/dms-ui/app/entries/composables/form/formSections.ts +1 -0
  1387. package/frontend-vue/layers/dms-ui/app/entries/composables/form/formValidation.ts +1 -0
  1388. package/frontend-vue/layers/dms-ui/app/entries/composables/form/keyValueRows.ts +1 -0
  1389. package/frontend-vue/layers/dms-ui/app/entries/composables/form/numberRange.ts +1 -0
  1390. package/frontend-vue/layers/dms-ui/app/entries/composables/form/readonlyValue.ts +1 -0
  1391. package/frontend-vue/layers/dms-ui/app/entries/composables/form/repeaterTable.ts +1 -0
  1392. package/frontend-vue/layers/dms-ui/app/entries/composables/form/serverFieldErrors.ts +1 -0
  1393. package/frontend-vue/layers/dms-ui/app/entries/composables/form/tagValues.ts +1 -0
  1394. package/frontend-vue/layers/dms-ui/app/entries/composables/form/toasterClearance.ts +1 -0
  1395. package/frontend-vue/layers/dms-ui/app/entries/composables/form/useInstantForm.ts +1 -0
  1396. package/frontend-vue/layers/dms-ui/app/entries/composables/global/searchShortcuts.ts +1 -0
  1397. package/frontend-vue/layers/dms-ui/app/entries/composables/instant-save/useInstantSave.ts +1 -0
  1398. package/frontend-vue/layers/dms-ui/app/entries/composables/layout/rowSidePanel.ts +1 -0
  1399. package/frontend-vue/layers/dms-ui/app/entries/composables/layout/sidePanelState.ts +1 -0
  1400. package/frontend-vue/layers/dms-ui/app/entries/composables/live/currentPageLive.ts +1 -0
  1401. package/frontend-vue/layers/dms-ui/app/entries/composables/live/formatElapsed.ts +1 -0
  1402. package/frontend-vue/layers/dms-ui/app/entries/composables/live/liveCadence.ts +1 -0
  1403. package/frontend-vue/layers/dms-ui/app/entries/composables/live/missedTally.ts +1 -0
  1404. package/frontend-vue/layers/dms-ui/app/entries/composables/live/pageLiveController.ts +1 -0
  1405. package/frontend-vue/layers/dms-ui/app/entries/composables/live/pageReadClock.ts +1 -0
  1406. package/frontend-vue/layers/dms-ui/app/entries/composables/live/usePageDataRefresh.ts +1 -0
  1407. package/frontend-vue/layers/dms-ui/app/entries/composables/live/usePageLiveHost.ts +1 -0
  1408. package/frontend-vue/layers/{dms-layout/app/build → dms-ui/app/entries}/composables/navigation/useCategoryNavCards.ts +6 -3
  1409. package/frontend-vue/layers/dms-ui/app/entries/composables/navigation/useNavBadges.ts +1 -0
  1410. package/frontend-vue/layers/dms-ui/app/entries/composables/page/blockAnchors.ts +1 -0
  1411. package/frontend-vue/layers/dms-ui/app/entries/composables/page/pageUrlValues.ts +1 -0
  1412. package/frontend-vue/layers/dms-ui/app/entries/composables/page-toolbar/pageToolbarContext.ts +1 -0
  1413. package/frontend-vue/layers/dms-ui/app/entries/composables/page-toolbar/toolbarControlHeight.ts +1 -0
  1414. package/frontend-vue/layers/dms-ui/app/entries/composables/period/periodComparisonControl.ts +1 -0
  1415. package/frontend-vue/layers/dms-ui/app/entries/composables/period/periodDisplay.ts +1 -0
  1416. package/frontend-vue/layers/dms-ui/app/entries/composables/period/periodQuery.ts +1 -0
  1417. package/frontend-vue/layers/dms-ui/app/entries/composables/period/periodShortLabels.ts +1 -0
  1418. package/frontend-vue/layers/dms-ui/app/entries/composables/period/usePeriodDraft.ts +1 -0
  1419. package/frontend-vue/layers/dms-ui/app/entries/composables/period/usePeriodLocation.ts +1 -0
  1420. package/frontend-vue/layers/dms-ui/app/entries/composables/shortcuts/useShortcutRegistry.ts +1 -0
  1421. package/frontend-vue/layers/dms-ui/app/entries/composables/table/constants.ts +1 -0
  1422. package/frontend-vue/layers/dms-ui/app/entries/composables/table/useRowScrollAnchor.ts +1 -0
  1423. package/frontend-vue/layers/dms-ui/app/entries/composables/table/useTable.ts +1 -0
  1424. package/frontend-vue/layers/dms-ui/app/entries/composables/table/useTableColumns.ts +1 -0
  1425. package/frontend-vue/layers/dms-ui/app/entries/composables/table/utils/archivedCount.ts +1 -0
  1426. package/frontend-vue/layers/dms-ui/app/entries/composables/table/utils/clearTableFilters.ts +1 -0
  1427. package/frontend-vue/layers/dms-ui/app/entries/composables/table/utils/columnOrder.ts +1 -0
  1428. package/frontend-vue/layers/dms-ui/app/entries/composables/table/utils/filterEditorValue.ts +1 -0
  1429. package/frontend-vue/layers/dms-ui/app/entries/composables/table/utils/formatFilterValue.ts +1 -0
  1430. package/frontend-vue/layers/dms-ui/app/entries/composables/table/utils/pageSizeOptions.ts +1 -0
  1431. package/frontend-vue/layers/dms-ui/app/entries/composables/table/utils/scrollEdges.ts +1 -0
  1432. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/displayRegistry.ts +1 -0
  1433. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/registerDefaultFunctions.ts +1 -0
  1434. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/types.ts +1 -0
  1435. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useAccumulatedPages.ts +1 -0
  1436. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useExpandedRowDetails.ts +1 -0
  1437. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useGroupedRows.ts +1 -0
  1438. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useMobileDisplay.ts +1 -0
  1439. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/usePersistedPagination.ts +1 -0
  1440. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableFooter.ts +1 -0
  1441. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableLinkedVisit.ts +1 -0
  1442. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableListData.ts +1 -0
  1443. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableLiveHold.ts +1 -0
  1444. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTablePreferences.ts +1 -0
  1445. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableRecordLink.ts +1 -0
  1446. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableReorder.ts +1 -0
  1447. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableRows.ts +1 -0
  1448. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableUrlTab.ts +1 -0
  1449. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableViewConfig.ts +1 -0
  1450. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableViewRowActions.ts +1 -0
  1451. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/useTableViews.ts +1 -0
  1452. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/bulkActions.ts +1 -0
  1453. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/card.ts +1 -0
  1454. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/chrome.ts +1 -0
  1455. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/columnVisibility.ts +1 -0
  1456. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/expandedRowProps.ts +1 -0
  1457. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/expandedRows.ts +1 -0
  1458. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/formTexts.ts +1 -0
  1459. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/groupedRows.ts +1 -0
  1460. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/linkedArrival.ts +1 -0
  1461. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/locateRow.ts +1 -0
  1462. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/pageArrival.ts +1 -0
  1463. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/pinnedRows.ts +1 -0
  1464. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/quickFilters.ts +1 -0
  1465. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/recordLink.ts +1 -0
  1466. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/reorder.ts +1 -0
  1467. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/sortableColumns.ts +1 -0
  1468. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/tableCounts.ts +1 -0
  1469. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/tableQuery.ts +1 -0
  1470. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/urlFilters.ts +1 -0
  1471. package/frontend-vue/layers/dms-ui/app/entries/composables/table-view/utils/views.ts +1 -0
  1472. package/frontend-vue/layers/dms-ui/app/entries/composables/unsaved-changes/formValue.ts +1 -0
  1473. package/frontend-vue/layers/dms-ui/app/entries/composables/unsaved-changes/registry.ts +1 -0
  1474. package/frontend-vue/layers/dms-ui/app/entries/i18n/locales/ui-en-GB.json.ts +1 -0
  1475. package/frontend-vue/layers/dms-ui/app/entries/i18n/locales/ui-fr-FR.json.ts +1 -0
  1476. package/frontend-vue/layers/dms-ui/app/entries/types/tree.ts +1 -0
  1477. package/frontend-vue/layers/dms-ui/app/entries/utils/accessibilityPreferences.ts +1 -0
  1478. package/frontend-vue/layers/dms-ui/app/entries/utils/addressSuggestions.ts +1 -0
  1479. package/frontend-vue/layers/dms-ui/app/entries/utils/blockPreview.ts +1 -0
  1480. package/frontend-vue/layers/dms-ui/app/entries/utils/categoryPages.ts +1 -0
  1481. package/frontend-vue/layers/dms-ui/app/entries/utils/characterCount.ts +1 -0
  1482. package/frontend-vue/layers/dms-ui/app/entries/utils/codeCells.ts +1 -0
  1483. package/frontend-vue/layers/dms-ui/app/entries/utils/codeHighlight.ts +1 -0
  1484. package/frontend-vue/layers/dms-ui/app/entries/utils/codeLanguages.ts +1 -0
  1485. package/frontend-vue/layers/dms-ui/app/entries/utils/codePalette.ts +1 -0
  1486. package/frontend-vue/layers/dms-ui/app/entries/utils/dispatchQuickActionTarget.ts +1 -0
  1487. package/frontend-vue/layers/dms-ui/app/entries/utils/eyebrow.ts +1 -0
  1488. package/frontend-vue/layers/dms-ui/app/entries/utils/fetchNotFound.ts +1 -0
  1489. package/frontend-vue/layers/dms-ui/app/entries/utils/fieldOptionsI18n.ts +1 -0
  1490. package/frontend-vue/layers/dms-ui/app/entries/utils/fileDownload.ts +1 -0
  1491. package/frontend-vue/layers/dms-ui/app/entries/utils/inputWidth.ts +1 -0
  1492. package/frontend-vue/layers/dms-ui/app/entries/utils/link.ts +1 -0
  1493. package/frontend-vue/layers/dms-ui/app/entries/utils/monoChip.ts +1 -0
  1494. package/frontend-vue/layers/dms-ui/app/entries/utils/navBadge.ts +1 -0
  1495. package/frontend-vue/layers/dms-ui/app/entries/utils/numberAdjustment.ts +1 -0
  1496. package/frontend-vue/layers/dms-ui/app/entries/utils/permissionPreview.ts +1 -0
  1497. package/frontend-vue/layers/dms-ui/app/entries/utils/quickActionTargets.ts +1 -0
  1498. package/frontend-vue/layers/dms-ui/app/entries/utils/responseWarning.ts +1 -0
  1499. package/frontend-vue/layers/dms-ui/app/entries/utils/rowClickTrigger.ts +1 -0
  1500. package/frontend-vue/layers/dms-ui/app/entries/utils/scrollWithin.ts +1 -0
  1501. package/frontend-vue/layers/dms-ui/app/entries/utils/selectionScope.ts +1 -0
  1502. package/frontend-vue/layers/dms-ui/app/entries/utils/shellParser.ts +1 -0
  1503. package/frontend-vue/layers/dms-ui/app/entries/utils/textLink.ts +1 -0
  1504. package/frontend-vue/layers/dms-ui/app/entries/utils/tileRow.ts +1 -0
  1505. package/frontend-vue/layers/dms-ui/app/entries/utils/tone.ts +1 -0
  1506. package/frontend-vue/layers/dms-ui/app/entries/utils/urlVariables.ts +1 -0
  1507. package/frontend-vue/layers/dms-ui/app/plugins/table-view-displays.ts +0 -5
  1508. package/frontend-vue/layers/dms-ui/app/types/quick-actions.ts +12 -5
  1509. package/frontend-vue/layers/dms-ui/app/types/shortcuts-aggregated.d.ts +5 -2
  1510. package/frontend-vue/layers/dms-ui/app/utils/blockRefresh.ts +1 -0
  1511. package/frontend-vue/layers/dms-ui/app/utils/cascader.ts +4 -3
  1512. package/frontend-vue/layers/dms-ui/app/utils/componentId.ts +0 -3
  1513. package/frontend-vue/layers/dms-ui/app/utils/fileConstraints.ts +6 -4
  1514. package/frontend-vue/layers/dms-ui/app/utils/metadataRetry.ts +11 -8
  1515. package/frontend-vue/layers/dms-ui/app/utils/overlayFocus.ts +0 -2
  1516. package/frontend-vue/layers/dms-ui/app/utils/rowClickAction.ts +3 -3
  1517. package/frontend-vue/layers/dms-ui/app/utils/semanticTint.ts +0 -5
  1518. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +1 -0
  1519. package/frontend-vue/package.json +3 -3
  1520. package/frontend-vue/scripts/check-autoimport-boundaries.mjs +277 -0
  1521. package/frontend-vue/scripts/check-disable-blocks.mjs +114 -0
  1522. package/frontend-vue/scripts/check-invariants.mjs +356 -0
  1523. package/frontend-vue/scripts/check-page-invariants.mjs +279 -0
  1524. package/frontend-vue/scripts/probes/capture-frontend-probe.cjs +21 -0
  1525. package/frontend-vue/scripts/probes/frontend-behavior.cjs +436 -0
  1526. package/frontend-vue/scripts/probes/frontend-legacy.cjs +471 -0
  1527. package/frontend-vue/scripts/probes/frontend-probe-controls.cjs +243 -0
  1528. package/frontend-vue/scripts/prove-comment-emit.mjs +142 -0
  1529. package/frontend-vue/scripts/prove-component-registration.mjs +173 -0
  1530. package/frontend-vue/scripts/test-autoimport-boundaries.mjs +144 -0
  1531. package/frontend-vue/server/private-options.ts +6 -5
  1532. package/package.json +11 -10
  1533. package/skills/dms/cases.json +52 -0
  1534. package/skills/dms-auth/cases.json +70 -0
  1535. package/skills/dms-best-practices/cases.json +82 -0
  1536. package/skills/dms-module/cases.json +62 -0
  1537. package/skills/dms-pages/SKILL.md +2 -2
  1538. package/skills/dms-pages/cases.json +96 -0
  1539. package/skills/dms-project/cases.json +88 -0
  1540. package/skills/dms-project/scripts/dms-dev-usage.sh +29 -0
  1541. package/skills/dms-project/scripts/dms-dev.sh +7 -29
  1542. package/dist/client-origin-cors.js.map +0 -1
  1543. package/dist/config.js.map +0 -1
  1544. package/dist/implementations/dms/dev-reload.js.map +0 -1
  1545. package/dist/implementations/dms/frontend-backend-proxies.js.map +0 -1
  1546. package/dist/implementations/dms/frontend-bootstrap.js.map +0 -1
  1547. package/dist/implementations/dms/frontend-modules.js.map +0 -1
  1548. package/dist/implementations/dms/frontend-public-endpoints.js.map +0 -1
  1549. package/dist/implementations/dms/frontend-ready.d.ts +0 -18
  1550. package/dist/implementations/dms/frontend-ready.js.map +0 -1
  1551. package/dist/implementations/dms/manifest.js.map +0 -1
  1552. package/dist/implementations/dms/warn-once.js.map +0 -1
  1553. package/dist/implementations/dms-notifications/registry.js.map +0 -1
  1554. package/dist/routes/auth/client-ip.js.map +0 -1
  1555. package/dist/routes/auth/constants.js.map +0 -1
  1556. package/dist/routes/auth/login-throttle.js.map +0 -1
  1557. package/dist/routes/auth/request-email-verification.js.map +0 -1
  1558. package/dist/startup-config.js.map +0 -1
  1559. package/dist/utils/sign-in-monitor.js.map +0 -1
  1560. package/dist/utils/workspace-notifications.js.map +0 -1
  1561. /package/dist/{client-origin-cors.d.ts → config/client-origin-cors.d.ts} +0 -0
  1562. /package/dist/{startup-config.d.ts → config/startup-config.d.ts} +0 -0
  1563. /package/dist/{utils → hooks/internal}/workspace-notifications.d.ts +0 -0
  1564. /package/dist/{implementations/dms → store/internal/frontend}/dev-reload.d.ts +0 -0
  1565. /package/dist/{implementations/dms → store/internal/frontend}/dev-reload.js +0 -0
  1566. /package/dist/{implementations/dms → store/internal/frontend}/frontend-backend-proxies.d.ts +0 -0
  1567. /package/dist/{implementations/dms → store/internal/frontend}/frontend-backend-proxies.js +0 -0
  1568. /package/dist/{implementations/dms → store/internal/frontend}/frontend-modules.d.ts +0 -0
  1569. /package/dist/{implementations/dms → store/internal/frontend}/frontend-public-endpoints.d.ts +0 -0
  1570. /package/dist/{implementations/dms → store/internal/frontend}/frontend-public-endpoints.js +0 -0
  1571. /package/dist/{implementations/dms → store/internal/frontend}/frontend-ready.js +0 -0
  1572. /package/dist/{implementations/dms → store/internal/frontend}/warn-once.d.ts +0 -0
  1573. /package/dist/{implementations/dms → store/internal/frontend}/warn-once.js +0 -0
  1574. /package/dist/{routes/auth/constants.d.ts → utils/auth-constants.d.ts} +0 -0
  1575. /package/dist/{routes/auth → utils}/client-ip.js +0 -0
  1576. /package/dist/{routes/auth → utils}/login-throttle.d.ts +0 -0
  1577. /package/dist/{implementations/dms-notifications/registry.d.ts → utils/notification-registry.d.ts} +0 -0
  1578. /package/dist/{routes/auth → utils}/request-email-verification.d.ts +0 -0
  1579. /package/frontend-vue/layers/{dms-auth/app/composables → dms-core/app/composables/auth}/useLogout.ts +0 -0
  1580. /package/frontend-vue/layers/{dms-ui → dms-core}/app/types/tone.ts +0 -0
  1581. /package/frontend-vue/layers/{dms-layout → dms-ui}/app/composables/useAppSidePanels.ts +0 -0
  1582. /package/frontend-vue/layers/{dms-layout → dms-ui}/app/composables/useSidePanel.ts +0 -0
@@ -1,227 +1,24 @@
1
1
  <script setup lang="ts" generic="T extends Data">
2
- import { get } from "@nuxt/ui/runtime/utils/index.js";
3
- import DmsBlockStatus from "../../build/components/blocks/BlockStatus.vue";
4
- import { readFetchNotFound } from "../../build/utils/fetchNotFound";
5
- import type {
6
- ColumnSizingState,
7
- ExpandedState,
8
- PaginationState,
9
- RowSelectionState,
10
- SortingState,
11
- Table,
12
- VisibilityState,
13
- } from "@tanstack/vue-table";
14
- import {
15
- refDebounced,
16
- until,
17
- useActiveElement,
18
- watchDebounced,
19
- } from "@vueuse/core";
20
- import {
21
- QUICK_ACTION_BUTTON_KEY,
22
- QUICK_ACTION_COMPONENT_KEY,
23
- QUICK_ACTION_QUERY_KEY,
24
- type QuickActionIntent,
25
- readQuickActionIntent,
26
- } from "../../types/quick-actions";
27
- import { registerQuickActionTarget } from "../../build/utils/quickActionTargets";
28
2
  import type {
29
- KanbanConfig,
30
3
  TableViewConfig,
31
4
  TableViewExpandableConfig,
32
5
  TableViewFooter,
33
6
  TableViewQuickFilter,
34
- TableViewListResponse,
35
- TableViewDisplayContext,
36
- TableViewDisplayConfig,
37
- TableViewExpandedRowProps,
38
7
  TableViewViewsConfig,
39
- TableViewGroupedConfig,
40
8
  TableViewEmptyStatesConfig,
41
9
  TableViewPaginationMode,
42
10
  TableViewSourceConfig,
43
11
  TableViewReorderConfig,
44
- TableViewTab,
45
- } from "../../composables/table-view/types";
46
- import {
47
- TABLE_DISPLAY_ID,
48
- CARDS_DISPLAY_ID,
49
- KANBAN_DISPLAY_ID,
50
- GROUPED_DISPLAY_ID,
51
- TableViewEvents,
52
12
  } from "../../composables/table-view/types";
53
- import {
54
- isEligibleKanbanColumn,
55
- KANBAN_DISPLAY_BRIDGE_KEY,
56
- } from "../../composables/table-view/kanban";
57
- import { useTableRowActions } from "../../build/composables/table-view/useTableViewRowActions";
58
- import { describeTableWriteError } from "../../build/composables/table-view/utils/writeError";
59
- import {
60
- buildTableQuery,
61
- isFilterEffective,
62
- } from "../../build/composables/table-view/utils/tableQuery";
63
- import { buildTableViewShortcuts } from "../../composables/table-view/shortcuts";
64
- import {
65
- expandedRowsOnListing,
66
- type ExpandedRowMap,
67
- nextExpandedRows,
68
- } from "../../build/composables/table-view/utils/expandedRows";
69
- import { resolveTableChrome } from "../../build/composables/table-view/utils/chrome";
70
- import {
71
- isSameSorting,
72
- isUnsortableFieldError,
73
- defaultSortingState,
74
- resolveDefaultSortConfig,
75
- sanitizeSorting,
76
- sortingOrDefault,
77
- sortableColumnIds,
78
- sortValueKind,
79
- } from "../../build/composables/table-view/utils/sortableColumns";
80
- import { selectedRowIds } from "../../build/composables/table-view/utils/bulkActions";
81
- import { isBulkAction } from "../../build/composables/actions/bulkSelection";
82
- import { selectionScopeKey } from "../../build/utils/selectionScope";
83
- import {
84
- isDeepLinkAction,
85
- resolveDeepLinkedRow,
86
- } from "../../build/composables/table-view/utils/recordLink";
87
- import {
88
- rowSidePanelOwnerKey,
89
- useRowSidePanelContent,
90
- } from "#dms-layout/app/build/composables/layout/rowSidePanel";
91
- import type { CustomRowAction } from "../../types/row-action";
92
- import {
93
- type QuickFilterItem,
94
- quickFilterMode,
95
- relationQuickFilterItems,
96
- relationQuickFilterSource,
97
- type ResolvedQuickFilter,
98
- staticQuickFilterItems,
99
- } from "../../build/composables/table-view/utils/quickFilters";
100
- import { useNavBadges } from "../../build/composables/navigation/useNavBadges";
101
- import {
102
- resolveRowClickAction,
103
- rowCustomActions,
104
- } from "../../utils/rowClickAction";
105
- import { usePermissionPreview } from "#dms-core/app/build/composables/auth/usePermissionPreview";
106
13
  import type { RowActionRule } from "#dms-core/app/types/row-action";
107
-
14
+ import type { TableViewLiveHoldOptions } from "#dms-core/app/types/live";
15
+ import DmsBlockStatus from "../../build/components/blocks/BlockStatus.vue";
108
16
  import UTable from "../../build/components/table/Table.vue";
109
17
  import ExpandedRowDetail from "../../build/components/table-view/ExpandedRowDetail.vue";
110
- import { buildExpandedRowProps } from "../../build/composables/table-view/utils/expandedRowProps";
111
- import {
112
- type ExpandedRowLoadState,
113
- useExpandedRowDetails,
114
- } from "../../build/composables/table-view/useExpandedRowDetails";
115
- import type {
116
- TableAccumulation,
117
- TableUrlFilter,
118
- TableViewSwitcherItem,
119
- } from "../../build/components/table/Table.vue";
120
- import {
121
- currentQuery,
122
- visibleUrlFilters,
123
- withoutQueryParam,
124
- } from "../../build/composables/table-view/utils/urlFilters";
125
- import {
126
- defineAsyncComponent,
127
- useTemplateRef,
128
- type Component,
129
- type ComponentPublicInstance,
130
- type WatchOptions,
131
- type WatchSource,
132
- } from "vue";
133
- import { useTableViewConfig } from "../../build/composables/table-view/useTableViewConfig";
134
- import {
135
- keptViewId,
136
- useTableViews,
137
- } from "../../build/composables/table-view/useTableViews";
138
- import { useGroupedRows } from "../../build/composables/table-view/useGroupedRows";
139
- import { useTableFooter } from "../../build/composables/table-view/useTableFooter";
140
- import { useAccumulatedPages } from "../../build/composables/table-view/useAccumulatedPages";
141
- import type { RowStep } from "../../build/composables/actions/rowNavigation";
142
- import { rowLocator } from "../../build/composables/table-view/utils/locateRow";
143
- import { usePersistedPagination } from "../../build/composables/table-view/usePersistedPagination";
144
- import { useTablePreferences } from "../../build/composables/table-view/useTablePreferences";
145
- import {
146
- isLinkedArrival,
147
- linkedArrivalPreferences,
148
- linkFollowingPreferences,
149
- linkKeyScope,
150
- urlFilterScope,
151
- } from "../../build/composables/table-view/utils/linkedArrival";
152
- import { pageArrivalKind } from "../../build/composables/table-view/utils/pageArrival";
153
- import { useTableLinkedVisit } from "../../build/composables/table-view/useTableLinkedVisit";
154
- import { useMobileDisplay } from "../../build/composables/table-view/useMobileDisplay";
155
- import type { Ref } from "vue";
156
- import type { TableField } from "#dms-core/app/build/composables/user/tablePreferences";
157
- import { useTableRows } from "../../build/composables/table-view/useTableRows";
158
- import { useRefreshTriggers } from "../../build/composables/blocks/useRefreshTriggers";
159
- import { refreshPageBlocks } from "../../utils/blockRefresh";
160
- import { useTableLiveHold } from "../../build/composables/table-view/useTableLiveHold";
161
- import type { TableViewLiveHoldOptions } from "../../types/live";
162
- import { usePageLive } from "../../composables/live/usePageLive";
163
18
  import LiveHoldBanner from "../../build/components/table-view/LiveHoldBanner.vue";
164
- import { useTableReorder } from "../../build/composables/table-view/useTableReorder";
165
- import {
166
- groupedOptionsFor,
167
- listTableSorting,
168
- orderGroupedRows,
169
- pickedTableSorting,
170
- type TableSortingInput,
171
- isGroupableColumn,
172
- } from "../../build/composables/table-view/utils/groupedRows";
173
- import {
174
- readTableUrlTab,
175
- useTableUrlTab,
176
- } from "../../build/composables/table-view/useTableUrlTab";
177
- import {
178
- buildTableCountQueries,
179
- isCountNarrowed,
180
- navBadgeCount,
181
- VIEW_COUNT_ID_PREFIX,
182
- type TableCountState,
183
- } from "../../build/composables/table-view/utils/tableCounts";
184
- import { viewFilters } from "../../build/composables/table-view/utils/views";
185
- import { useTableRecordLink } from "../../build/composables/table-view/useTableRecordLink";
186
- import TableViews, {
187
- type TableViewItem,
188
- } from "../../build/components/table/Views.vue";
189
- import {
190
- useTableCountsData,
191
- useTableListData,
192
- } from "../../build/composables/table-view/useTableListData";
193
- import { useTableDataChanges } from "../../composables/table-view/useTableDataChanges";
194
-
195
- const REALTIME_ROW_TOPIC_PREFIX = "tableview:row:";
196
- const REALTIME_PRESENCE_TOPIC_PREFIX = "tableview:presence:";
197
- const ROW_ID_DEFAULT_KEY = "_id";
198
- const KanbanDisplay = defineAsyncComponent(() => import("./KanbanDisplay.vue"));
199
-
200
- const REALTIME_EVENT_TYPE = {
201
- CREATED: "created",
202
- UPDATED: "updated",
203
- DELETED: "deleted",
204
- ACQUIRED: "acquired",
205
- RELEASED: "released",
206
- SNAPSHOT: "snapshot",
207
- } as const;
208
-
209
- interface RealtimePresenceActor {
210
- id: string;
211
- displayName?: string;
212
- avatarUrl?: string;
213
- sessionId: string;
214
- since?: number;
215
- }
216
-
217
- type RealtimePresenceMap = Record<string, RealtimePresenceActor[]>;
218
-
219
- /** A kept field of the table, its state, and its default. */
220
- // The default may move once mounted (a phone's display): read when written.
221
- type TableStatePreference = [TableField, Ref<unknown>, unknown];
19
+ import TableViews from "../../build/components/table/Views.vue";
20
+ import { useTableViewSetup } from "../../build/composables/table-view/tableViewSetup";
222
21
 
223
- // The backend options of a table view, declared here as well so the
224
- // component's runtime props never depend on resolving the imported config.
225
22
  interface TableViewProps<T extends Data> extends TableViewConfig<T> {
226
23
  /** Expandable rows: caret column + detail band (backend `expandable`). */
227
24
  expandable?: TableViewExpandableConfig;
@@ -260,2143 +57,92 @@ interface TableViewProps<T extends Data> extends TableViewConfig<T> {
260
57
  }
261
58
 
262
59
  const props = defineProps<TableViewProps<T>>();
263
-
264
60
  const {
265
- allColumns,
266
61
  listableColumns,
267
62
  initialVisibility,
268
63
  tableProps,
269
- location,
270
- caption,
271
- labelKey,
272
64
  enableTableExport,
273
- archiveMode,
274
- defaultFilters,
275
65
  customButtons,
276
- formComponents,
277
- formContainer,
278
- formPages,
279
- componentId,
280
- pageId,
281
- defaultSort,
282
- queryParamFilters,
283
- routeParamFilters,
284
- routeParams,
285
- tabs,
286
- resolvedDisplays,
287
- defaultDisplay,
288
- } = useTableViewConfig<T>(props);
289
-
290
- const route = useDmsRoute();
291
- const urlScope = {
292
- tableId: props.tableId,
293
- isSoleTableView: props.isSoleTableView,
294
- };
295
- const ALL_TAB_ID = "all";
296
-
297
- const keptPreferences = useTablePreferences(componentId, pageId);
298
- // A link naming a view, a tab, a record or a URL filter opens on the table's
299
- // defaults plus what it names, never over the state kept from the last visit
300
- // (which stays kept for the next plain visit), until the user makes the
301
- // state shown their own: a view, a tab, a filter or a sort they pick. Only a
302
- // reload (or Back) of the URL the table wrote for that state restores it.
303
- const isLinked = isLinkedArrival({
304
- query: route.query,
305
- urlScope,
306
- queryParamFilters,
307
- isVisit: pageArrivalKind() === "visit",
308
- rememberedTab: keptPreferences.get<string>("activeTab", ALL_TAB_ID),
309
- keptLinkScope: keptPreferences.get<string | undefined>(
310
- "linkScope",
311
- undefined,
312
- ),
313
- shownLink: keptPreferences.get<string | undefined>("shownLink", undefined),
314
- });
315
- const tablePreferences = linkFollowingPreferences(
316
- isLinked ? linkedArrivalPreferences(keptPreferences) : keptPreferences,
317
- {
318
- isLinkedArrival: isLinked,
319
- urlScope,
320
- linkScope: () => urlFilterScope(route.query, queryParamFilters),
321
- linkKeys: () => linkKeyScope(route.query, urlScope, queryParamFilters),
322
- // Read once the table is mounted, past the declarations below. A page
323
- // kept without its scope is restored as it is (`usePersistedPagination`).
324
- listingState: () => [
325
- ["activeView", keptViewId(activeViewId.value), undefined],
326
- ["activeTab", activeTabId.value, ALL_TAB_ID],
327
- ["columnFilters", columnFilters.value, []],
328
- ["sorting", sorting.value, defaultSortState],
329
- ["pagination", paginationState.value, DEFAULT_PAGINATION],
330
- ["paginationScope", undefined, undefined],
331
- ],
332
- },
333
- );
334
- onMounted(() => void tablePreferences.settleArrival());
335
- const { sendComponentEvent } = useComponentEvent(componentId);
336
- const { processI18n } = useTranslation();
337
-
338
- const kanbanEligibleColumns = allColumns.filter(isEligibleKanbanColumn);
339
- const kanbanGroupByOptions = kanbanEligibleColumns.map((column) => ({
340
- label: processI18n(column.header),
341
- value: column.accessorKey,
342
- }));
343
-
344
- const { displays: registeredDisplays, getById } = useTableViewDisplays();
345
-
346
- const offeredDisplayIds = new Set(resolvedDisplays.map((d) => d.id));
347
- // Where a stale or unavailable choice lands: the grid, unless the table view
348
- // drops it, then its default display.
349
- const fallbackDisplayId = offeredDisplayIds.has(TABLE_DISPLAY_ID)
350
- ? TABLE_DISPLAY_ID
351
- : defaultDisplay;
352
- const resolvedDisplay = (id: string): TableViewDisplayConfig | undefined =>
353
- resolvedDisplays.find((d) => d.id === id);
354
- const optionsForDisplay = (id: string): Record<string, unknown> | undefined =>
355
- resolvedDisplay(id)?.options;
356
- const kanbanOptions = optionsForDisplay(KANBAN_DISPLAY_ID) as
357
- | KanbanConfig
358
- | undefined;
359
- const groupedOptions = optionsForDisplay(GROUPED_DISPLAY_ID) as
360
- | TableViewGroupedConfig
361
- | undefined;
362
-
363
- // Stored under the legacy "viewMode" key (free migration of "table"/"kanban");
364
- // clamped to the offered set so a stale/removed id never renders an un-offered display.
365
- const persistedDisplay = tablePreferences.get<string>(
366
- "viewMode",
367
- defaultDisplay,
368
- );
369
- // A default display that draws its whole interface (no table chrome, hence no
370
- // switcher) is the only way into the page: a saved choice cannot override it.
371
- const isDefaultDisplayStandalone =
372
- resolvedDisplay(defaultDisplay)?.capabilities?.header === false;
373
- const activeDisplayId = ref<string>(
374
- isDefaultDisplayStandalone
375
- ? defaultDisplay
376
- : offeredDisplayIds.has(persistedDisplay)
377
- ? persistedDisplay
378
- : fallbackDisplayId,
379
- );
380
-
381
- /** A display the backend config renders by itself, with no client plugin. */
382
- const isConfigRenderedDisplay = (id: string): boolean =>
383
- !!resolvedDisplay(id)?.component;
384
-
385
- const availableDisplays = computed<TableViewSwitcherItem[]>(() =>
386
- registeredDisplays.value
387
- .filter((display) => offeredDisplayIds.has(display.id))
388
- .filter(
389
- (display) =>
390
- !display.isAvailable ||
391
- display.isAvailable({
392
- columns: allColumns,
393
- options: optionsForDisplay(display.id),
394
- }),
395
- )
396
- .map(({ id, label, icon }) => ({ id, label, icon })),
397
- );
398
-
399
- // SSR-safe: capabilities + self-managed flag come from config, not the
400
- // client-only registry, so the chrome and list-query decision match across SSR.
401
- // A hand-ordered table is listed by its position: no sort to pick.
402
- const reorderConfig = props.reorder;
403
- const activeCapabilities = computed(() => {
404
- const capabilities = resolveDisplayCapabilities(
405
- resolvedDisplay(activeDisplayId.value)?.capabilities,
406
- );
407
- return reorderConfig ? { ...capabilities, sorting: false } : capabilities;
408
- });
409
-
410
- const isActiveDisplaySelfManaged = computed(
411
- () => !!resolvedDisplay(activeDisplayId.value)?.selfManagedData,
412
- );
413
-
414
- // Static fallback for built-in displays whose config entry carries options but
415
- // no component (kanban); the registry confirms the same component client-side.
416
- const STATIC_DISPLAY_COMPONENTS: Record<string, Component> = {
417
- [KANBAN_DISPLAY_ID]: KanbanDisplay,
418
- };
419
-
420
- const resolveDisplayComponentRef = (
421
- component: Component | ComponentInfo | undefined,
422
- ): Component | string | undefined => {
423
- if (!component) return undefined;
424
- if (typeof component === "object" && "componentName" in component) {
425
- const name = component.componentName;
426
- return name ? resolveDmsComponent(name) || name : undefined;
427
- }
428
- return component;
429
- };
430
-
431
- const activeDisplayComponent = computed<Component | string | undefined>(() => {
432
- const id = activeDisplayId.value;
433
- if (id === TABLE_DISPLAY_ID || !offeredDisplayIds.has(id)) return undefined;
434
- // The instance's own component wins over the registered one: the server
435
- // renders it, so the client must hydrate the same tree.
436
- const fromConfig = resolvedDisplay(id)?.component;
437
- if (fromConfig) return resolveDisplayComponentRef(fromConfig);
438
- const registered = getById(id)?.component;
439
- if (registered) return resolveDisplayComponentRef(registered);
440
- return STATIC_DISPLAY_COMPONENTS[id];
441
- });
442
-
443
- const defaultKanbanGroupBy = kanbanOptions?.groupByField ?? "";
444
- const kanbanGroupBy = ref<string>(defaultKanbanGroupBy);
445
- // A saved preference may point to a column that no longer exists or is no
446
- // longer eligible after a backend config change.
447
- tablePreferences.restore(
448
- "kanbanGroupBy",
66
+ kanbanGroupByOptions,
67
+ activeDisplayId,
68
+ availableDisplays,
69
+ activeCapabilities,
70
+ activeDisplayComponent,
449
71
  kanbanGroupBy,
450
- (field) =>
451
- !kanbanOptions ||
452
- kanbanEligibleColumns.some((c) => c.accessorKey === field),
453
- );
454
-
455
- const DEFAULT_DENSITY = "default";
456
- // The module's density is the default; the user's pick in the ⋯ menu is kept
457
- // with the rest of the table's state.
458
- const defaultDensity = props.density ?? DEFAULT_DENSITY;
459
- const density = ref<"default" | "compact">(defaultDensity);
460
- tablePreferences.restore("density", density);
461
-
462
- const DEFAULT_PAGE_SIZE = 10;
463
- const DEFAULT_PAGINATION: PaginationState = {
464
- pageIndex: 0,
465
- pageSize: props.pageSize ?? DEFAULT_PAGE_SIZE,
466
- };
467
- const resolvedChrome = resolveTableChrome(props.layout, {
468
- hasCaption: !!caption,
469
- isSearchable: !!props.searchable,
470
- isFilterable: allColumns.some((column) => column.enableColumnFilter),
471
- });
472
- const GLOBAL_FILTER_DEBOUNCE_MS = 400;
473
-
474
- const DEFAULT_FILTER_MODE = "is";
475
-
476
- const queryParamHiddenFilters = computed<TableFilter[]>(() => {
477
- if (!queryParamFilters) return [];
478
-
479
- return Object.entries(queryParamFilters)
480
- .filter(([param]) => route.query[param] !== undefined)
481
- .map(([param, config]) => ({
482
- accessorKey: config.field,
483
- mode: config.mode || DEFAULT_FILTER_MODE,
484
- value: route.query[param] as string,
485
- }));
486
- });
487
-
488
- const shownUrlFilters = computed<TableUrlFilter[]>(() =>
489
- visibleUrlFilters(queryParamFilters, route.query as Record<string, unknown>),
490
- );
491
-
492
- // Rebuilt from the URL the browser shows: a `?record=` a closed drawer
493
- // removed in place must not come back with the visit.
494
- const removeUrlFilter = (param: string) =>
495
- router.replace({
496
- query: withoutQueryParam(currentQuery(route.query), param),
497
- });
498
-
499
- const routeParamHiddenFilters = computed<TableFilter[]>(() => {
500
- if (!routeParamFilters || !routeParams) return [];
501
-
502
- return Object.entries(routeParamFilters)
503
- .filter(([param]) => routeParams[param] !== undefined)
504
- .map(([param, config]) => ({
505
- accessorKey: config.field,
506
- mode: config.mode || DEFAULT_FILTER_MODE,
507
- value: routeParams[param] as string,
508
- }));
509
- });
510
-
511
- // A hidden filter's value changed with the URL, in place or through a
512
- // remount: the page reached among the previous rows lists from page 1.
513
- const paginationState = usePersistedPagination({
514
- preferences: tablePreferences,
515
- defaults: DEFAULT_PAGINATION,
516
- scope: () => [queryParamHiddenFilters.value, routeParamHiddenFilters.value],
517
- });
518
- const rowSelect = ref<RowSelectionState>({});
519
- // A column's grid header, for the sort messages.
520
- const columnLabel = (id: string): string => {
521
- const column = allColumns.find((c) => (c.id ?? c.accessorKey) === id);
522
- return column ? processI18n(column.header) : id;
523
- };
524
-
525
- // The list route sorts on one `@Sortable()` column and refuses any other key
526
- // with a 400 that would leave the table on its error panel: every sort it is
527
- // sent (default, saved, pasted, picked) is checked against the columns first.
528
- const declaredSortableIds = sortableColumnIds(allColumns);
529
- // Columns the route refused although declared sortable (see the recovery
530
- // below): a backend change since the page loaded.
531
- const refusedSortIds = ref<string[]>([]);
532
- const sortableIds = computed(
533
- () =>
534
- new Set(
535
- [...declaredSortableIds].filter(
536
- (id) => !refusedSortIds.value.includes(id),
537
- ),
538
- ),
539
- );
540
-
541
- // The grouped display's column, picked in the options menu as the kanban's
542
- // is: the rows of a group follow each other only when the route sorts on it.
543
- const groupedGroupByOptions = groupedOptions
544
- ? allColumns
545
- .filter(
546
- (column) =>
547
- column.accessorKey === groupedOptions.groupByField ||
548
- (isGroupableColumn(column) &&
549
- declaredSortableIds.has(column.accessorKey)),
550
- )
551
- .map((column) => ({
552
- label: processI18n(column.header),
553
- value: column.accessorKey,
554
- }))
555
- : [];
556
- const defaultGroupedGroupBy = groupedOptions?.groupByField ?? "";
557
- const groupedGroupBy = ref<string>(defaultGroupedGroupBy);
558
- tablePreferences.restore(
559
- "groupedGroupBy",
72
+ density,
73
+ resolvedChrome,
74
+ queryParamHiddenFilters,
75
+ shownUrlFilters,
76
+ removeUrlFilter,
77
+ paginationState,
78
+ rowSelect,
79
+ groupedGroupByOptions,
560
80
  groupedGroupBy,
561
- (field) =>
562
- !groupedOptions || groupedGroupByOptions.some((o) => o.value === field),
563
- );
564
- const activeGroupedOptions = computed<TableViewGroupedConfig | undefined>(
565
- () =>
566
- groupedOptions &&
567
- groupedOptionsFor(groupedOptions, groupedGroupBy.value, allColumns),
568
- );
569
- // The declared default sort when the route accepts it; without one, the
570
- // sortable creation date, newest first, rather than the database's natural
571
- // order (see `resolveDefaultSortConfig`).
572
- const tableDefaultSort = resolveDefaultSortConfig(
573
- defaultSort,
574
- declaredSortableIds,
575
- import.meta.env.DEV ? (message) => console.warn(message) : undefined,
576
- );
577
- const defaultSortState: SortingState = defaultSortingState(tableDefaultSort);
578
- // The toolbar sort menu names the default sort even when its field is not a
579
- // displayed column.
580
- const defaultSortLabel = tableDefaultSort
581
- ? columnLabel(tableDefaultSort.field)
582
- : undefined;
583
- const defaultSortKind = tableDefaultSort
584
- ? sortValueKind(
585
- allColumns.find((c) => (c.id ?? c.accessorKey) === tableDefaultSort.field)
586
- ?.type?.id,
587
- )
588
- : undefined;
589
- // A hand-ordered table has no sort to pick: a sort saved before it was
590
- // ordered by hand is not read back.
591
- const sorting = ref<SortingState>(
592
- reorderConfig
593
- ? defaultSortState
594
- : sortingOrDefault(
595
- tablePreferences.get<SortingState>("sorting", defaultSortState),
596
- declaredSortableIds,
597
- defaultSortState,
598
- ),
599
- );
600
-
601
- const savedFilters = tablePreferences.get<TableFilter[]>("columnFilters", []);
602
-
603
- const buildPinnedFilters = (): TableFilter[] =>
604
- (defaultFilters || []).map((def) => {
605
- const saved = savedFilters.find((f) => f.accessorKey === def.accessorKey);
606
- return {
607
- accessorKey: def.accessorKey,
608
- mode: def.mode,
609
- value: saved ? saved.value : def.value,
610
- pinned: true,
611
- initialValue: def.value,
612
- };
613
- });
614
-
615
- const pinnedKeys = new Set((defaultFilters || []).map((f) => f.accessorKey));
616
- const manualFilters = savedFilters
617
- .filter((f) => !pinnedKeys.has(f.accessorKey))
618
- .map((f) => ({ ...f, pinned: false }));
619
- const initialFilters = [...buildPinnedFilters(), ...manualFilters];
620
- // The pinned filters at their declared value: what a view leaves out of them.
621
- const pinnedDefaultFilters: TableFilter[] = (defaultFilters || []).map(
622
- (filter) => ({
623
- accessorKey: filter.accessorKey,
624
- mode: filter.mode,
625
- value: filter.value,
626
- pinned: true,
627
- initialValue: filter.value,
628
- }),
629
- );
630
-
631
- const columnFilters = ref<TableFilter[]>(initialFilters);
632
- const columnVisibility = ref<VisibilityState>(
633
- tablePreferences.get<VisibilityState>("columnVisibility", initialVisibility),
634
- );
635
- const columnSizing = ref<ColumnSizingState>({});
636
- tablePreferences.restore("columnSizing", columnSizing);
637
- const columnOrder = ref<string[]>([]);
638
- tablePreferences.restore("columnOrder", columnOrder, Array.isArray);
639
- const hasEmptyDefaultFilter = (defaultFilters || []).some(
640
- (f) => f.value === undefined || f.value === null || f.value === "",
641
- );
642
- const filtersRowOpen = ref<boolean>(hasEmptyDefaultFilter);
643
- tablePreferences.restore("filtersOpen", filtersRowOpen);
644
- const globalFilter = shallowRef<string>();
645
- const globalFilterDebounced = refDebounced(
81
+ tableDefaultSort,
82
+ defaultSortLabel,
83
+ defaultSortKind,
84
+ sorting,
85
+ columnFilters,
86
+ columnVisibility,
87
+ columnSizing,
88
+ columnOrder,
89
+ filtersRowOpen,
646
90
  globalFilter,
647
- GLOBAL_FILTER_DEBOUNCE_MS,
648
- );
649
- const showArchived = ref(false);
650
-
651
- // The display the table counts as its default: the phone's `mobileDisplay`
652
- // once applied (see `useMobileDisplay` below).
653
- const displayDefault = ref(
654
- offeredDisplayIds.has(defaultDisplay) ? defaultDisplay : fallbackDisplayId,
655
- );
656
-
657
- // Views: named states of the whole table, the module's and the user's own.
658
- const {
659
- items: tableViewItems,
91
+ showArchived,
660
92
  activeViewId,
661
- activeView,
662
- isModified: isViewModified,
93
+ isViewModified,
663
94
  canSaveViews,
664
95
  selectView,
665
- openLinkedView,
666
96
  resetView,
667
97
  saveView,
668
98
  saveAsNewView,
669
99
  deleteView,
670
- } = useTableViews({
671
- views: props.views,
672
- defaults: {
673
- pinnedFilters: pinnedDefaultFilters,
674
- sorting: defaultSortState,
675
- visibility: initialVisibility,
676
- columnOrder: listableColumns.map(
677
- (column) => column.id ?? column.accessorKey,
678
- ),
679
- // Read when a view opens: a phone's `mobileDisplay` once applied.
680
- get display() {
681
- return displayDefault.value;
682
- },
683
- density: props.density ?? DEFAULT_DENSITY,
684
- displays: offeredDisplayIds,
685
- },
686
- state: {
687
- columnFilters,
688
- globalFilter,
689
- sorting,
690
- columnVisibility,
691
- columnOrder,
692
- display: activeDisplayId,
693
- density,
694
- pagination: paginationState,
695
- },
696
- preferences: tablePreferences,
697
- urlScope,
698
- });
699
-
700
- // A phone opens on the table's `mobileDisplay` (cards rather than a grid cut
701
- // after its first columns) unless a display was chosen: saved, fixed by the
702
- // open view, or the only way in.
703
- useMobileDisplay({
704
- mobileDisplay: props.mobileDisplay,
705
- defaultDisplay: displayDefault,
706
- offered: offeredDisplayIds,
707
- display: activeDisplayId,
708
- activeView,
709
- isDisplayChosen: () =>
710
- isDefaultDisplayStandalone ||
711
- tablePreferences.get<string | undefined>("viewMode", undefined) !==
712
- undefined,
713
- });
714
-
715
- const { t, te, locale } = useI18n();
716
-
717
- // A tab named by the URL wins over the one kept from the last visit.
718
- const activeTabId = ref<string>(
719
- readTableUrlTab(route.query, urlScope) ??
720
- tablePreferences.get<string>("activeTab", ALL_TAB_ID),
721
- );
722
-
723
- interface ResolvedTab {
724
- id: string;
725
- label: string;
726
- filters: TableFilter[];
727
- icon?: string;
728
- textColor?: string;
729
- iconColor?: string;
730
- /** Link tab: the page it opens. */
731
- to?: string;
732
- toPage?: string;
733
- countFrom?: string;
734
- navBadge?: TableViewTab["navBadge"];
735
- }
736
-
737
- // A configured "all" tab stands in for the implicit one, at its own place.
738
- const hasConfiguredAllTab = (tabs ?? []).some((tab) => tab.id === ALL_TAB_ID);
739
-
740
- const resolvedTabs = computed<ResolvedTab[]>(() => {
741
- // Tabs are a transverse-but-table-shaped concept; displays that opt out of the
742
- // `tabs` capability (e.g. kanban) hide them and have their own grouping.
743
- if (!activeCapabilities.value.tabs) return [];
744
- if (!tabs || tabs.length === 0) return [];
745
- const implicitAll: ResolvedTab[] = hasConfiguredAllTab
746
- ? []
747
- : [{ id: ALL_TAB_ID, label: t("dms.table.tabs.all"), filters: [] }];
748
- return [
749
- ...implicitAll,
750
- ...tabs.map((tab) => ({
751
- id: tab.id,
752
- label: processI18n(tab.label),
753
- // A link tab filters nothing: it opens another page.
754
- filters: tab.filter && !tab.to ? [{ ...tab.filter }] : [],
755
- icon: tab.icon,
756
- textColor: tab.textColor,
757
- iconColor: tab.iconColor,
758
- to: tab.to,
759
- toPage: tab.toPage,
760
- countFrom: tab.countFrom,
761
- navBadge: tab.navBadge,
762
- })),
763
- ];
764
- });
765
-
766
- const activeTabFilters = computed<TableFilter[]>(() => {
767
- const tab = resolvedTabs.value.find((t) => t.id === activeTabId.value);
768
- return tab?.filters || [];
769
- });
770
-
771
- const isOpenableTab = (tabId: string) =>
772
- resolvedTabs.value.some((tab) => !tab.to && tab.id === tabId);
773
-
774
- useTableUrlTab({
775
- route,
776
- urlScope,
777
100
  activeTabId,
778
- isOpenable: isOpenableTab,
779
- });
780
-
781
- // A link to this page while it is shown opens like a linked arrival: on the
782
- // table's defaults plus what it names, leaving the kept state as it was.
783
- useTableLinkedVisit({
784
- route,
785
- urlScope,
786
- queryParamFilters,
787
- activeView: () => activeViewId.value,
788
- activeTab: () => activeTabId.value,
789
- canOpenView: (id) => tableViewItems.value.some((view) => view.id === id),
790
- canOpenTab: isOpenableTab,
791
- follow: (query) => {
792
- void tablePreferences.followLink(() => {
793
- openLinkedView(query);
794
- const tab = readTableUrlTab(query, urlScope);
795
- activeTabId.value = tab && isOpenableTab(tab) ? tab : ALL_TAB_ID;
796
- });
797
- },
798
- });
799
-
800
- watch(resolvedTabs, (next) => {
801
- if (next.length === 0) return;
802
- if (!next.some((tab) => !tab.to && tab.id === activeTabId.value)) {
803
- activeTabId.value = ALL_TAB_ID;
804
- }
805
- });
806
-
807
- const { $authFetch } = useAuthFetch();
808
- // The controller's routes, or a `TableView.fromSource` table's route.
809
- const tableRows = useTableRows<T>({
810
- api: $authFetch,
811
- location,
812
- source: props.source,
813
- columns: props.columns,
814
- route: () => ({
815
- routeParams: props.routeParams,
816
- routeQuery: route.query as Record<string, unknown>,
817
- }),
818
- // Groups keep their rows together: the grouped display pins nothing.
819
- pinnedRows: () => (isGroupedDisplay.value ? undefined : props.pinnedRows),
820
- });
821
- // Quick filters: dropdowns of the toolbar over a column's values (a select's
822
- // items, a boolean, the rows a relation points to), writing that column's
823
- // filter like the filters row does.
824
- const { getDataType } = useDataTypes();
825
- const relationQuickFilterValues = ref<Record<string, QuickFilterItem[]>>({});
826
- // Relation values load after mount: until then their buttons hold their place.
827
- const relationQuickFiltersLoaded = ref(false);
828
- const quickFilterDefinitions = (props.quickFilters ?? []).map((filter) => {
829
- const column = allColumns.find(
830
- (candidate) => candidate.accessorKey === filter.field,
831
- );
832
- return {
833
- filter,
834
- column,
835
- mode: quickFilterMode(column, filter.mode),
836
- items: staticQuickFilterItems(column, processI18n),
837
- source: relationQuickFilterSource(column, getDataType),
838
- };
839
- });
840
-
841
- const RELATION_QUICK_FILTER_LIMIT = 200;
842
-
843
- const loadRelationQuickFilters = async () => {
844
- await Promise.allSettled(
845
- quickFilterDefinitions
846
- .filter((definition) => !definition.items && definition.source)
847
- .map(async ({ filter, source }) => {
848
- try {
849
- const response = await $authFetch<
850
- TableViewListResponse<Record<string, unknown>>
851
- >(source!.searchUrl, {
852
- query: { limit: RELATION_QUICK_FILTER_LIMIT },
853
- });
854
- relationQuickFilterValues.value = {
855
- ...relationQuickFilterValues.value,
856
- [filter.field]: relationQuickFilterItems(response.results, source!),
857
- };
858
- } catch {
859
- // A picker the caller may not read just stays out of the toolbar.
860
- }
861
- }),
862
- );
863
- relationQuickFiltersLoaded.value = true;
864
- };
865
-
866
- // A quick filter with nothing to pick is left out of the toolbar; one whose
867
- // relation values are still loading shows disabled, holding its place.
868
- const resolvedQuickFilters = computed<ResolvedQuickFilter[]>(() =>
869
- quickFilterDefinitions
870
- .map(({ filter, column, mode, items, source }) => ({
871
- field: filter.field,
872
- label: processI18n(filter.label ?? column?.header ?? filter.field),
873
- icon: filter.icon ?? "i-ph-funnel",
874
- allLabel: filter.allLabel
875
- ? processI18n(filter.allLabel)
876
- : t("dms.table.quick_filter.all"),
877
- mode,
878
- items: items ?? relationQuickFilterValues.value[filter.field] ?? [],
879
- pending: !items && !!source && !relationQuickFiltersLoaded.value,
880
- }))
881
- .filter((filter) => filter.items.length > 0 || filter.pending),
882
- );
883
-
884
- const hiddenFilters = computed<TableFilter[]>(() => [
885
- ...queryParamHiddenFilters.value,
886
- ...routeParamHiddenFilters.value,
887
- ...activeTabFilters.value,
888
- ]);
889
-
890
- const queryParamDefaults = computed<Record<string, unknown> | undefined>(() => {
891
- if (!queryParamFilters && !routeParamFilters) return undefined;
892
-
893
- const defaults: Record<string, unknown> = {};
894
- if (queryParamFilters) {
895
- for (const [param, config] of Object.entries(queryParamFilters)) {
896
- const value = route.query[param];
897
- if (value !== undefined) {
898
- defaults[config.field] = value;
899
- }
900
- }
901
- }
902
- if (routeParamFilters && routeParams) {
903
- for (const [param, config] of Object.entries(routeParamFilters)) {
904
- const value = routeParams[param];
905
- if (value !== undefined) {
906
- defaults[config.field] = value;
907
- }
908
- }
909
- }
910
-
911
- return Object.keys(defaults).length > 0 ? defaults : undefined;
912
- });
913
-
914
- // A display that hides a transverse control (capability off) must not silently
915
- // keep applying that control's persisted state to the shared query.
916
- const effectiveColumnFilters = computed<TableFilter[]>(() =>
917
- activeCapabilities.value.filters
918
- ? columnFilters.value
919
- : columnFilters.value.filter((f) => f.pinned),
920
- );
921
- const effectiveGlobalFilter = computed(() =>
922
- activeCapabilities.value.search ? globalFilterDebounced.value : undefined,
923
- );
924
- const isGroupedDisplay = computed(
925
- () => activeDisplayId.value === GROUPED_DISPLAY_ID && !!groupedOptions,
926
- );
927
- const sortingInput = computed<TableSortingInput>(() => ({
928
- reorderField: reorderConfig?.field,
929
- grouped: isGroupedDisplay.value ? activeGroupedOptions.value : undefined,
930
- canSort: activeCapabilities.value.sorting,
931
- sorting: sorting.value,
932
- defaultSorting: defaultSortState,
933
- }));
934
- // The order the rows are wanted in; the grouped display lists them on the
935
- // grouped column and orders each group by it (`shownResults`).
936
- const pickedSorting = computed(() => pickedTableSorting(sortingInput.value));
937
- const effectiveSorting = computed<SortingState>(() => {
938
- const listed = listTableSorting(sortingInput.value);
939
- // The hand order is kept whole: its field need not be a sortable column.
940
- return reorderConfig && !sortingInput.value.grouped
941
- ? listed
942
- : sanitizeSorting(listed, sortableIds.value);
943
- });
944
-
945
- // A feed grows by pages (`loadMore`, `infinite`) rather than paging.
946
- const paginationMode = props.pagination ?? "pages";
947
- const { isAccumulating, requestedPagination, loadNextPage } =
948
- useAccumulatedPages({
949
- mode: paginationMode,
950
- pagination: paginationState,
951
- resetOn: [
952
- effectiveSorting,
953
- effectiveColumnFilters,
954
- hiddenFilters,
955
- effectiveGlobalFilter,
956
- showArchived,
957
- ],
958
- });
959
-
960
- const queryRequest = computed(() =>
961
- buildTableQuery({
962
- pagination: requestedPagination.value,
963
- sorting: effectiveSorting.value,
964
- columnFilters: effectiveColumnFilters.value,
965
- hiddenFilters: hiddenFilters.value,
966
- globalFilter: effectiveGlobalFilter.value,
967
- }),
968
- );
969
- const archiveQuery = computed(() =>
970
- archiveMode ? { showArchived: showArchived.value } : {},
971
- );
972
-
973
- // The row a side panel has open, which the grid highlights.
974
- const rowSidePanel = useRowSidePanelContent();
975
- const rowSidePanelOwner = rowSidePanelOwnerKey(pageId!, componentId!);
976
- const openRowId = computed(() =>
977
- rowSidePanel.value?.ownerKey === rowSidePanelOwner
978
- ? rowSidePanel.value.rowKey
979
- : undefined,
980
- );
981
-
982
- // The gate is set up with the other refresh triggers below; the hold only
983
- // reads it once the table is on screen.
984
- const NEW_ROWS_COUNT_ID = "liveHold:new";
985
- const tableRoot = useTemplateRef<ComponentPublicInstance>("tableRoot");
986
- const liveHold = useTableLiveHold({
987
- liveHold: props.liveHold,
988
- isSource: tableRows.isSource,
989
- gate: () => liveGate,
990
- signals: {
991
- isRowOpen: () => openRowId.value !== undefined,
992
- isSearching: () => !!effectiveGlobalFilter.value,
993
- isSorted: () => !isSameSorting(effectiveSorting.value, defaultSortState),
994
- tableElement: () => tableRoot.value?.$el ?? null,
995
- },
996
- // The pill counts the rows the table would list, on its own count route:
997
- // the rows its tab, search and filters match now, less those it holds.
998
- newRows: {
999
- heldList: () => data.value,
1000
- countNow: async (signal) => {
1001
- const counts = await tableRows.countBatch(
1002
- [
1003
- {
1004
- id: NEW_ROWS_COUNT_ID,
1005
- query: {
1006
- ...buildTableQuery({
1007
- pagination: { pageIndex: 0, pageSize: 0 },
1008
- sorting: [],
1009
- columnFilters: effectiveColumnFilters.value,
1010
- hiddenFilters: hiddenFilters.value,
1011
- globalFilter: effectiveGlobalFilter.value,
1012
- }),
1013
- ...archiveQuery.value,
1014
- },
1015
- },
1016
- ],
1017
- signal,
1018
- );
1019
- return counts[NEW_ROWS_COUNT_ID];
1020
- },
1021
- },
1022
- });
1023
-
1024
- // The list, its counters and its footer figures load in parallel: a server
1025
- // render waits for each before rendering, whether or not the setup awaits it.
1026
- const { data, status, error, refresh } = useTableListData<T>({
1027
- componentId,
1028
- pageId,
1029
- rows: tableRows,
1030
- query: queryRequest,
1031
- archiveQuery,
1032
- isSelfManaged: isActiveDisplaySelfManaged,
1033
- heldQuery: liveHold.heldQuery,
1034
- });
1035
-
1036
- // The failure of the last answer. The async data keeps it while the next run
1037
- // is in flight; the table shows that run (its skeleton, or the rows it has)
1038
- // rather than the failure it may replace.
1039
- const settledError = computed(() =>
1040
- status.value === "pending" ? null : error.value,
1041
- );
1042
-
1043
- // Nothing listed yet (a client navigation paints before the first page
1044
- // arrives): the table draws its skeleton, never the empty state.
1045
- const isFirstPageLoading = computed(
1046
- () => data.value === null && !settledError.value,
1047
- );
1048
- const isListLoading = computed(
1049
- () => status.value === "pending" || isFirstPageLoading.value,
1050
- );
1051
-
1052
- // A refused or failed list query must show as an error, never as an empty
1053
- // table: "no data" on a 403 would tell a blocked caller there is nothing
1054
- // to see.
1055
- // Always a key the panel can resolve. The backend body is a message key by
1056
- // contract, but not every one is translated (and a proxy error carries prose
1057
- // or HTML, which must never reach the screen); the HTTP status is the fallback
1058
- // that keeps a refusal distinguishable from a server failure.
1059
- const listLoadError = computed(() => {
1060
- const failure = settledError.value;
1061
- if (!failure) return undefined;
1062
- const message = resolveApiErrorMessage(failure);
1063
- if (te(`${message}.description`) || te(message)) return message;
1064
- const status = (failure as { statusCode?: number }).statusCode;
1065
- return status && te(`error.${status}.description`)
1066
- ? `error.${status}`
1067
- : "error.500";
1068
- });
1069
-
1070
- // A list answering 404 names a resource that does not exist (the workspace
1071
- // its rows belong to was deleted): no retry fixes it, so the table gives way
1072
- // to the not-found state blocks show, with what the 404 said.
1073
- const listNotFound = computed(() => readFetchNotFound(settledError.value));
1074
-
1075
- // useDmsAsyncData keeps the previous result when a refetch fails, so rows kept
1076
- // on screen would masquerade as the newly requested page/filter. Hide them
1077
- // while the latest query is in error; the error panel takes their place.
1078
- // Every consumer acting on visible rows (table, displays, selection
1079
- // shortcuts) must read the shown refs, never `data` directly.
1080
- const shownData = computed(() =>
1081
- listLoadError.value ? undefined : data.value,
1082
- );
1083
- const shownResults = computed(() => {
1084
- const results = shownData.value?.results;
1085
- const grouped = activeGroupedOptions.value;
1086
- return results && isGroupedDisplay.value && grouped
1087
- ? orderGroupedRows(results, grouped, pickedSorting.value, locale.value)
1088
- : results;
1089
- });
1090
-
1091
- // Rows selected before the failure can no longer be seen or verified, yet the
1092
- // selection toolbar would keep offering delete/archive/export on them.
1093
- watch(listLoadError, (message) => {
1094
- if (message) rowSelect.value = {};
1095
- });
1096
-
1097
- // Whatever sets the sort (a header, the sort menu, a pasted table config), the
1098
- // route only ever receives a sort it accepts, and a cleared sort goes back to
1099
- // the default one rather than being remembered empty. A new order lists from page 1:
1100
- // the page reached in the previous order shows unrelated rows in the new one.
1101
- // Synchronous, so the list is queried once, with both changes.
1102
- watch(
1103
- sorting,
1104
- (next, previous) => {
1105
- const sanitized = sortingOrDefault(
1106
- next,
1107
- sortableIds.value,
1108
- defaultSortState,
1109
- );
1110
- if (!isSameSorting(sanitized, next)) {
1111
- sorting.value = sanitized;
1112
- return;
1113
- }
1114
- const before = sortingOrDefault(
1115
- previous,
1116
- sortableIds.value,
1117
- defaultSortState,
1118
- );
1119
- if (
1120
- !isSameSorting(sanitized, before) &&
1121
- paginationState.value.pageIndex !== 0
1122
- ) {
1123
- paginationState.value = { ...paginationState.value, pageIndex: 0 };
1124
- }
1125
- },
1126
- { deep: true, flush: "sync" },
1127
- );
1128
-
1129
- const toast = useToast();
1130
-
1131
- // The route refused the sort key anyway: a column whose `@Sortable()` was
1132
- // removed since the page loaded. Stop sorting on it (the next query drops it)
1133
- // and list again, with a warning, rather than leaving the table on its error
1134
- // panel.
1135
- watch(error, (failure) => {
1136
- if (!failure || !isUnsortableFieldError(failure)) return;
1137
- const refused = effectiveSorting.value[0]?.id;
1138
- if (!refused) return;
1139
- refusedSortIds.value = [...refusedSortIds.value, refused];
1140
- sorting.value = sanitizeSorting(sorting.value, sortableIds.value);
1141
- toast.add({
1142
- title: t("dms.sort.reset_title"),
1143
- description: t("dms.sort.reset_description", {
1144
- column: columnLabel(refused),
1145
- }),
1146
- color: Color.warning,
1147
- icon: "i-ph-warning",
1148
- });
1149
- });
1150
-
1151
- // A non-self-managed display consumes the shared query, and nothing
1152
- // guarantees it knows how to render a failure. While that query is in error,
1153
- // fall back to the table body so the error panel and its retry replace the
1154
- // display instead of letting it show blank content.
1155
- const activeDisplayBlockedByError = computed(
1156
- () => !!listLoadError.value && !isActiveDisplaySelfManaged.value,
1157
- );
1158
-
1159
- watch(
1160
- [() => data.value?.total, () => paginationState.value.pageSize],
1161
- ([total, pageSize]) => {
1162
- if (total === undefined || total === null || pageSize <= 0) return;
1163
- const maxPageIndex = Math.max(0, Math.ceil(total / pageSize) - 1);
1164
- if (paginationState.value.pageIndex > maxPageIndex) {
1165
- paginationState.value = {
1166
- ...paginationState.value,
1167
- pageIndex: maxPageIndex,
1168
- };
1169
- }
1170
- },
1171
- );
1172
-
1173
- const scopeFilters = computed<TableFilter[]>(() => [
1174
- ...queryParamHiddenFilters.value,
1175
- ...routeParamHiddenFilters.value,
1176
- ]);
1177
- const countState = computed<TableCountState>(() => ({
1178
- scopeFilters: scopeFilters.value,
1179
- tabFilters: activeTabFilters.value,
1180
- columnFilters: effectiveColumnFilters.value,
1181
- search: effectiveGlobalFilter.value,
1182
- }));
1183
- const isCountStateNarrowed = computed(() => isCountNarrowed(countState.value));
1184
-
1185
- // Each counter counts what a click on it would list, so the counters follow
1186
- // the filters, the search, the view and the tab: picks made in a row (quick
1187
- // filters toggled one after the other) are counted once, when they settle.
1188
- const COUNTS_DEBOUNCE_MS = 200;
1189
- const debouncedCountsQuery = refDebounced(
1190
- computed(() =>
1191
- buildTableCountQueries({
1192
- ...countState.value,
1193
- tabs: resolvedTabs.value
1194
- .filter((tab) => !tab.to)
1195
- .map((tab) => ({
1196
- id: tab.id,
1197
- filters: tab.filters,
1198
- hasNavBadge: !!tab.navBadge,
1199
- })),
1200
- views: tableViewItems.value
1201
- .filter((view) => view.count)
1202
- .map((view) => ({
1203
- id: view.id,
1204
- filters: viewFilters(view, pinnedDefaultFilters),
1205
- search: view.search,
1206
- })),
1207
- activeViewId: activeViewId.value,
1208
- }),
1209
- ),
1210
- COUNTS_DEBOUNCE_MS,
1211
- );
1212
- const tabCountsQuery = computed(() => debouncedCountsQuery.value);
1213
-
1214
- // No default: `null` until the counts arrive, so the tabs draw placeholders
1215
- // instead of a count of nothing.
1216
- const { data: tabCountsData, refresh: refreshTabCounts } =
1217
- useTableCountsData<T>({
1218
- componentId,
1219
- pageId,
1220
- rows: tableRows,
1221
- queries: tabCountsQuery,
1222
- archiveQuery,
1223
- heldQuery: liveHold.heldQuery,
1224
- });
1225
-
1226
- const viewItems = computed<TableViewItem[]>(() =>
1227
- tableViewItems.value.map((view) => ({
1228
- id: view.id,
1229
- label: view.label,
1230
- icon: view.icon,
1231
- tone: view.tone,
1232
- dot: view.dot,
1233
- isUserView: view.isUserView,
1234
- count: view.count
1235
- ? tabCountsData.value?.[`${VIEW_COUNT_ID_PREFIX}${view.id}`]
1236
- : undefined,
1237
- countPending: !!view.count && tabCountsData.value == null,
1238
- })),
1239
- );
1240
- const viewsLayout = props.views?.layout ?? "tabs";
1241
- const hasViews =
1242
- !!props.views && (props.views.items.length > 0 || canSaveViews);
1243
-
1244
- interface ActiveDisplayExposed {
1245
- refresh?: () => Promise<void> | void;
1246
- }
1247
-
1248
- // Ref to the active display component (when one is rendered in #body); used to
1249
- // refresh self-managed displays on realtime updates and manual refresh.
1250
- const activeDisplayRef = ref<ActiveDisplayExposed | null>(null);
1251
-
1252
- // Filters/search/sort query without paging — exposed generically on the context
1253
- // (context.query) for any self-managed display to fetch its own data.
1254
- const baseQuery = computed<Record<string, unknown>>(() => {
1255
- const {
1256
- limit: _limit,
1257
- offset: _offset,
1258
- ...query
1259
- } = buildTableQuery({
1260
- pagination: { pageIndex: 0, pageSize: 0 },
1261
- sorting: effectiveSorting.value,
1262
- columnFilters: effectiveColumnFilters.value,
1263
- hiddenFilters: hiddenFilters.value,
1264
- globalFilter: effectiveGlobalFilter.value,
1265
- });
1266
- return { ...query, ...archiveQuery.value };
1267
- });
1268
-
1269
- const { footer: resolvedFooter, refreshSummaries } = useTableFooter({
1270
- footer: props.footer,
1271
- columns: props.columns,
1272
- location,
1273
- query: baseQuery,
1274
- dataKey: `table-view-${componentId}-${pageId}`,
1275
- });
1276
-
1277
- const hasMoreRows = computed(
1278
- () => (data.value?.total ?? 0) > (shownResults.value?.length ?? 0),
1279
- );
1280
- const loadMoreRows = () => {
1281
- if (hasMoreRows.value && !isListLoading.value) loadNextPage();
1282
- };
1283
- // A row's drawer or side panel steps through every row the table lists: past
1284
- // the rows loaded, it turns the table's page (or grows its feed) and steps
1285
- // onto the rows that arrive. A display reading its own rows keeps to them.
1286
- const ADJACENT_ROWS_TIMEOUT_MS = 15_000;
1287
- const listsServerPages = computed(() => !isActiveDisplaySelfManaged.value);
1288
- // What a display reading its own rows shows (`setShownRows`), in its order:
1289
- // the rows its row's container steps through. Another display, another set.
1290
- const selfManagedRows = shallowRef<Data[]>([]);
1291
- const setSelfManagedRows = (rows: T[]) => {
1292
- selfManagedRows.value = rows as Data[];
1293
- };
1294
- watch(activeDisplayId, () => {
1295
- selfManagedRows.value = [];
1296
- });
1297
- const navigableRows = (): Data[] =>
1298
- listsServerPages.value
1299
- ? ((shownResults.value ?? []) as Data[])
1300
- : selfManagedRows.value;
1301
- const loadedRowsOffset = () => {
1302
- if (isAccumulating || !listsServerPages.value) return 0;
1303
- const { pageIndex, pageSize } = paginationState.value;
1304
- return pageSize > 0 ? pageIndex * pageSize : 0;
1305
- };
1306
- const turnPage = (step: RowStep): boolean => {
1307
- if (isAccumulating) {
1308
- if (step < 0 || !hasMoreRows.value) return false;
1309
- loadNextPage();
1310
- return true;
1311
- }
1312
- const { pageIndex, pageSize } = paginationState.value;
1313
- const next = pageIndex + step;
1314
- const total = data.value?.total ?? 0;
1315
- if (pageSize <= 0 || next < 0 || next * pageSize >= total) return false;
1316
- paginationState.value = { ...paginationState.value, pageIndex: next };
1317
- return true;
1318
- };
1319
- let adjacentRowsLoad: Promise<boolean> | undefined;
1320
- const loadAdjacentRows = (step: RowStep): Promise<boolean> => {
1321
- // A second J while the page loads waits for the same page.
1322
- if (adjacentRowsLoad) return adjacentRowsLoad;
1323
- if (!listsServerPages.value || isListLoading.value || !turnPage(step)) {
1324
- return Promise.resolve(false);
1325
- }
1326
- const before = shownResults.value;
1327
- adjacentRowsLoad = until(
1328
- () => shownResults.value !== before && !isListLoading.value,
1329
- )
1330
- .toBe(true, { timeout: ADJACENT_ROWS_TIMEOUT_MS })
1331
- .then(() => !listLoadError.value && shownResults.value !== before)
1332
- .finally(() => {
1333
- adjacentRowsLoad = undefined;
1334
- });
1335
- return adjacentRowsLoad;
1336
- };
1337
- // A row past the rows loaded (a deep link, a row live rows pushed out) is
1338
- // found in the table's whole result, under the query the list reads: its
1339
- // position, and its neighbours for the steps. Its rows read in the order
1340
- // the table shows them: pinned rows lead each page it reads, not the result.
1341
- const locateRow = rowLocator({
1342
- list: async (offset, limit) => {
1343
- if (!listsServerPages.value) return null;
1344
- const page = await tableRows.listAsShown(
1345
- {
1346
- ...queryRequest.value,
1347
- ...archiveQuery.value,
1348
- ...liveHold.heldQuery(),
1349
- offset,
1350
- limit,
1351
- },
1352
- requestedPagination.value.pageSize,
1353
- );
1354
- return page && { results: page.results as Data[], total: page.total };
1355
- },
1356
- rowIdKey: props.rowIdKey ?? ROW_ID_DEFAULT_KEY,
1357
- isWholeRead: () => !!props.source && !props.source.capabilities.paginate,
1358
- });
1359
-
1360
- const accumulation = computed<TableAccumulation | undefined>(() =>
1361
- isAccumulating
1362
- ? {
1363
- mode: paginationMode as TableAccumulation["mode"],
1364
- shown: shownResults.value?.length ?? 0,
1365
- hasMore: hasMoreRows.value,
1366
- loading: isListLoading.value,
1367
- load: loadMoreRows,
1368
- }
1369
- : undefined,
1370
- );
1371
-
1372
- // Rows ordered by hand: moving is off while anything narrows the rows, and
1373
- // only the displays drawing the rows in their order move them.
1374
- const ORDERED_DISPLAY_IDS = new Set([TABLE_DISPLAY_ID, CARDS_DISPLAY_ID]);
1375
- const { reorderState } = useTableReorder<T>({
1376
- reorder: reorderConfig,
101
+ resolvedQuickFilters,
102
+ openRowId,
103
+ tableRoot,
104
+ liveHold,
1377
105
  data,
1378
- rowIdKey: props.rowIdKey ?? ROW_ID_DEFAULT_KEY,
1379
- location,
1380
- api: $authFetch,
1381
- canEdit: computed(() => isActionEnabled(tableProps.value.rowActions?.edit)),
1382
- isNarrowed: computed(
1383
- () =>
1384
- effectiveColumnFilters.value.some(isFilterEffective) ||
1385
- !!effectiveGlobalFilter.value ||
1386
- activeTabFilters.value.length > 0,
1387
- ),
1388
- isOrderedDisplay: computed(() =>
1389
- ORDERED_DISPLAY_IDS.has(activeDisplayId.value),
1390
- ),
1391
- refresh: () => refresh(),
1392
- onError: (failure) =>
1393
- toast.add({
1394
- title: t("dms.table.reorder.error"),
1395
- description: describeTableWriteError(failure, t, allColumns, processI18n),
1396
- color: Color.error,
1397
- icon: "i-ph-warning-circle",
1398
- }),
1399
- });
1400
-
1401
- const { grouping, refreshCounts: refreshGroupCounts } = useGroupedRows({
1402
- grouped: activeGroupedOptions,
1403
- isActive: isGroupedDisplay,
1404
- columns: props.columns,
1405
- rows: shownResults,
1406
- countQuery: (filter) => ({
1407
- ...buildTableQuery({
1408
- pagination: { pageIndex: 0, pageSize: 0 },
1409
- sorting: [],
1410
- columnFilters: [...effectiveColumnFilters.value, filter],
1411
- hiddenFilters: hiddenFilters.value,
1412
- globalFilter: effectiveGlobalFilter.value,
1413
- }),
1414
- ...archiveQuery.value,
1415
- }),
1416
- countBatch: tableRows.countBatch,
1417
- });
1418
-
1419
- // Only what the (unchanged) KanbanBoard needs beyond the generic context: the
1420
- // two-way group-by ref and the raw action configs for per-row rule evaluation.
1421
- provide(KANBAN_DISPLAY_BRIDGE_KEY, {
1422
- groupByField: kanbanGroupBy,
1423
- editAction: tableProps.value.rowActions?.edit,
1424
- deleteAction: tableProps.value.rowActions?.delete,
1425
- onCardMoved: () => void refreshCounts(),
1426
- });
1427
-
1428
- // A link tab counts the rows of the list it opens; a list the caller may not
1429
- // read shows no counter.
1430
- const linkTabCounts = ref<Record<string, number>>({});
1431
- // The link counters load after mount: until then their tabs hold a placeholder.
1432
- const linkTabCountsLoaded = ref(false);
1433
- const LINK_TAB_COUNT_QUERY = { limit: 1, offset: 0 };
1434
-
1435
- const refreshLinkTabCounts = async () => {
1436
- const linked = resolvedTabs.value.filter((tab) => tab.to && tab.countFrom);
1437
- if (linked.length === 0) {
1438
- linkTabCountsLoaded.value = true;
1439
- return;
1440
- }
1441
- const entries = await Promise.all(
1442
- linked.map(async (tab) => {
1443
- try {
1444
- const response = await $authFetch<TableViewListResponse<unknown>>(
1445
- `${tab.countFrom}/list`,
1446
- { query: LINK_TAB_COUNT_QUERY },
1447
- );
1448
- return [tab.id, response.total] as const;
1449
- } catch {
1450
- return undefined;
1451
- }
1452
- }),
1453
- );
1454
- linkTabCounts.value = Object.fromEntries(
1455
- entries.filter((entry) => entry !== undefined),
1456
- );
1457
- linkTabCountsLoaded.value = true;
1458
- };
1459
-
1460
- // Each re-read follows a change of the rows (a save, an action, a realtime
1461
- // event) or a refresh: what summarises them elsewhere (a navigation count)
1462
- // is told to read its figure again.
1463
- const { notifyTableDataChanged } = useTableDataChanges();
1464
- const refreshCounts = async () => {
1465
- notifyTableDataChanged(location);
1466
- await Promise.all([
1467
- refreshTabCounts(),
1468
- refreshLinkTabCounts(),
1469
- refreshGroupCounts(),
1470
- refreshSummaries(),
1471
- ]);
1472
- };
1473
- const refreshAll = async () => {
1474
- await Promise.all([
1475
- refresh(),
1476
- refreshCounts(),
1477
- activeDisplayRef.value?.refresh?.(),
1478
- ]);
1479
- };
1480
-
1481
- // The rows can move without the table seeing it (a batch, a job, another
1482
- // block's action): a topic of the backend or a page refresh reads them again,
1483
- // keeping the current rows on screen until the answer lands. On a live page
1484
- // the row events below go through the same gate.
1485
- const liveGate = useRefreshTriggers(props.realtimeTopic, () => refreshAll());
1486
- // What the user asks for (a row action, the refresh button, ⌘R, a display's
1487
- // own action) reads at once, even while the live page is paused, and brings
1488
- // a held table up to date.
1489
- const refreshByUser = () => {
1490
- liveGate.acknowledge();
1491
- return refreshAll();
1492
- };
1493
- // A write of the user's (a row or bulk action, a form saved) can move what
1494
- // the rest of the page shows of the same records — a KPI, a tab's badge,
1495
- // another list: every block of the page reads its data again, this table
1496
- // among them, at once even on a paused live page.
1497
- const refreshAfterWrite = () => refreshPageBlocks();
1498
-
1499
- // "Preview as role": a link tab to a page the previewed role could not open
1500
- // is drawn locked, one to a page it opens partially is drawn partially
1501
- // locked. Never outside a preview (`entryState` is null then).
1502
- const permissionPreview = usePermissionPreview();
1503
- const previewSiteLayout = useSiteLayout();
1504
- const linkTabPreviewState = (tab: ResolvedTab) => {
1505
- if (!tab.to || !permissionPreview.isActive.value) return null;
1506
- const fullId =
1507
- tab.toPage ??
1508
- previewSiteLayout.findMatchingRoute(stripQueryAndHash(tab.to))?.metadata
1509
- .fullId;
1510
- return permissionPreview.entryState(fullId);
1511
- };
1512
-
1513
- const isTabCountPending = (tab: ResolvedTab): boolean => {
1514
- if (!tab.to) return tabCountsData.value == null;
1515
- return !!tab.countFrom && !linkTabCountsLoaded.value;
1516
- };
1517
-
1518
- const tabsWithCount = computed(() =>
1519
- resolvedTabs.value.map((tab) => ({
1520
- id: tab.id,
1521
- label: tab.label,
1522
- count: tab.to ? linkTabCounts.value[tab.id] : tabCountsData.value?.[tab.id],
1523
- countPending: isTabCountPending(tab),
1524
- icon: tab.icon,
1525
- textColor: tab.textColor,
1526
- iconColor: tab.iconColor,
1527
- to: tab.to,
1528
- previewLocked: linkTabPreviewState(tab) === "hidden",
1529
- previewPartial: linkTabPreviewState(tab) === "partial",
1530
- })),
1531
- );
1532
-
1533
- // A tab declared with `navBadge` keeps the navigation badge the server
1534
- // counted for the page it stands for (the linked page, or this one) up to
1535
- // date: with the tab's own counter while nothing narrows it, else with a
1536
- // count of the tab alone, since the badge stands for the whole page. An
1537
- // empty badge stands for zero.
1538
- const { setNavBadge } = useNavBadges();
1539
- const tabNavBadgeCount = (tab: ResolvedTab, count: number | undefined) =>
1540
- tab.to
1541
- ? count
1542
- : navBadgeCount(tabCountsData.value, tab.id, isCountStateNarrowed.value);
1543
- watch(
106
+ isFirstPageLoading,
107
+ isListLoading,
108
+ listLoadError,
109
+ listNotFound,
110
+ shownResults,
111
+ activeDisplayBlockedByError,
112
+ viewItems,
113
+ viewsLayout,
114
+ hasViews,
115
+ activeDisplayRef,
116
+ resolvedFooter,
117
+ accumulation,
118
+ reorderState,
119
+ grouping,
120
+ refreshByUser,
1544
121
  tabsWithCount,
1545
- (next) => {
1546
- for (const tab of next) {
1547
- const source = resolvedTabs.value.find((entry) => entry.id === tab.id);
1548
- if (!source?.navBadge) continue;
1549
- const count = tabNavBadgeCount(source, tab.count);
1550
- if (count === undefined) continue;
1551
- const fullId = source.to ? source.toPage : pageId;
1552
- const tone =
1553
- typeof source.navBadge === "object" ? source.navBadge.tone : undefined;
1554
- if (fullId) {
1555
- setNavBadge(fullId, count > 0 ? String(count) : "", tone);
1556
- }
1557
- }
1558
- },
1559
- { immediate: true },
1560
- );
1561
-
1562
- const { exportTable } = useTableViewExport({ componentId });
1563
- const {
1564
- openRow,
1565
- openRowById,
1566
- editRow,
1567
- newRow,
1568
- duplicateRow,
1569
- deleteRows: deleteRowsAction,
1570
- archiveRows: archiveRowsAction,
1571
- restoreRows: restoreRowsAction,
1572
122
  handleCustomButton,
1573
123
  handleCustomRowAction,
1574
- handleBulkCustomAction,
1575
- handleMissingRow,
1576
- runConfirmedBuiltIn,
1577
- } = useTableRowActions<T>({
1578
- api: $authFetch,
1579
- location,
1580
- columns: allColumns,
1581
- caption,
1582
- labelKey,
1583
- rowIdKey: props.rowIdKey,
1584
- refreshCallback: refreshAfterWrite,
1585
- formComponents,
1586
- formContainer,
1587
- formPages,
1588
- routeParams,
1589
- componentId: componentId!,
1590
- pageId: pageId!,
1591
- queryParamFilters,
1592
- rowNavigation: {
1593
- rows: navigableRows,
1594
- rowIdKey: props.rowIdKey ?? ROW_ID_DEFAULT_KEY,
1595
- getRow: (id) => tableRows.getRow(id) as Promise<Data | undefined>,
1596
- total: () =>
1597
- listsServerPages.value
1598
- ? (shownData.value?.total ?? undefined)
1599
- : undefined,
1600
- offset: loadedRowsOffset,
1601
- loadAdjacent: loadAdjacentRows,
1602
- locate: locateRow,
1603
- },
1604
- recordScope: urlScope,
1605
- onRecordShown: (id) => recordLink?.shown(id),
1606
- });
1607
-
1608
- // Custom actions offered on the selection bar. "Select all N matching"
1609
- // hands them the table's filters instead of ids; a new query lists other
1610
- // rows, so it ends with it.
1611
- const bulkCustomActions = computed(() =>
1612
- (tableProps.value.rowActions?.custom ?? []).filter(isBulkAction),
1613
- );
1614
- const allMatching = ref(false);
1615
- const runBulkAction = (action: CustomRowAction) =>
1616
- handleBulkCustomAction(
1617
- action,
1618
- allMatching.value
1619
- ? { matching: baseQuery.value, count: data.value?.total ?? 0 }
1620
- : { ids: selectedIds.value, count: selectedIds.value.length },
1621
- );
1622
-
1623
- // Archive mode: the toolbar carries an "Archived" toggle for callers allowed
1624
- // to see archived rows.
1625
- const canToggleArchived = computed(
1626
- () => !!archiveMode && tableProps.value.rowActions?.showArchived === true,
1627
- );
1628
-
1629
- // A selection made among the rows a filter, a search or a tab listed would
1630
- // let a bulk action reach rows no longer shown: it goes with them.
1631
- const selectionScope = computed(() =>
1632
- selectionScopeKey({
1633
- columnFilters: effectiveColumnFilters.value,
1634
- hiddenFilters: hiddenFilters.value,
1635
- globalFilter: effectiveGlobalFilter.value,
1636
- }),
1637
- );
1638
- watch(selectionScope, () => {
1639
- rowSelect.value = {};
1640
- });
1641
-
1642
- // A selection made among active rows means nothing among archived ones, and
1643
- // the page reached in one list rarely exists in the other: start over.
1644
- watch(showArchived, () => {
1645
- rowSelect.value = {};
1646
- paginationState.value = { ...paginationState.value, pageIndex: 0 };
1647
- });
1648
-
1649
- const customNavItems = computed(() => {
1650
- const items = [];
1651
-
1652
- if (enableTableExport) {
1653
- items.push({
1654
- label: t("dms.button.export_data"),
1655
- icon: "i-ph-export",
1656
- onSelect: () => handleExportTable(),
1657
- });
1658
- }
1659
-
1660
- return items;
1661
- });
1662
-
1663
- // Deleted, archived and restored rows leave the listed set: a selection kept
1664
- // on them would offer bulk actions on rows no longer shown. A cancelled
1665
- // confirmation (or a failed request) keeps the selection as it was.
1666
- const deselectRows = (ids: string[]) => {
1667
- const removed = new Set(ids);
1668
- rowSelect.value = Object.fromEntries(
1669
- Object.entries(rowSelect.value).filter(([id]) => !removed.has(id)),
1670
- );
1671
- };
1672
-
1673
- // From the archive, a delete is a permanent one: its confirmation says so.
1674
- // A display holding the rows (a kanban card) hands them for its wording.
1675
- const deleteRows = async (ids: string[], rows?: T[]) => {
1676
- const done = await deleteRowsAction(
1677
- ids,
1678
- tableProps.value.rowActions?.delete,
1679
- {
1680
- permanently: !!archiveMode && showArchived.value,
1681
- rows,
1682
- },
1683
- );
1684
- if (done) deselectRows(ids);
1685
- };
1686
-
1687
- const archiveRows = async (ids: string[]) => {
1688
- if (await archiveRowsAction(ids, tableProps.value.rowActions?.archive)) {
1689
- deselectRows(ids);
1690
- }
1691
- };
1692
-
1693
- const restoreRows = async (ids: string[]) => {
1694
- if (await restoreRowsAction(ids, tableProps.value.rowActions?.restore)) {
1695
- deselectRows(ids);
1696
- }
1697
- };
1698
-
1699
- const handleExportTable = () =>
1700
- exportTable(location, { ...queryRequest.value, ...archiveQuery.value });
1701
- const handleExportSelection = (ids: string[]) =>
1702
- exportTable(location, queryRequest.value, ids);
1703
- // A built-in action declaring a `confirm` asks it first.
1704
- const rowActionConfig = (key: "details" | "duplicate" | "add" | "edit") =>
1705
- tableProps.value.rowActions?.[key];
1706
- const handleRowClick = (item: T) =>
1707
- runConfirmedBuiltIn(rowActionConfig("details"), item, () => openRow(item));
1708
- // Its dialog words the row shown (`{name}`), else only its id.
1709
- const handleRowDuplicate = (itemId: string) => {
1710
- const idKey = props.rowIdKey ?? ROW_ID_DEFAULT_KEY;
1711
- const shown = shownResults.value?.find(
1712
- (row) => String(get(row, idKey)) === itemId,
1713
- );
1714
- return runConfirmedBuiltIn(
1715
- rowActionConfig("duplicate"),
1716
- shown ?? { [idKey]: itemId },
1717
- () => duplicateRow(itemId),
1718
- );
1719
- };
1720
- const handleRowAdd = () =>
1721
- runConfirmedBuiltIn(rowActionConfig("add"), undefined, () =>
1722
- newRow(queryParamDefaults.value),
1723
- );
1724
-
1725
- const rowIdKey = props.rowIdKey ?? ROW_ID_DEFAULT_KEY;
1726
- // A source table has no realtime: its route is no data controller's.
1727
- const realtimeLocation = tableRows.isSource ? undefined : location;
1728
- const realtimeRowTopic = computed(() =>
1729
- realtimeLocation
1730
- ? `${REALTIME_ROW_TOPIC_PREFIX}${realtimeLocation}`
1731
- : undefined,
1732
- );
1733
- const realtimePresenceTopic = computed(() =>
1734
- realtimeLocation
1735
- ? `${REALTIME_PRESENCE_TOPIC_PREFIX}${realtimeLocation}`
1736
- : undefined,
1737
- );
1738
-
1739
- const presenceByRow = ref<RealtimePresenceMap>({});
1740
- const { user: realtimeUser } = useDmsUserSession();
1741
-
1742
- const getRowId = (row: T): string | undefined => {
1743
- const value = (row as Record<string, unknown>)[rowIdKey];
1744
- if (value === undefined || value === null) return undefined;
1745
- return String(value);
1746
- };
1747
-
1748
- const removeRowsLocal = (ids: string[]) => {
1749
- if (!data.value?.results) return;
1750
- const idSet = new Set(ids);
1751
- const next = data.value.results.filter((row) => {
1752
- const id = getRowId(row);
1753
- return !id || !idSet.has(id);
1754
- });
1755
- data.value = { ...data.value, results: next };
1756
- };
1757
-
1758
- const patchRowLocal = async (id: string) => {
1759
- if (!data.value?.results) return;
1760
- const idx = data.value.results.findIndex((row) => getRowId(row) === id);
1761
- if (idx === -1) return;
1762
- try {
1763
- const fresh = await tableRows.getRow(id);
1764
- if (!fresh) return;
1765
- const next = [...data.value.results];
1766
- next[idx] = fresh as unknown as T;
1767
- data.value = { ...data.value, results: next };
1768
- } catch (error) {
1769
- console.warn("[realtime] failed to refetch updated row", id, error);
1770
- }
1771
- };
1772
-
1773
- const realtimeEventHandlers: Record<
1774
- string,
1775
- (ids: string[]) => void | Promise<void>
1776
- > = {
1777
- [REALTIME_EVENT_TYPE.DELETED]: (ids) => {
1778
- removeRowsLocal(ids);
1779
- // Rows gone elsewhere leave the selection too, or it would count them.
1780
- deselectRows(ids);
1781
- return refreshAll();
1782
- },
1783
- [REALTIME_EVENT_TYPE.CREATED]: () => refreshAll(),
1784
- // An edited row can change tab, group or column: the counts are read again
1785
- // with it.
1786
- [REALTIME_EVENT_TYPE.UPDATED]: async (ids) => {
1787
- if (isActiveDisplaySelfManaged.value) {
1788
- await Promise.all([activeDisplayRef.value?.refresh?.(), refreshCounts()]);
1789
- return;
1790
- }
1791
- await Promise.all([...ids.map((id) => patchRowLocal(id)), refreshCounts()]);
1792
- },
1793
- };
1794
-
1795
- // On a live page a row event is one more event behind the table: in Direct
1796
- // it reads the rows again (at most once per `maxRate`), paused it is counted
1797
- // and the rows stay as they are. Rows gone elsewhere still leave a selection
1798
- // the page shows moving.
1799
- const { isEnabled: isPageLive, isPaused: isPagePaused } = usePageLive();
1800
- const gateRowEvent = (type: string, ids: string[], event: object) => {
1801
- if (type === REALTIME_EVENT_TYPE.DELETED && !isPagePaused.value) {
1802
- deselectRows(ids);
1803
- }
1804
- liveGate.trigger(event);
1805
- };
1806
-
1807
- useRealtimeTopic(realtimeRowTopic, (event) => {
1808
- const payload = event as { type: string; payload?: { ids?: string[] } };
1809
- const handler = realtimeEventHandlers[payload.type];
1810
- if (!handler) return;
1811
- const ids = payload.payload?.ids ?? [];
1812
- if (ids.length === 0 && payload.type !== REALTIME_EVENT_TYPE.CREATED) return;
1813
- if (isPageLive.value) {
1814
- gateRowEvent(payload.type, ids, event);
1815
- return;
1816
- }
1817
- void handler(ids);
1818
- });
1819
-
1820
- const replacePresenceMap = (next: RealtimePresenceMap) => {
1821
- presenceByRow.value = next;
1822
- };
1823
-
1824
- const upsertPresence = (rowId: string, actor: RealtimePresenceActor) => {
1825
- const current = presenceByRow.value[rowId] ?? [];
1826
- if (current.some((entry) => entry.sessionId === actor.sessionId)) return;
1827
- replacePresenceMap({
1828
- ...presenceByRow.value,
1829
- [rowId]: [...current, actor],
1830
- });
1831
- };
1832
-
1833
- const removePresence = (rowId: string, sessionId: string) => {
1834
- const current = presenceByRow.value[rowId];
1835
- if (!current) return;
1836
- const next = current.filter((entry) => entry.sessionId !== sessionId);
1837
- if (next.length === 0) {
1838
- const { [rowId]: _removed, ...rest } = presenceByRow.value;
1839
- replacePresenceMap(rest);
1840
- return;
1841
- }
1842
- replacePresenceMap({ ...presenceByRow.value, [rowId]: next });
1843
- };
1844
-
1845
- const applySnapshot = (
1846
- entries: Array<{
1847
- rowId: string;
1848
- actor: { id: string; displayName?: string; avatarUrl?: string };
1849
- sessionId: string;
1850
- since?: number;
1851
- }>,
1852
- ) => {
1853
- const next: RealtimePresenceMap = {};
1854
- for (const entry of entries) {
1855
- const list = next[entry.rowId] ?? [];
1856
- list.push({
1857
- ...entry.actor,
1858
- sessionId: entry.sessionId,
1859
- since: entry.since,
1860
- });
1861
- next[entry.rowId] = list;
1862
- }
1863
- replacePresenceMap(next);
1864
- };
1865
-
1866
- useRealtimeTopic(realtimePresenceTopic, (event) => {
1867
- const eventTyped = event as {
1868
- type?: string;
1869
- payload?: {
1870
- rowId?: string;
1871
- actor?: { id: string; displayName?: string; avatarUrl?: string };
1872
- sessionId?: string;
1873
- since?: number;
1874
- };
1875
- entries?: Array<{
1876
- rowId: string;
1877
- actor: { id: string; displayName?: string; avatarUrl?: string };
1878
- sessionId: string;
1879
- since?: number;
1880
- }>;
1881
- };
1882
- if (Array.isArray(eventTyped.entries)) {
1883
- applySnapshot(eventTyped.entries);
1884
- return;
1885
- }
1886
- const { rowId, actor, sessionId, since } = eventTyped.payload ?? {};
1887
- if (!rowId || !sessionId) return;
1888
- if (eventTyped.type === REALTIME_EVENT_TYPE.ACQUIRED && actor) {
1889
- upsertPresence(rowId, { ...actor, sessionId, since });
1890
- return;
1891
- }
1892
- if (eventTyped.type === REALTIME_EVENT_TYPE.RELEASED) {
1893
- removePresence(rowId, sessionId);
1894
- }
1895
- });
1896
-
1897
- const filterSelf = (
1898
- entries: RealtimePresenceActor[],
1899
- ): RealtimePresenceActor[] => {
1900
- const myId = realtimeUser.value?._id;
1901
- return myId ? entries.filter((entry) => entry.id !== myId) : entries;
1902
- };
1903
-
1904
- const otherEditorsForRow = (rowId: string): RealtimePresenceActor[] => {
1905
- return filterSelf(presenceByRow.value[rowId] ?? []);
1906
- };
1907
-
1908
- const presenceByRowFiltered = computed<RealtimePresenceMap>(() => {
1909
- const result: RealtimePresenceMap = {};
1910
- for (const [rowId, entries] of Object.entries(presenceByRow.value)) {
1911
- const others = filterSelf(entries);
1912
- if (others.length > 0) result[rowId] = others;
1913
- }
1914
- return result;
1915
- });
1916
-
1917
- // Expandable rows: which rows are open. A newly listed set (page, filter,
1918
- // search, sort, tab, archive view) starts from `defaultExpanded`; a refresh of
1919
- // the same set keeps what the user opened, minus rows no longer listed.
1920
- const expandableConfig = props.expandable;
1921
- const expanded = ref<ExpandedRowMap>({});
1922
-
1923
- const rowIdsOf = (rows: T[] | undefined): string[] =>
1924
- (rows ?? []).map((row) => getRowId(row)).filter((id): id is string => !!id);
1925
-
1926
- const expandedModel = computed<ExpandedState>({
1927
- get: () => expanded.value,
1928
- set: (next) => {
1929
- expanded.value = nextExpandedRows(
1930
- expanded.value,
1931
- next,
1932
- rowIdsOf(shownResults.value),
1933
- expandableConfig?.single,
1934
- );
1935
- },
1936
- });
1937
-
1938
- let expandedListedKey: string | undefined;
1939
- if (expandableConfig) {
1940
- watch(
1941
- shownResults,
1942
- (rows) => {
1943
- const next = expandedRowsOnListing(
1944
- { expanded: expanded.value, listedKey: expandedListedKey },
1945
- rows ? rowIdsOf(rows) : undefined,
1946
- JSON.stringify([queryRequest.value, archiveQuery.value]),
1947
- expandableConfig.defaultExpanded,
1948
- expandableConfig.single,
1949
- );
1950
- expandedListedKey = next.listedKey;
1951
- expanded.value = next.expanded;
1952
- },
1953
- { immediate: true },
1954
- );
1955
- }
1956
-
1957
- // `lazyLoad` bands read their row when it opens; any reload of the listed
1958
- // rows drops what they read, and the open ones read it again.
1959
- const expandedDetails = useExpandedRowDetails<T>((id) => tableRows.getRow(id));
1960
- if (expandableConfig?.lazyLoad) {
1961
- watch(shownResults, () => expandedDetails.reset());
1962
- watch(
1963
- [expanded, shownResults],
1964
- () =>
1965
- expandedDetails.ensure(
1966
- Object.keys(expanded.value).filter((id) => expanded.value[id]),
1967
- ),
1968
- { immediate: true },
1969
- );
1970
- }
1971
-
1972
- const expandedRowLoadState = (id: string): ExpandedRowLoadState =>
1973
- expandableConfig?.lazyLoad
1974
- ? (expandedDetails.entryOf(id)?.state ?? "loading")
1975
- : "ready";
1976
-
1977
- // The band takes any row: its props are the table's, for the row type it lists.
1978
- const expandedRowProps = (listed: T): TableViewExpandedRowProps => {
1979
- const id = getRowId(listed);
1980
- const read = id ? expandedDetails.entryOf(id)?.row : undefined;
1981
- return buildExpandedRowProps<T>(
1982
- read ? { ...listed, ...read } : listed,
1983
- displayContext.value,
1984
- ) as unknown as TableViewExpandedRowProps;
1985
- };
1986
-
1987
- const { warnBeforeEdit } = usePresenceEditWarning();
1988
-
1989
- const handleRowEdit = async (item: T) => {
1990
- const itemId = getRowId(item);
1991
- if (itemId) {
1992
- const others = otherEditorsForRow(itemId);
1993
- if (others.length > 0 && !(await warnBeforeEdit(others))) return;
1994
- }
1995
- return runConfirmedBuiltIn(rowActionConfig("edit"), item, () =>
1996
- editRow(item, queryParamDefaults.value),
1997
- );
1998
- };
1999
-
2000
- const EMPTY_ITEMS: T[] = [];
2001
-
2002
- watch(
2003
- baseQuery,
2004
- () => {
2005
- allMatching.value = false;
2006
- },
2007
- { deep: true },
2008
- );
2009
- watch(rowSelect, (selection) => {
2010
- if (Object.keys(selection).length === 0) allMatching.value = false;
2011
- });
2012
-
2013
- // A deep-linked action reopens on the row the URL names, listed or not. A
2014
- // list still loading is waited for first: a row it lists keeps its position
2015
- // among the rows shown, and a source table without `fetchRowUrl` has no
2016
- // route to read one row from.
2017
- const deepLinkAction = (tableProps.value.rowActions?.custom ?? []).find(
2018
- isDeepLinkAction,
2019
- );
2020
- const recordLink = deepLinkAction
2021
- ? useTableRecordLink<T>({
2022
- route,
2023
- urlScope,
2024
- action: deepLinkAction,
2025
- resolve: async (id) => {
2026
- await until(isListLoading).toBe(false);
2027
- return resolveDeepLinkedRow(id, {
2028
- listed: shownResults.value ?? undefined,
2029
- idOf: getRowId,
2030
- getRow: tableRows.getRow,
2031
- });
2032
- },
2033
- open: (row) => handleCustomRowAction(deepLinkAction, row as Data),
2034
- showMissing: (id) => handleMissingRow(deepLinkAction, id),
2035
- notify: (outcome) => toast.add(recordLinkToasts[outcome]()),
2036
- })
2037
- : undefined;
2038
-
2039
- const recordLinkToasts = {
2040
- notify: () => ({
2041
- title: t("dms.record_link.not_found_title"),
2042
- description: t("dms.record_link.not_found_description"),
2043
- color: Color.warning,
2044
- icon: "i-ph-link-break",
2045
- }),
2046
- notifyFailed: () => ({
2047
- title: t("dms.record_link.failed_title"),
2048
- description: t("dms.record_link.failed_description"),
2049
- color: Color.error,
2050
- icon: "i-ph-warning-circle",
2051
- }),
2052
- };
2053
-
2054
- const selectedIds = computed(() => selectedRowIds(rowSelect.value));
2055
-
2056
- const isRowActionEnabled = (
2057
- config: boolean | RowActionConfig | undefined,
2058
- item: T,
2059
- ): boolean => {
2060
- const normalized = normalizeActionConfig(config);
2061
- if (!normalized.isEnabled) return false;
2062
- if (!normalized.rule) return true;
2063
- return evaluateRowActionRule(
2064
- normalized.rule,
2065
- item as Record<string, unknown>,
2066
- );
2067
- };
2068
-
2069
- // Stable API objects (defined once): they only capture stable refs, so the
2070
- // display context keeps a stable identity across renders.
2071
- const displaySelection = {
2072
- isSelected: (id: string) => !!rowSelect.value[id],
2073
- toggle: (id: string, value?: boolean) => {
2074
- if (value ?? !rowSelect.value[id]) {
2075
- rowSelect.value = { ...rowSelect.value, [id]: true };
2076
- return;
2077
- }
2078
- const { [id]: _removed, ...rest } = rowSelect.value;
2079
- rowSelect.value = rest;
2080
- },
2081
- // Decide from the visible page and merge, so selections on other server-paged
2082
- // pages are preserved rather than cleared.
2083
- toggleAll: (value?: boolean) => {
2084
- const ids = (shownResults.value ?? [])
2085
- .map((row) => getRowId(row))
2086
- .filter((id): id is string => !!id);
2087
- const allVisibleSelected =
2088
- ids.length > 0 && ids.every((id) => rowSelect.value[id]);
2089
- if (value ?? !allVisibleSelected) {
2090
- rowSelect.value = {
2091
- ...rowSelect.value,
2092
- ...Object.fromEntries(ids.map((id) => [id, true])),
2093
- };
2094
- return;
2095
- }
2096
- const removed = new Set(ids);
2097
- rowSelect.value = Object.fromEntries(
2098
- Object.entries(rowSelect.value).filter(([id]) => !removed.has(id)),
2099
- );
2100
- },
2101
- clear: () => {
2102
- rowSelect.value = {};
2103
- },
2104
- };
2105
-
2106
- const displayPagination = {
2107
- setPage: (index: number) => {
2108
- paginationState.value = { ...paginationState.value, pageIndex: index };
2109
- },
2110
- setPageSize: (size: number) => {
2111
- paginationState.value = {
2112
- ...paginationState.value,
2113
- pageSize: size,
2114
- pageIndex: 0,
2115
- };
2116
- },
2117
- };
2118
-
2119
- // A display opens an item the way a click opens a row of the grid: its
2120
- // default custom action, else edit, else details.
2121
- const builtInRowClicks: Record<"edit" | "details", (item: T) => unknown> = {
2122
- edit: handleRowEdit,
2123
- details: handleRowClick,
2124
- };
2125
- const openDisplayItem = (item: T) => {
2126
- const action = resolveRowClickAction(
2127
- tableProps.value.rowActions,
2128
- item as Record<string, unknown>,
2129
- );
2130
- if (!action) return;
2131
- if (typeof action === "string") {
2132
- void builtInRowClicks[action](item);
2133
- return;
2134
- }
2135
- handleCustomRowAction(action, item);
2136
- };
2137
-
2138
- const displayRowActions = {
2139
- add: handleRowAdd,
2140
- edit: handleRowEdit,
2141
- delete: deleteRows,
2142
- duplicate: handleRowDuplicate,
2143
- details: handleRowClick,
2144
- open: openDisplayItem,
2145
- custom: handleCustomRowAction,
2146
- canEditRow: (item: T) =>
2147
- isRowActionEnabled(tableProps.value.rowActions?.edit, item),
2148
- canDeleteRow: (item: T) =>
2149
- isRowActionEnabled(tableProps.value.rowActions?.delete, item),
2150
- customFor: (item: T) =>
2151
- rowCustomActions(
2152
- tableProps.value.rowActions?.custom,
2153
- item as Record<string, unknown>,
2154
- ),
2155
- };
2156
-
2157
- // The TanStack instance is only available as a #body slot prop; captured here so
2158
- // the context can stay a memoized computed (stable identity unless its deps change).
2159
- const displayTable = shallowRef<Table<T>>();
2160
- const captureDisplayTable = (table: Table<T>) => {
2161
- if (displayTable.value !== table) displayTable.value = table;
2162
- };
2163
-
2164
- const displayContext = computed(
2165
- (): TableViewDisplayContext<T> => ({
2166
- items: shownResults.value ?? EMPTY_ITEMS,
2167
- columns: props.columns,
2168
- loading: isListLoading.value,
2169
- firstPageLoading: isFirstPageLoading.value,
2170
- selection: { ids: selectedIds.value, ...displaySelection },
2171
- pagination: {
2172
- pageIndex: paginationState.value.pageIndex,
2173
- pageSize: paginationState.value.pageSize,
2174
- total: data.value?.total ?? 0,
2175
- ...displayPagination,
2176
- mode: paginationMode,
2177
- hasMore: hasMoreRows.value,
2178
- loadMore: loadMoreRows,
2179
- },
2180
- actions: {
2181
- canAdd: isActionEnabled(tableProps.value.rowActions?.add),
2182
- canEdit: isActionEnabled(tableProps.value.rowActions?.edit),
2183
- canDelete: isActionEnabled(tableProps.value.rowActions?.delete),
2184
- canDetails: isActionEnabled(tableProps.value.rowActions?.details),
2185
- ...displayRowActions,
2186
- },
2187
- presenceByRow: presenceByRowFiltered.value,
2188
- rowIdKey,
2189
- labelKey,
2190
- location,
2191
- query: baseQuery.value,
2192
- componentId,
2193
- pageId,
2194
- options: optionsForDisplay(activeDisplayId.value),
2195
- refresh: refreshByUser,
2196
- setShownRows: setSelfManagedRows,
2197
- reorder: reorderState.value,
2198
- table: displayTable.value,
2199
- }),
2200
- );
2201
-
2202
- const contextForSlot = (table: Table<T>): TableViewDisplayContext<T> => {
2203
- captureDisplayTable(table);
2204
- return displayContext.value;
2205
- };
2206
-
2207
- const router = useDmsRouter();
2208
-
2209
- async function clearQuickActionQuery() {
2210
- const {
2211
- [QUICK_ACTION_QUERY_KEY]: _discarded,
2212
- [QUICK_ACTION_COMPONENT_KEY]: _discardedComponent,
2213
- [QUICK_ACTION_BUTTON_KEY]: _discardedButton,
2214
- ...rest
2215
- } = route.query;
2216
- await router.replace({ query: rest });
2217
- }
2218
-
2219
- // The button is looked up among the ones the server kept for this caller: a
2220
- // button it stripped cannot be pressed through the URL either.
2221
- function pressCustomButton(id: string) {
2222
- const button = customButtons?.find((candidate) => candidate.id === id);
2223
- if (button) handleCustomButton(button);
2224
- }
2225
-
2226
- const quickActionHandlers: {
2227
- [K in QuickActionIntent["kind"]]: (
2228
- intent: Extract<QuickActionIntent, { kind: K }>,
2229
- ) => void;
2230
- } = {
2231
- add: () => handleRowAdd(),
2232
- button: (intent) => pressCustomButton(intent.button),
2233
- };
2234
-
2235
- function runQuickActionIntent(intent: QuickActionIntent) {
2236
- // Keyed by the intent's own discriminant, so the handler always matches.
2237
- const handler = quickActionHandlers[intent.kind] as (
2238
- value: QuickActionIntent,
2239
- ) => void;
2240
- handler(intent);
2241
- }
2242
-
2243
- // Watched key by key rather than through the parsed intent: a fresh intent
2244
- // object on every unrelated query change would press the button twice.
2245
- watch(
2246
- [
2247
- QUICK_ACTION_QUERY_KEY,
2248
- QUICK_ACTION_COMPONENT_KEY,
2249
- QUICK_ACTION_BUTTON_KEY,
2250
- ].map((key) => () => route.query[key]),
2251
- () => {
2252
- const intent = readQuickActionIntent(route.query, componentId);
2253
- if (!intent) return;
2254
- // A server render only drops the query (a redirect): it opens nothing.
2255
- if (import.meta.env.SSR) {
2256
- void clearQuickActionQuery();
2257
- return;
2258
- }
2259
- // Run first, then drop the query: dropping it is a server visit, and a
2260
- // visit cut short by a navigation still settles, so awaiting it first
2261
- // opened the form over the page navigated to.
2262
- runQuickActionIntent(intent);
2263
- void clearQuickActionQuery();
2264
- },
2265
- { immediate: true },
2266
- );
2267
-
2268
- // A header button of this page presses this table view's buttons in place
2269
- // (see `runMountedQuickAction`): the modal opens on the click.
2270
- let unregisterQuickActionTarget: (() => void) | undefined;
2271
- onMounted(() => {
2272
- if (!componentId) return;
2273
- unregisterQuickActionTarget = registerQuickActionTarget({
2274
- path: route.path,
2275
- componentId,
2276
- run: runQuickActionIntent,
2277
- });
2278
- });
2279
- onBeforeUnmount(() => unregisterQuickActionTarget?.());
2280
-
2281
- defineShortcuts(
2282
- buildTableViewShortcuts({
2283
- refresh: refreshByUser,
2284
- tableProps,
2285
- newRow: () => newRow(queryParamDefaults.value),
2286
- globalFilter,
2287
- rowSelect,
2288
- data: shownData,
2289
- activeElement: useActiveElement(),
2290
- }),
2291
- );
2292
-
2293
- // Each kept field with its default: a value back to it is forgotten.
2294
- // A hand-ordered table keeps no sort.
2295
- const tableStatePreferences: TableStatePreference[] = [
2296
- ...(reorderConfig
2297
- ? []
2298
- : [["sorting", sorting, defaultSortState] as TableStatePreference]),
2299
- ["columnFilters", columnFilters, []],
2300
- ["columnVisibility", columnVisibility, initialVisibility],
2301
- ["filtersOpen", filtersRowOpen, hasEmptyDefaultFilter],
2302
- ["activeTab", activeTabId, ALL_TAB_ID],
2303
- ["viewMode", activeDisplayId, displayDefault],
2304
- ["columnOrder", columnOrder, []],
2305
- ["kanbanGroupBy", kanbanGroupBy, defaultKanbanGroupBy],
2306
- ["groupedGroupBy", groupedGroupBy, defaultGroupedGroupBy],
2307
- ["density", density, defaultDensity],
2308
- ];
2309
-
2310
- tableStatePreferences.forEach(([field, state, defaultValue]) => {
2311
- watch(
2312
- state,
2313
- (newValue) => {
2314
- tablePreferences.set(field, newValue, unref(defaultValue));
2315
- },
2316
- { deep: true },
2317
- );
2318
- });
2319
-
2320
- // Resizing fires on every mousemove (columnResizeMode "onChange"); debounce so
2321
- // the preference cookie is only written once the drag settles.
2322
- const COLUMN_SIZING_PERSIST_DEBOUNCE_MS = 500;
2323
- let pendingColumnSizingWrite = false;
2324
-
2325
- const persistColumnSizing = () => {
2326
- tablePreferences.set("columnSizing", columnSizing.value, {});
2327
- pendingColumnSizingWrite = false;
2328
- };
2329
-
2330
- watch(
2331
- columnSizing,
2332
- () => {
2333
- pendingColumnSizingWrite = true;
2334
- },
2335
- { deep: true },
2336
- );
2337
- watchDebounced(columnSizing, persistColumnSizing, {
2338
- deep: true,
2339
- debounce: COLUMN_SIZING_PERSIST_DEBOUNCE_MS,
2340
- });
2341
-
2342
- // Flush a pending resize if the user navigates away (SPA route change, unmount)
2343
- // within the debounce window — otherwise the debounced write is cancelled on
2344
- // teardown and the last width is silently dropped.
2345
- onBeforeUnmount(() => {
2346
- if (pendingColumnSizingWrite) persistColumnSizing();
2347
- });
2348
-
2349
- function watchAndEmit<T>(
2350
- source: WatchSource<T>,
2351
- event: string,
2352
- componentId: string,
2353
- mapper: (val: T) => Record<string, unknown> = (v) =>
2354
- v as Record<string, unknown>,
2355
- opts: WatchOptions = {},
2356
- ): void {
2357
- watch(
2358
- source,
2359
- (newVal) => sendComponentEvent(event, componentId, mapper(newVal)),
2360
- { deep: true, ...opts },
2361
- );
2362
- }
2363
-
2364
- if (componentId) {
2365
- watchAndEmit(columnFilters, TableViewEvents.FILTER_CHANGE, componentId);
2366
- watchAndEmit(sorting, TableViewEvents.SORT_CHANGE, componentId);
2367
- watchAndEmit(
2368
- rowSelect,
2369
- TableViewEvents.ROW_SELECT,
2370
- componentId,
2371
- (selection) => ({
2372
- selectedIds: selectedRowIds(selection),
2373
- }),
2374
- );
2375
- }
2376
-
2377
- const checkUrlParameter = () => {
2378
- const urlParamKey = `${componentId}:id`;
2379
- const itemId = route.query[urlParamKey];
2380
-
2381
- if (itemId && isString(itemId)) {
2382
- openRowById(itemId);
2383
- }
2384
- };
2385
-
2386
- onMounted(() => {
2387
- checkUrlParameter();
2388
- void loadRelationQuickFilters();
2389
- void refreshLinkTabCounts();
2390
- // The registry is client-only; once hydrated, degrade to the fallback display
2391
- // if the active id is no longer available (e.g. kanban with no eligible column).
2392
- if (
2393
- activeDisplayId.value !== fallbackDisplayId &&
2394
- !isConfigRenderedDisplay(activeDisplayId.value) &&
2395
- !availableDisplays.value.some((d) => d.id === activeDisplayId.value)
2396
- ) {
2397
- activeDisplayId.value = fallbackDisplayId;
2398
- }
2399
- });
124
+ bulkCustomActions,
125
+ allMatching,
126
+ runBulkAction,
127
+ canToggleArchived,
128
+ customNavItems,
129
+ deleteRows,
130
+ archiveRows,
131
+ restoreRows,
132
+ handleExportTable,
133
+ handleExportSelection,
134
+ handleRowClick,
135
+ handleRowDuplicate,
136
+ handleRowAdd,
137
+ presenceByRowFiltered,
138
+ expandableConfig,
139
+ expandedModel,
140
+ expandedDetails,
141
+ expandedRowLoadState,
142
+ expandedRowProps,
143
+ handleRowEdit,
144
+ contextForSlot,
145
+ } = useTableViewSetup<T>(props);
2400
146
  </script>
2401
147
 
2402
148
  <template>