@antelopejs/dms 0.5.5 → 0.6.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 (1275) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +8 -0
  3. package/data/NOTICE.md +12 -0
  4. package/data/dbip-country-lite.mmdb +0 -0
  5. package/dist/attachments/access.d.ts +2 -2
  6. package/dist/attachments/access.js +2 -2
  7. package/dist/attachments/access.js.map +1 -1
  8. package/dist/attachments/table-view.d.ts +1 -1
  9. package/dist/attachments/table-view.js +2 -2
  10. package/dist/attachments/table-view.js.map +1 -1
  11. package/dist/config.d.ts +5 -1
  12. package/dist/config.js +1 -1
  13. package/dist/config.js.map +1 -1
  14. package/dist/crons/cleanup-user-invites.js +2 -2
  15. package/dist/crons/cleanup-user-invites.js.map +1 -1
  16. package/dist/db/models/index.d.ts +3 -0
  17. package/dist/db/models/index.js +3 -0
  18. package/dist/db/models/index.js.map +1 -1
  19. package/dist/db/models/notification-feed-filter.d.ts +39 -0
  20. package/dist/db/models/notification-feed-filter.js +143 -0
  21. package/dist/db/models/notification-feed-filter.js.map +1 -0
  22. package/dist/db/models/signInAttempts.model.d.ts +29 -0
  23. package/dist/db/models/signInAttempts.model.js +67 -0
  24. package/dist/db/models/signInAttempts.model.js.map +1 -0
  25. package/dist/db/models/userEmailChanges.model.d.ts +31 -0
  26. package/dist/db/models/userEmailChanges.model.js +21 -0
  27. package/dist/db/models/userEmailChanges.model.js.map +1 -0
  28. package/dist/db/models/userKnownDevices.model.d.ts +25 -0
  29. package/dist/db/models/userKnownDevices.model.js +45 -0
  30. package/dist/db/models/userKnownDevices.model.js.map +1 -0
  31. package/dist/db/models/userNotificationPreferences.model.d.ts +4 -0
  32. package/dist/db/models/userNotificationPreferences.model.js +28 -0
  33. package/dist/db/models/userNotificationPreferences.model.js.map +1 -1
  34. package/dist/db/models/userNotifications.model.d.ts +39 -5
  35. package/dist/db/models/userNotifications.model.js +152 -45
  36. package/dist/db/models/userNotifications.model.js.map +1 -1
  37. package/dist/db/tables/index.d.ts +3 -0
  38. package/dist/db/tables/index.js +3 -0
  39. package/dist/db/tables/index.js.map +1 -1
  40. package/dist/db/tables/signInAttempts.table.d.ts +9 -0
  41. package/dist/db/tables/signInAttempts.table.js +42 -0
  42. package/dist/db/tables/signInAttempts.table.js.map +1 -0
  43. package/dist/db/tables/systemState.table.d.ts +2 -0
  44. package/dist/db/tables/systemState.table.js +8 -0
  45. package/dist/db/tables/systemState.table.js.map +1 -1
  46. package/dist/db/tables/userEmailChanges.table.d.ts +9 -0
  47. package/dist/db/tables/userEmailChanges.table.js +45 -0
  48. package/dist/db/tables/userEmailChanges.table.js.map +1 -0
  49. package/dist/db/tables/userKnownDevices.table.d.ts +9 -0
  50. package/dist/db/tables/userKnownDevices.table.js +45 -0
  51. package/dist/db/tables/userKnownDevices.table.js.map +1 -0
  52. package/dist/db/tables/userNotificationPreferences.table.d.ts +1 -0
  53. package/dist/db/tables/userNotificationPreferences.table.js +4 -0
  54. package/dist/db/tables/userNotificationPreferences.table.js.map +1 -1
  55. package/dist/db/tables/userNotifications.table.d.ts +3 -0
  56. package/dist/db/tables/userNotifications.table.js +8 -0
  57. package/dist/db/tables/userNotifications.table.js.map +1 -1
  58. package/dist/dev/module-update-notifications.js +4 -1
  59. package/dist/dev/module-update-notifications.js.map +1 -1
  60. package/dist/hooks/invite-extensions.js +3 -3
  61. package/dist/hooks/invite-extensions.js.map +1 -1
  62. package/dist/hooks/workspace-notifications.d.ts +1 -0
  63. package/dist/hooks/workspace-notifications.js +26 -0
  64. package/dist/hooks/workspace-notifications.js.map +1 -0
  65. package/dist/implementations/dms/dev-reload.d.ts +1 -0
  66. package/dist/implementations/dms/dev-reload.js +9 -0
  67. package/dist/implementations/dms/dev-reload.js.map +1 -1
  68. package/dist/implementations/dms/invite-extensions.d.ts +1 -1
  69. package/dist/implementations/dms/invite-extensions.js +3 -3
  70. package/dist/implementations/dms/invite-extensions.js.map +1 -1
  71. package/dist/implementations/dms/nav-badges.d.ts +15 -0
  72. package/dist/implementations/dms/nav-badges.js +34 -0
  73. package/dist/implementations/dms/nav-badges.js.map +1 -0
  74. package/dist/implementations/dms/page.d.ts +45 -7
  75. package/dist/implementations/dms/page.js +484 -32
  76. package/dist/implementations/dms/page.js.map +1 -1
  77. package/dist/implementations/dms/permission-preview.d.ts +43 -0
  78. package/dist/implementations/dms/permission-preview.js +124 -0
  79. package/dist/implementations/dms/permission-preview.js.map +1 -0
  80. package/dist/implementations/dms/saas-mode.d.ts +1 -1
  81. package/dist/implementations/dms/uploads.d.ts +2 -2
  82. package/dist/implementations/dms-auth/index.d.ts +2 -1
  83. package/dist/implementations/dms-auth/index.js +15 -17
  84. package/dist/implementations/dms-auth/index.js.map +1 -1
  85. package/dist/implementations/dms-auth/session-handoff.d.ts +8 -0
  86. package/dist/implementations/dms-auth/session-handoff.js +46 -0
  87. package/dist/implementations/dms-auth/session-handoff.js.map +1 -0
  88. package/dist/implementations/dms-auth/token-secret.d.ts +1 -0
  89. package/dist/implementations/dms-auth/token-secret.js +9 -0
  90. package/dist/implementations/dms-auth/token-secret.js.map +1 -0
  91. package/dist/implementations/dms-base/bulk-selection.d.ts +3 -0
  92. package/dist/implementations/dms-base/bulk-selection.js +28 -0
  93. package/dist/implementations/dms-base/bulk-selection.js.map +1 -0
  94. package/dist/implementations/dms-base/filter-tokens.d.ts +7 -0
  95. package/dist/implementations/dms-base/filter-tokens.js +30 -0
  96. package/dist/implementations/dms-base/filter-tokens.js.map +1 -0
  97. package/dist/implementations/dms-base/footer-summary.d.ts +12 -0
  98. package/dist/implementations/dms-base/footer-summary.js +74 -0
  99. package/dist/implementations/dms-base/footer-summary.js.map +1 -0
  100. package/dist/implementations/dms-base/search-route.d.ts +1 -0
  101. package/dist/implementations/dms-base/search-route.js +11 -6
  102. package/dist/implementations/dms-base/search-route.js.map +1 -1
  103. package/dist/implementations/dms-base/table-view.d.ts +2 -1
  104. package/dist/implementations/dms-base/table-view.js +24 -7
  105. package/dist/implementations/dms-base/table-view.js.map +1 -1
  106. package/dist/implementations/dms-html-render/service-jwt.js +1 -1
  107. package/dist/implementations/dms-html-render/service-jwt.js.map +1 -1
  108. package/dist/implementations/dms-notifications/delivery-dedupe.d.ts +9 -0
  109. package/dist/implementations/dms-notifications/delivery-dedupe.js +38 -0
  110. package/dist/implementations/dms-notifications/delivery-dedupe.js.map +1 -0
  111. package/dist/implementations/dms-notifications/delivery-guard.d.ts +2 -0
  112. package/dist/implementations/dms-notifications/delivery-guard.js +7 -0
  113. package/dist/implementations/dms-notifications/delivery-guard.js.map +1 -0
  114. package/dist/implementations/dms-notifications/index.d.ts +7 -5
  115. package/dist/implementations/dms-notifications/index.js +72 -28
  116. package/dist/implementations/dms-notifications/index.js.map +1 -1
  117. package/dist/implementations/dms-notifications/registry.d.ts +2 -1
  118. package/dist/implementations/dms-notifications/registry.js +12 -3
  119. package/dist/implementations/dms-notifications/registry.js.map +1 -1
  120. package/dist/index.js +11 -2
  121. package/dist/index.js.map +1 -1
  122. package/dist/page-extensions/pending-report.js +2 -1
  123. package/dist/page-extensions/pending-report.js.map +1 -1
  124. package/dist/pages/settings/overview/account-activity.d.ts +4 -0
  125. package/dist/pages/settings/overview/account-activity.js +29 -0
  126. package/dist/pages/settings/overview/account-activity.js.map +1 -0
  127. package/dist/pages/settings/overview/account-summary.d.ts +7 -0
  128. package/dist/pages/settings/overview/account-summary.js +64 -0
  129. package/dist/pages/settings/overview/account-summary.js.map +1 -0
  130. package/dist/pages/settings/settings-index.d.ts +11 -1
  131. package/dist/pages/settings/settings-index.js +83 -4
  132. package/dist/pages/settings/settings-index.js.map +1 -1
  133. package/dist/pages/settings/users/account-activity-feed.d.ts +11 -0
  134. package/dist/pages/settings/users/account-activity-feed.js +198 -0
  135. package/dist/pages/settings/users/account-activity-feed.js.map +1 -0
  136. package/dist/pages/settings/users/account-activity-store.d.ts +3 -0
  137. package/dist/pages/settings/users/account-activity-store.js +77 -0
  138. package/dist/pages/settings/users/account-activity-store.js.map +1 -0
  139. package/dist/pages/settings/users/account-activity.d.ts +47 -0
  140. package/dist/pages/settings/users/account-activity.js +180 -0
  141. package/dist/pages/settings/users/account-activity.js.map +1 -0
  142. package/dist/pages/settings/users/account-credentials.d.ts +46 -0
  143. package/dist/pages/settings/users/account-credentials.js +99 -0
  144. package/dist/pages/settings/users/account-credentials.js.map +1 -0
  145. package/dist/pages/settings/users/account-data-store.d.ts +25 -0
  146. package/dist/pages/settings/users/account-data-store.js +188 -0
  147. package/dist/pages/settings/users/account-data-store.js.map +1 -0
  148. package/dist/pages/settings/users/account-data.d.ts +76 -0
  149. package/dist/pages/settings/users/account-data.js +131 -0
  150. package/dist/pages/settings/users/account-data.js.map +1 -0
  151. package/dist/pages/settings/users/appearance.d.ts +5 -1
  152. package/dist/pages/settings/users/appearance.js +39 -6
  153. package/dist/pages/settings/users/appearance.js.map +1 -1
  154. package/dist/pages/settings/users/category.js +3 -1
  155. package/dist/pages/settings/users/category.js.map +1 -1
  156. package/dist/pages/settings/users/current-password.d.ts +3 -0
  157. package/dist/pages/settings/users/current-password.js +19 -0
  158. package/dist/pages/settings/users/current-password.js.map +1 -0
  159. package/dist/pages/settings/users/dashboard-languages.d.ts +4 -0
  160. package/dist/pages/settings/users/dashboard-languages.js +8 -0
  161. package/dist/pages/settings/users/dashboard-languages.js.map +1 -0
  162. package/dist/pages/settings/users/email-change.d.ts +11 -0
  163. package/dist/pages/settings/users/email-change.js +87 -0
  164. package/dist/pages/settings/users/email-change.js.map +1 -0
  165. package/dist/pages/settings/users/index.d.ts +2 -0
  166. package/dist/pages/settings/users/index.js +2 -0
  167. package/dist/pages/settings/users/index.js.map +1 -1
  168. package/dist/pages/settings/users/invite-extension-routes.js +8 -9
  169. package/dist/pages/settings/users/invite-extension-routes.js.map +1 -1
  170. package/dist/pages/settings/users/invite-resend.d.ts +7 -0
  171. package/dist/pages/settings/users/invite-resend.js +41 -0
  172. package/dist/pages/settings/users/invite-resend.js.map +1 -0
  173. package/dist/pages/settings/users/invites.d.ts +12 -5
  174. package/dist/pages/settings/users/invites.js +207 -65
  175. package/dist/pages/settings/users/invites.js.map +1 -1
  176. package/dist/pages/settings/users/member-change-notifications.d.ts +5 -0
  177. package/dist/pages/settings/users/member-change-notifications.js +51 -0
  178. package/dist/pages/settings/users/member-change-notifications.js.map +1 -0
  179. package/dist/pages/settings/users/member-invite-batch.d.ts +37 -0
  180. package/dist/pages/settings/users/member-invite-batch.js +108 -0
  181. package/dist/pages/settings/users/member-invite-batch.js.map +1 -0
  182. package/dist/pages/settings/users/member-invite-form.d.ts +3 -5
  183. package/dist/pages/settings/users/member-invite-form.js +59 -74
  184. package/dist/pages/settings/users/member-invite-form.js.map +1 -1
  185. package/dist/pages/settings/users/member-management.d.ts +23 -0
  186. package/dist/pages/settings/users/member-management.js +107 -0
  187. package/dist/pages/settings/users/member-management.js.map +1 -0
  188. package/dist/pages/settings/users/member-role-options.d.ts +13 -0
  189. package/dist/pages/settings/users/member-role-options.js +28 -0
  190. package/dist/pages/settings/users/member-role-options.js.map +1 -0
  191. package/dist/pages/settings/users/member-roles-field.d.ts +8 -0
  192. package/dist/pages/settings/users/member-roles-field.js +44 -0
  193. package/dist/pages/settings/users/member-roles-field.js.map +1 -0
  194. package/dist/pages/settings/users/members.d.ts +31 -7
  195. package/dist/pages/settings/users/members.js +304 -122
  196. package/dist/pages/settings/users/members.js.map +1 -1
  197. package/dist/pages/settings/users/notifications.d.ts +38 -6
  198. package/dist/pages/settings/users/notifications.js +316 -33
  199. package/dist/pages/settings/users/notifications.js.map +1 -1
  200. package/dist/pages/settings/users/permission-tree-nodes.d.ts +7 -3
  201. package/dist/pages/settings/users/permission-tree-nodes.js +22 -15
  202. package/dist/pages/settings/users/permission-tree-nodes.js.map +1 -1
  203. package/dist/pages/settings/users/profile-access.d.ts +7 -0
  204. package/dist/pages/settings/users/profile-access.js +15 -0
  205. package/dist/pages/settings/users/profile-access.js.map +1 -0
  206. package/dist/pages/settings/users/profile-helpers.d.ts +7 -2
  207. package/dist/pages/settings/users/profile-helpers.js +10 -7
  208. package/dist/pages/settings/users/profile-helpers.js.map +1 -1
  209. package/dist/pages/settings/users/profile.d.ts +15 -37
  210. package/dist/pages/settings/users/profile.js +137 -242
  211. package/dist/pages/settings/users/profile.js.map +1 -1
  212. package/dist/pages/settings/users/region-form.d.ts +2 -0
  213. package/dist/pages/settings/users/region-form.js +93 -0
  214. package/dist/pages/settings/users/region-form.js.map +1 -0
  215. package/dist/pages/settings/users/region.d.ts +14 -0
  216. package/dist/pages/settings/users/region.js +77 -0
  217. package/dist/pages/settings/users/region.js.map +1 -0
  218. package/dist/pages/settings/users/regional-preferences.d.ts +14 -0
  219. package/dist/pages/settings/users/regional-preferences.js +56 -0
  220. package/dist/pages/settings/users/regional-preferences.js.map +1 -0
  221. package/dist/pages/settings/users/role-editor-store.d.ts +19 -0
  222. package/dist/pages/settings/users/role-editor-store.js +196 -0
  223. package/dist/pages/settings/users/role-editor-store.js.map +1 -0
  224. package/dist/pages/settings/users/role-editor.d.ts +60 -0
  225. package/dist/pages/settings/users/role-editor.js +109 -0
  226. package/dist/pages/settings/users/role-editor.js.map +1 -0
  227. package/dist/pages/settings/users/role-preview.d.ts +41 -0
  228. package/dist/pages/settings/users/role-preview.js +97 -0
  229. package/dist/pages/settings/users/role-preview.js.map +1 -0
  230. package/dist/pages/settings/users/roles.d.ts +18 -3
  231. package/dist/pages/settings/users/roles.js +235 -26
  232. package/dist/pages/settings/users/roles.js.map +1 -1
  233. package/dist/pages/settings/users/security-attention.d.ts +3 -0
  234. package/dist/pages/settings/users/security-attention.js +22 -0
  235. package/dist/pages/settings/users/security-attention.js.map +1 -0
  236. package/dist/pages/settings/users/security.d.ts +31 -0
  237. package/dist/pages/settings/users/security.js +251 -0
  238. package/dist/pages/settings/users/security.js.map +1 -0
  239. package/dist/pages/settings/users/shortcuts.js +2 -3
  240. package/dist/pages/settings/users/shortcuts.js.map +1 -1
  241. package/dist/pages/settings/users/two-factor-operations.d.ts +33 -0
  242. package/dist/pages/settings/users/two-factor-operations.js +156 -0
  243. package/dist/pages/settings/users/two-factor-operations.js.map +1 -0
  244. package/dist/routes/auth/client-ip.js +2 -5
  245. package/dist/routes/auth/client-ip.js.map +1 -1
  246. package/dist/routes/auth/index.d.ts +1 -0
  247. package/dist/routes/auth/index.js +1 -0
  248. package/dist/routes/auth/index.js.map +1 -1
  249. package/dist/routes/auth/login-throttle.d.ts +3 -0
  250. package/dist/routes/auth/login-throttle.js +29 -0
  251. package/dist/routes/auth/login-throttle.js.map +1 -0
  252. package/dist/routes/auth/login.d.ts +2 -1
  253. package/dist/routes/auth/login.js +16 -4
  254. package/dist/routes/auth/login.js.map +1 -1
  255. package/dist/routes/auth/oauth/callback.d.ts +3 -2
  256. package/dist/routes/auth/oauth/callback.js +4 -3
  257. package/dist/routes/auth/oauth/callback.js.map +1 -1
  258. package/dist/routes/auth/reset-password.js +3 -1
  259. package/dist/routes/auth/reset-password.js.map +1 -1
  260. package/dist/routes/auth/session-handoff.d.ts +4 -0
  261. package/dist/routes/auth/session-handoff.js +26 -0
  262. package/dist/routes/auth/session-handoff.js.map +1 -0
  263. package/dist/routes/auth/session-response.d.ts +3 -2
  264. package/dist/routes/auth/session-response.js +6 -6
  265. package/dist/routes/auth/session-response.js.map +1 -1
  266. package/dist/routes/auth/signup.d.ts +2 -1
  267. package/dist/routes/auth/signup.js +4 -2
  268. package/dist/routes/auth/signup.js.map +1 -1
  269. package/dist/routes/auth/verify-2fa.d.ts +2 -1
  270. package/dist/routes/auth/verify-2fa.js +8 -3
  271. package/dist/routes/auth/verify-2fa.js.map +1 -1
  272. package/dist/routes/auth.d.ts +2 -0
  273. package/dist/routes/auth.js +18 -4
  274. package/dist/routes/auth.js.map +1 -1
  275. package/dist/routes/onboarding.d.ts +1 -0
  276. package/dist/routes/onboarding.js +14 -4
  277. package/dist/routes/onboarding.js.map +1 -1
  278. package/dist/routes/system-state.d.ts +2 -0
  279. package/dist/routes/system-state.js +1 -1
  280. package/dist/routes/system-state.js.map +1 -1
  281. package/dist/test/antelope.test.js +1 -1
  282. package/dist/test/attachment-host/archive.d.ts +58 -0
  283. package/dist/test/attachment-host/archive.js +79 -0
  284. package/dist/test/attachment-host/archive.js.map +1 -0
  285. package/dist/test/attachment-host/capabilities.d.ts +82 -0
  286. package/dist/test/attachment-host/capabilities.js +189 -0
  287. package/dist/test/attachment-host/capabilities.js.map +1 -0
  288. package/dist/test/attachment-host/derived.d.ts +74 -0
  289. package/dist/test/attachment-host/derived.js +96 -0
  290. package/dist/test/attachment-host/derived.js.map +1 -0
  291. package/dist/test/attachment-host/index.d.ts +3 -0
  292. package/dist/test/attachment-host/index.js +3 -0
  293. package/dist/test/attachment-host/index.js.map +1 -1
  294. package/dist/test/attachment-host/native.js +9 -3
  295. package/dist/test/attachment-host/native.js.map +1 -1
  296. package/dist/test/helpers/derived-controller.d.ts +12 -0
  297. package/dist/test/helpers/derived-controller.js +20 -0
  298. package/dist/test/helpers/derived-controller.js.map +1 -0
  299. package/dist/test/integration/account-deletion.test.d.ts +1 -0
  300. package/dist/test/integration/account-deletion.test.js +84 -0
  301. package/dist/test/integration/account-deletion.test.js.map +1 -0
  302. package/dist/test/integration/auth/auth-key-rotation.test.d.ts +1 -0
  303. package/dist/test/integration/auth/auth-key-rotation.test.js +77 -0
  304. package/dist/test/integration/auth/auth-key-rotation.test.js.map +1 -0
  305. package/dist/test/integration/auth/login-throttle.test.d.ts +1 -0
  306. package/dist/test/integration/auth/login-throttle.test.js +88 -0
  307. package/dist/test/integration/auth/login-throttle.test.js.map +1 -0
  308. package/dist/test/integration/auth/sign-in-country.test.d.ts +1 -0
  309. package/dist/test/integration/auth/sign-in-country.test.js +75 -0
  310. package/dist/test/integration/auth/sign-in-country.test.js.map +1 -0
  311. package/dist/test/integration/auth/two-factor-password.test.d.ts +1 -0
  312. package/dist/test/integration/auth/two-factor-password.test.js +40 -0
  313. package/dist/test/integration/auth/two-factor-password.test.js.map +1 -0
  314. package/dist/test/integration/derived-controller.test.d.ts +1 -0
  315. package/dist/test/integration/derived-controller.test.js +105 -0
  316. package/dist/test/integration/derived-controller.test.js.map +1 -0
  317. package/dist/test/integration/email-change.test.d.ts +1 -0
  318. package/dist/test/integration/email-change.test.js +100 -0
  319. package/dist/test/integration/email-change.test.js.map +1 -0
  320. package/dist/test/integration/export-cleanup.test.js +1 -1
  321. package/dist/test/integration/export-cleanup.test.js.map +1 -1
  322. package/dist/test/integration/files/shared-controller-files.test.js +31 -21
  323. package/dist/test/integration/files/shared-controller-files.test.js.map +1 -1
  324. package/dist/test/integration/invite-extension-edit.test.js +5 -5
  325. package/dist/test/integration/invite-extension-edit.test.js.map +1 -1
  326. package/dist/test/integration/invite-resolution.test.js +6 -6
  327. package/dist/test/integration/invite-resolution.test.js.map +1 -1
  328. package/dist/test/integration/member-change-notifications.test.d.ts +1 -0
  329. package/dist/test/integration/member-change-notifications.test.js +52 -0
  330. package/dist/test/integration/member-change-notifications.test.js.map +1 -0
  331. package/dist/test/integration/member-settings-access.test.d.ts +1 -0
  332. package/dist/test/integration/member-settings-access.test.js +100 -0
  333. package/dist/test/integration/member-settings-access.test.js.map +1 -0
  334. package/dist/test/integration/notification-inbox.test.d.ts +1 -0
  335. package/dist/test/integration/notification-inbox.test.js +97 -0
  336. package/dist/test/integration/notification-inbox.test.js.map +1 -0
  337. package/dist/test/integration/notification-locked-subjects.test.d.ts +1 -0
  338. package/dist/test/integration/notification-locked-subjects.test.js +81 -0
  339. package/dist/test/integration/notification-locked-subjects.test.js.map +1 -0
  340. package/dist/test/integration/notifications.test.js +46 -1
  341. package/dist/test/integration/notifications.test.js.map +1 -1
  342. package/dist/test/integration/role-delete-reassign.test.d.ts +1 -0
  343. package/dist/test/integration/role-delete-reassign.test.js +68 -0
  344. package/dist/test/integration/role-delete-reassign.test.js.map +1 -0
  345. package/dist/test/integration/sign-in-records.test.d.ts +1 -0
  346. package/dist/test/integration/sign-in-records.test.js +41 -0
  347. package/dist/test/integration/sign-in-records.test.js.map +1 -0
  348. package/dist/test/integration/table-view-archive.test.d.ts +1 -0
  349. package/dist/test/integration/table-view-archive.test.js +46 -0
  350. package/dist/test/integration/table-view-archive.test.js.map +1 -0
  351. package/dist/test/integration/table-view-capabilities.test.d.ts +1 -0
  352. package/dist/test/integration/table-view-capabilities.test.js +146 -0
  353. package/dist/test/integration/table-view-capabilities.test.js.map +1 -0
  354. package/dist/test/integration/tenant-lifecycle.test.js +1 -1
  355. package/dist/test/integration/tenant-lifecycle.test.js.map +1 -1
  356. package/dist/test/unit/client-ip.test.js +0 -6
  357. package/dist/test/unit/client-ip.test.js.map +1 -1
  358. package/dist/test/unit/db/notification-feed-filter.test.d.ts +1 -0
  359. package/dist/test/unit/db/notification-feed-filter.test.js +144 -0
  360. package/dist/test/unit/db/notification-feed-filter.test.js.map +1 -0
  361. package/dist/test/unit/db/notification-inbox.test.d.ts +1 -0
  362. package/dist/test/unit/db/notification-inbox.test.js +110 -0
  363. package/dist/test/unit/db/notification-inbox.test.js.map +1 -0
  364. package/dist/test/unit/db/notification-preferences.test.js +35 -0
  365. package/dist/test/unit/db/notification-preferences.test.js.map +1 -1
  366. package/dist/test/unit/db/session-refresh-token.test.js +3 -14
  367. package/dist/test/unit/db/session-refresh-token.test.js.map +1 -1
  368. package/dist/test/unit/db/session-sweep.test.js +0 -1
  369. package/dist/test/unit/db/session-sweep.test.js.map +1 -1
  370. package/dist/test/unit/implementations/dms/dev-reload.test.js +41 -0
  371. package/dist/test/unit/implementations/dms/dev-reload.test.js.map +1 -1
  372. package/dist/test/unit/implementations/dms/gate-consistency.test.js +1 -1
  373. package/dist/test/unit/implementations/dms/gate-consistency.test.js.map +1 -1
  374. package/dist/test/unit/implementations/dms/missing-category.test.js +46 -0
  375. package/dist/test/unit/implementations/dms/missing-category.test.js.map +1 -1
  376. package/dist/test/unit/implementations/dms/nav-badges.test.d.ts +1 -0
  377. package/dist/test/unit/implementations/dms/nav-badges.test.js +146 -0
  378. package/dist/test/unit/implementations/dms/nav-badges.test.js.map +1 -0
  379. package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.d.ts +1 -0
  380. package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js +116 -0
  381. package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js.map +1 -0
  382. package/dist/test/unit/implementations/dms/permission-preview-cost.test.d.ts +1 -0
  383. package/dist/test/unit/implementations/dms/permission-preview-cost.test.js +118 -0
  384. package/dist/test/unit/implementations/dms/permission-preview-cost.test.js.map +1 -0
  385. package/dist/test/unit/implementations/dms/permission-preview-header.test.d.ts +1 -0
  386. package/dist/test/unit/implementations/dms/permission-preview-header.test.js +78 -0
  387. package/dist/test/unit/implementations/dms/permission-preview-header.test.js.map +1 -0
  388. package/dist/test/unit/implementations/dms/permission-preview-menu.test.d.ts +1 -0
  389. package/dist/test/unit/implementations/dms/permission-preview-menu.test.js +162 -0
  390. package/dist/test/unit/implementations/dms/permission-preview-menu.test.js.map +1 -0
  391. package/dist/test/unit/implementations/dms-base/filter-tokens.test.d.ts +1 -0
  392. package/dist/test/unit/implementations/dms-base/filter-tokens.test.js +39 -0
  393. package/dist/test/unit/implementations/dms-base/filter-tokens.test.js.map +1 -0
  394. package/dist/test/unit/implementations/dms-base/footer-summary.test.d.ts +1 -0
  395. package/dist/test/unit/implementations/dms-base/footer-summary.test.js +51 -0
  396. package/dist/test/unit/implementations/dms-base/footer-summary.test.js.map +1 -0
  397. package/dist/test/unit/implementations/dms-notifications/delivery-dedupe.test.d.ts +1 -0
  398. package/dist/test/unit/implementations/dms-notifications/delivery-dedupe.test.js +100 -0
  399. package/dist/test/unit/implementations/dms-notifications/delivery-dedupe.test.js.map +1 -0
  400. package/dist/test/unit/implementations/dms-notifications/delivery-guard.test.d.ts +1 -0
  401. package/dist/test/unit/implementations/dms-notifications/delivery-guard.test.js +20 -0
  402. package/dist/test/unit/implementations/dms-notifications/delivery-guard.test.js.map +1 -0
  403. package/dist/test/unit/implementations/notification-subject-lock.test.d.ts +1 -0
  404. package/dist/test/unit/implementations/notification-subject-lock.test.js +31 -0
  405. package/dist/test/unit/implementations/notification-subject-lock.test.js.map +1 -0
  406. package/dist/test/unit/interfaces/dms/category-default-layout.test.d.ts +1 -0
  407. package/dist/test/unit/interfaces/dms/category-default-layout.test.js +85 -0
  408. package/dist/test/unit/interfaces/dms/category-default-layout.test.js.map +1 -0
  409. package/dist/test/unit/interfaces/dms/component-children-permissions.test.js +2 -2
  410. package/dist/test/unit/interfaces/dms/component-children-permissions.test.js.map +1 -1
  411. package/dist/test/unit/interfaces/dms/invite-extension.test.js +31 -28
  412. package/dist/test/unit/interfaces/dms/invite-extension.test.js.map +1 -1
  413. package/dist/test/unit/interfaces/dms/member-access.test.d.ts +1 -0
  414. package/dist/test/unit/interfaces/dms/member-access.test.js +117 -0
  415. package/dist/test/unit/interfaces/dms/member-access.test.js.map +1 -0
  416. package/dist/test/unit/interfaces/dms/module-permission-registration.test.js +11 -0
  417. package/dist/test/unit/interfaces/dms/module-permission-registration.test.js.map +1 -1
  418. package/dist/test/unit/interfaces/dms/module-reload-registrations.test.js +1 -1
  419. package/dist/test/unit/interfaces/dms/module-reload-registrations.test.js.map +1 -1
  420. package/dist/test/unit/interfaces/dms/page-extension.test.js +2 -1
  421. package/dist/test/unit/interfaces/dms/page-extension.test.js.map +1 -1
  422. package/dist/test/unit/interfaces/dms/page-registration-identity.test.js +5 -4
  423. package/dist/test/unit/interfaces/dms/page-registration-identity.test.js.map +1 -1
  424. package/dist/test/unit/interfaces/dms/tenant-invite-email.test.js +2 -2
  425. package/dist/test/unit/interfaces/dms/tenant-invite-email.test.js.map +1 -1
  426. package/dist/test/unit/interfaces/dms-auth/refresh-token-rotation.test.js +20 -32
  427. package/dist/test/unit/interfaces/dms-auth/refresh-token-rotation.test.js.map +1 -1
  428. package/dist/test/unit/interfaces/dms-base/block-vocabulary.test.d.ts +1 -0
  429. package/dist/test/unit/interfaces/dms-base/block-vocabulary.test.js +76 -0
  430. package/dist/test/unit/interfaces/dms-base/block-vocabulary.test.js.map +1 -0
  431. package/dist/test/unit/interfaces/dms-base/column-display.test.d.ts +1 -0
  432. package/dist/test/unit/interfaces/dms-base/column-display.test.js +98 -0
  433. package/dist/test/unit/interfaces/dms-base/column-display.test.js.map +1 -0
  434. package/dist/test/unit/interfaces/dms-base/data-types/field-types.test.d.ts +1 -0
  435. package/dist/test/unit/interfaces/dms-base/data-types/field-types.test.js +155 -0
  436. package/dist/test/unit/interfaces/dms-base/data-types/field-types.test.js.map +1 -0
  437. package/dist/test/unit/interfaces/dms-base/date-type-filter.test.d.ts +1 -0
  438. package/dist/test/unit/interfaces/dms-base/date-type-filter.test.js +34 -0
  439. package/dist/test/unit/interfaces/dms-base/date-type-filter.test.js.map +1 -0
  440. package/dist/test/unit/interfaces/dms-base/date-type-range.test.d.ts +1 -0
  441. package/dist/test/unit/interfaces/dms-base/date-type-range.test.js +29 -0
  442. package/dist/test/unit/interfaces/dms-base/date-type-range.test.js.map +1 -0
  443. package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.d.ts +1 -0
  444. package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js +76 -0
  445. package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js.map +1 -0
  446. package/dist/test/unit/interfaces/dms-base/form-catalog.test.js +10 -5
  447. package/dist/test/unit/interfaces/dms-base/form-catalog.test.js.map +1 -1
  448. package/dist/test/unit/interfaces/dms-base/form-footer.test.d.ts +1 -0
  449. package/dist/test/unit/interfaces/dms-base/form-footer.test.js +12 -0
  450. package/dist/test/unit/interfaces/dms-base/form-footer.test.js.map +1 -0
  451. package/dist/test/unit/interfaces/dms-base/form-sections.test.d.ts +1 -0
  452. package/dist/test/unit/interfaces/dms-base/form-sections.test.js +93 -0
  453. package/dist/test/unit/interfaces/dms-base/form-sections.test.js.map +1 -0
  454. package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.d.ts +1 -0
  455. package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js +222 -0
  456. package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js.map +1 -0
  457. package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.d.ts +1 -0
  458. package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js +43 -0
  459. package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js.map +1 -0
  460. package/dist/test/unit/interfaces/dms-base/table-view-after-write.test.d.ts +1 -0
  461. package/dist/test/unit/interfaces/dms-base/table-view-after-write.test.js +62 -0
  462. package/dist/test/unit/interfaces/dms-base/table-view-after-write.test.js.map +1 -0
  463. package/dist/test/unit/interfaces/dms-base/table-view-bulk-operations.test.d.ts +1 -0
  464. package/dist/test/unit/interfaces/dms-base/table-view-bulk-operations.test.js +259 -0
  465. package/dist/test/unit/interfaces/dms-base/table-view-bulk-operations.test.js.map +1 -0
  466. package/dist/test/unit/interfaces/dms-base/table-view-column-validator.test.d.ts +1 -0
  467. package/dist/test/unit/interfaces/dms-base/table-view-column-validator.test.js +87 -0
  468. package/dist/test/unit/interfaces/dms-base/table-view-column-validator.test.js.map +1 -0
  469. package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.d.ts +1 -0
  470. package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js +90 -0
  471. package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js.map +1 -0
  472. package/dist/test/unit/interfaces/dms-base/table-view-footer.test.d.ts +1 -0
  473. package/dist/test/unit/interfaces/dms-base/table-view-footer.test.js +177 -0
  474. package/dist/test/unit/interfaces/dms-base/table-view-footer.test.js.map +1 -0
  475. package/dist/test/unit/interfaces/dms-base/table-view-form-page-texts.test.d.ts +1 -0
  476. package/dist/test/unit/interfaces/dms-base/table-view-form-page-texts.test.js +36 -0
  477. package/dist/test/unit/interfaces/dms-base/table-view-form-page-texts.test.js.map +1 -0
  478. package/dist/test/unit/interfaces/dms-base/table-view-form-page-urls.test.js +15 -13
  479. package/dist/test/unit/interfaces/dms-base/table-view-form-page-urls.test.js.map +1 -1
  480. package/dist/test/unit/interfaces/dms-base/table-view-form-redirect.test.js +9 -7
  481. package/dist/test/unit/interfaces/dms-base/table-view-form-redirect.test.js.map +1 -1
  482. package/dist/test/unit/interfaces/dms-base/table-view-meta-inherit.test.d.ts +1 -0
  483. package/dist/test/unit/interfaces/dms-base/table-view-meta-inherit.test.js +119 -0
  484. package/dist/test/unit/interfaces/dms-base/table-view-meta-inherit.test.js.map +1 -0
  485. package/dist/test/unit/interfaces/dms-base/table-view-one-writer.test.d.ts +1 -0
  486. package/dist/test/unit/interfaces/dms-base/table-view-one-writer.test.js +179 -0
  487. package/dist/test/unit/interfaces/dms-base/table-view-one-writer.test.js.map +1 -0
  488. package/dist/test/unit/interfaces/dms-base/table-view-realtime-no-change.test.d.ts +1 -0
  489. package/dist/test/unit/interfaces/dms-base/table-view-realtime-no-change.test.js +23 -0
  490. package/dist/test/unit/interfaces/dms-base/table-view-realtime-no-change.test.js.map +1 -0
  491. package/dist/test/unit/interfaces/dms-base/table-view-realtime.test.js +1 -1
  492. package/dist/test/unit/interfaces/dms-base/table-view-realtime.test.js.map +1 -1
  493. package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.d.ts +1 -0
  494. package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js +454 -0
  495. package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js.map +1 -0
  496. package/dist/test/unit/interfaces/dms-base/table-view-route-param-filter-defaults.test.js +8 -6
  497. package/dist/test/unit/interfaces/dms-base/table-view-route-param-filter-defaults.test.js.map +1 -1
  498. package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.d.ts +1 -0
  499. package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js +144 -0
  500. package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js.map +1 -0
  501. package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.d.ts +1 -0
  502. package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.js +188 -0
  503. package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.js.map +1 -0
  504. package/dist/test/unit/interfaces/dms-base/table-view-tab-count-warning.test.js +1 -1
  505. package/dist/test/unit/interfaces/dms-base/table-view-tab-count-warning.test.js.map +1 -1
  506. package/dist/test/unit/interfaces/dms-base/table-view-tenant-gate.test.js +14 -13
  507. package/dist/test/unit/interfaces/dms-base/table-view-tenant-gate.test.js.map +1 -1
  508. package/dist/test/unit/interfaces/dms-base/table-view-views.test.d.ts +1 -0
  509. package/dist/test/unit/interfaces/dms-base/table-view-views.test.js +314 -0
  510. package/dist/test/unit/interfaces/dms-base/table-view-views.test.js.map +1 -0
  511. package/dist/test/unit/interfaces/dms-base/table-view-writer-row-rules.test.d.ts +1 -0
  512. package/dist/test/unit/interfaces/dms-base/table-view-writer-row-rules.test.js +292 -0
  513. package/dist/test/unit/interfaces/dms-base/table-view-writer-row-rules.test.js.map +1 -0
  514. package/dist/test/unit/onboarding-platform.test.d.ts +1 -0
  515. package/dist/test/unit/onboarding-platform.test.js +76 -0
  516. package/dist/test/unit/onboarding-platform.test.js.map +1 -0
  517. package/dist/test/unit/pages/settings/account-activity-feed.test.d.ts +1 -0
  518. package/dist/test/unit/pages/settings/account-activity-feed.test.js +116 -0
  519. package/dist/test/unit/pages/settings/account-activity-feed.test.js.map +1 -0
  520. package/dist/test/unit/pages/settings/account-activity.test.d.ts +1 -0
  521. package/dist/test/unit/pages/settings/account-activity.test.js +262 -0
  522. package/dist/test/unit/pages/settings/account-activity.test.js.map +1 -0
  523. package/dist/test/unit/pages/settings/account-data.test.d.ts +1 -0
  524. package/dist/test/unit/pages/settings/account-data.test.js +255 -0
  525. package/dist/test/unit/pages/settings/account-data.test.js.map +1 -0
  526. package/dist/test/unit/pages/settings/account-security.test.d.ts +1 -0
  527. package/dist/test/unit/pages/settings/account-security.test.js +208 -0
  528. package/dist/test/unit/pages/settings/account-security.test.js.map +1 -0
  529. package/dist/test/unit/pages/settings/invite-email-delivery.test.js +24 -18
  530. package/dist/test/unit/pages/settings/invite-email-delivery.test.js.map +1 -1
  531. package/dist/test/unit/pages/settings/invite-member-quick-action.test.js +1 -1
  532. package/dist/test/unit/pages/settings/invite-member-quick-action.test.js.map +1 -1
  533. package/dist/test/unit/pages/settings/member-roles-field.test.d.ts +1 -0
  534. package/dist/test/unit/pages/settings/member-roles-field.test.js +47 -0
  535. package/dist/test/unit/pages/settings/member-roles-field.test.js.map +1 -0
  536. package/dist/test/unit/pages/settings/member-table-widths.test.d.ts +1 -0
  537. package/dist/test/unit/pages/settings/member-table-widths.test.js +53 -0
  538. package/dist/test/unit/pages/settings/member-table-widths.test.js.map +1 -0
  539. package/dist/test/unit/pages/settings/members-page.test.d.ts +1 -0
  540. package/dist/test/unit/pages/settings/members-page.test.js +234 -0
  541. package/dist/test/unit/pages/settings/members-page.test.js.map +1 -0
  542. package/dist/test/unit/pages/settings/permission-tree-nodes.test.js +41 -5
  543. package/dist/test/unit/pages/settings/permission-tree-nodes.test.js.map +1 -1
  544. package/dist/test/unit/pages/settings/regional-preferences.test.d.ts +1 -0
  545. package/dist/test/unit/pages/settings/regional-preferences.test.js +118 -0
  546. package/dist/test/unit/pages/settings/regional-preferences.test.js.map +1 -0
  547. package/dist/test/unit/pages/settings/role-delete-confirm.test.d.ts +1 -0
  548. package/dist/test/unit/pages/settings/role-delete-confirm.test.js +77 -0
  549. package/dist/test/unit/pages/settings/role-delete-confirm.test.js.map +1 -0
  550. package/dist/test/unit/pages/settings/role-editor.test.d.ts +1 -0
  551. package/dist/test/unit/pages/settings/role-editor.test.js +261 -0
  552. package/dist/test/unit/pages/settings/role-editor.test.js.map +1 -0
  553. package/dist/test/unit/pages/settings/role-preview.test.d.ts +1 -0
  554. package/dist/test/unit/pages/settings/role-preview.test.js +200 -0
  555. package/dist/test/unit/pages/settings/role-preview.test.js.map +1 -0
  556. package/dist/test/unit/request-authenticators.test.js +1 -1
  557. package/dist/test/unit/request-authenticators.test.js.map +1 -1
  558. package/dist/test/unit/request-tenant-guards.test.js +2 -1
  559. package/dist/test/unit/request-tenant-guards.test.js.map +1 -1
  560. package/dist/test/unit/signup-account-guard.test.js +1 -1
  561. package/dist/test/unit/signup-account-guard.test.js.map +1 -1
  562. package/dist/test/unit/utils/attempt-limiter.test.d.ts +1 -0
  563. package/dist/test/unit/utils/attempt-limiter.test.js +43 -0
  564. package/dist/test/unit/utils/attempt-limiter.test.js.map +1 -0
  565. package/dist/test/unit/utils/failed-sign-ins.test.d.ts +1 -0
  566. package/dist/test/unit/utils/failed-sign-ins.test.js +57 -0
  567. package/dist/test/unit/utils/failed-sign-ins.test.js.map +1 -0
  568. package/dist/test/unit/utils/notification-rules.test.d.ts +1 -0
  569. package/dist/test/unit/utils/notification-rules.test.js +60 -0
  570. package/dist/test/unit/utils/notification-rules.test.js.map +1 -0
  571. package/dist/test/unit/utils/notification-tones.test.d.ts +1 -0
  572. package/dist/test/unit/utils/notification-tones.test.js +18 -0
  573. package/dist/test/unit/utils/notification-tones.test.js.map +1 -0
  574. package/dist/test/unit/utils/owned-registry.test.js +1 -1
  575. package/dist/test/unit/utils/owned-registry.test.js.map +1 -1
  576. package/dist/test/unit/utils/sign-in-country.test.d.ts +1 -0
  577. package/dist/test/unit/utils/sign-in-country.test.js +70 -0
  578. package/dist/test/unit/utils/sign-in-country.test.js.map +1 -0
  579. package/dist/test/unit/utils/sign-in-devices.test.d.ts +1 -0
  580. package/dist/test/unit/utils/sign-in-devices.test.js +105 -0
  581. package/dist/test/unit/utils/sign-in-devices.test.js.map +1 -0
  582. package/dist/test/unit/utils/type-check.test.js +1 -1
  583. package/dist/test/unit/utils/type-check.test.js.map +1 -1
  584. package/dist/test/unit/utils/user-activity.test.d.ts +1 -0
  585. package/dist/test/unit/utils/user-activity.test.js +85 -0
  586. package/dist/test/unit/utils/user-activity.test.js.map +1 -0
  587. package/dist/test/unit/utils/value-parser.test.js +1 -1
  588. package/dist/test/unit/utils/value-parser.test.js.map +1 -1
  589. package/dist/test/unit/utils/workspace-notifications.test.d.ts +1 -0
  590. package/dist/test/unit/utils/workspace-notifications.test.js +32 -0
  591. package/dist/test/unit/utils/workspace-notifications.test.js.map +1 -0
  592. package/dist/test/unit/validation/onboarding/register-admin.schema.test.js +54 -14
  593. package/dist/test/unit/validation/onboarding/register-admin.schema.test.js.map +1 -1
  594. package/dist/test/unit/validation/user-notification-preferences.schema.test.js +12 -0
  595. package/dist/test/unit/validation/user-notification-preferences.schema.test.js.map +1 -1
  596. package/dist/utils/account-notifications.d.ts +12 -4
  597. package/dist/utils/account-notifications.js +86 -101
  598. package/dist/utils/account-notifications.js.map +1 -1
  599. package/dist/utils/attempt-limiter.d.ts +12 -0
  600. package/dist/utils/attempt-limiter.js +48 -0
  601. package/dist/utils/attempt-limiter.js.map +1 -0
  602. package/dist/utils/email-change-mail.d.ts +3 -0
  603. package/dist/utils/email-change-mail.js +25 -0
  604. package/dist/utils/email-change-mail.js.map +1 -0
  605. package/dist/utils/export-jobs-run.d.ts +1 -1
  606. package/dist/utils/export-jobs-run.js +4 -3
  607. package/dist/utils/export-jobs-run.js.map +1 -1
  608. package/dist/utils/export-jobs.d.ts +3 -1
  609. package/dist/utils/export-jobs.js +11 -4
  610. package/dist/utils/export-jobs.js.map +1 -1
  611. package/dist/utils/failed-sign-ins.d.ts +13 -0
  612. package/dist/utils/failed-sign-ins.js +22 -0
  613. package/dist/utils/failed-sign-ins.js.map +1 -0
  614. package/dist/utils/index.d.ts +3 -3
  615. package/dist/utils/index.js +3 -3
  616. package/dist/utils/index.js.map +1 -1
  617. package/dist/utils/notification-emitter.d.ts +23 -0
  618. package/dist/utils/notification-emitter.js +43 -0
  619. package/dist/utils/notification-emitter.js.map +1 -0
  620. package/dist/utils/notification-rules.d.ts +5 -0
  621. package/dist/utils/notification-rules.js +26 -0
  622. package/dist/utils/notification-rules.js.map +1 -0
  623. package/dist/utils/notification-tones.d.ts +4 -0
  624. package/dist/utils/notification-tones.js +13 -0
  625. package/dist/utils/notification-tones.js.map +1 -0
  626. package/dist/utils/sign-in-country.d.ts +15 -0
  627. package/dist/utils/sign-in-country.js +87 -0
  628. package/dist/utils/sign-in-country.js.map +1 -0
  629. package/dist/utils/sign-in-devices.d.ts +15 -0
  630. package/dist/utils/sign-in-devices.js +43 -0
  631. package/dist/utils/sign-in-devices.js.map +1 -0
  632. package/dist/utils/sign-in-monitor.d.ts +6 -0
  633. package/dist/utils/sign-in-monitor.js +90 -0
  634. package/dist/utils/sign-in-monitor.js.map +1 -0
  635. package/dist/utils/user-activity.d.ts +4 -0
  636. package/dist/utils/user-activity.js +22 -0
  637. package/dist/utils/user-activity.js.map +1 -0
  638. package/dist/utils/user-agent.d.ts +2 -2
  639. package/dist/utils/workspace-notifications.d.ts +28 -0
  640. package/dist/utils/workspace-notifications.js +184 -0
  641. package/dist/utils/workspace-notifications.js.map +1 -0
  642. package/dist/validation/account-deletion.schema.d.ts +12 -0
  643. package/dist/validation/account-deletion.schema.js +44 -0
  644. package/dist/validation/account-deletion.schema.js.map +1 -0
  645. package/dist/validation/auth.schema.d.ts +7 -0
  646. package/dist/validation/auth.schema.js +3 -0
  647. package/dist/validation/auth.schema.js.map +1 -1
  648. package/dist/validation/member-invite.schema.d.ts +34 -9
  649. package/dist/validation/member-invite.schema.js +57 -23
  650. package/dist/validation/member-invite.schema.js.map +1 -1
  651. package/dist/validation/member-ownership.schema.d.ts +8 -0
  652. package/dist/validation/member-ownership.schema.js +8 -0
  653. package/dist/validation/member-ownership.schema.js.map +1 -0
  654. package/dist/validation/onboarding/register-admin.schema.d.ts +19 -4
  655. package/dist/validation/onboarding/register-admin.schema.js +27 -2
  656. package/dist/validation/onboarding/register-admin.schema.js.map +1 -1
  657. package/dist/validation/regional-preferences.schema.d.ts +22 -0
  658. package/dist/validation/regional-preferences.schema.js +70 -0
  659. package/dist/validation/regional-preferences.schema.js.map +1 -0
  660. package/dist/validation/role-editor.schema.d.ts +42 -0
  661. package/dist/validation/role-editor.schema.js +34 -0
  662. package/dist/validation/role-editor.schema.js.map +1 -0
  663. package/dist/validation/security.schema.d.ts +37 -0
  664. package/dist/validation/security.schema.js +61 -0
  665. package/dist/validation/security.schema.js.map +1 -0
  666. package/dist/validation/user-notification-preferences.schema.d.ts +1 -0
  667. package/dist/validation/user-notification-preferences.schema.js +2 -1
  668. package/dist/validation/user-notification-preferences.schema.js.map +1 -1
  669. package/frontend-vue/deferred-plugins.ts +2 -0
  670. package/frontend-vue/dms.frontend.build.ts +11 -0
  671. package/frontend-vue/dms.frontend.ts +32 -10
  672. package/frontend-vue/layers/dms-auth/app/build/components/AuthBackLink.vue +21 -0
  673. package/frontend-vue/layers/dms-auth/app/build/components/AuthFormAlert.vue +26 -0
  674. package/frontend-vue/layers/dms-auth/app/build/components/AuthNewPasswordField.vue +41 -0
  675. package/frontend-vue/layers/dms-auth/app/build/components/AuthResendCode.vue +51 -0
  676. package/frontend-vue/layers/dms-auth/app/build/composables/useAuthFormError.ts +102 -0
  677. package/frontend-vue/layers/dms-auth/app/build/utils/authStyles.ts +8 -0
  678. package/frontend-vue/layers/dms-auth/app/components/OAuthButtons.vue +6 -5
  679. package/frontend-vue/layers/dms-auth/app/composables/useLogout.ts +5 -0
  680. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/2fa.vue +124 -83
  681. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/accounts.vue +98 -94
  682. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/backup.vue +82 -48
  683. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/forgot-validation.vue +118 -80
  684. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/forgot.vue +69 -47
  685. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/login.vue +128 -103
  686. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/recover-success.vue +20 -13
  687. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/recover.vue +57 -75
  688. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/signup.vue +108 -103
  689. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/validate.vue +101 -80
  690. package/frontend-vue/layers/dms-auth/app/utils/accountsFlow.ts +1 -4
  691. package/frontend-vue/layers/dms-auth/i18n/locales/auth-en-GB.json +292 -21
  692. package/frontend-vue/layers/dms-auth/i18n/locales/auth-fr-FR.json +295 -24
  693. package/frontend-vue/layers/dms-core/app/build/composables/auth/usePermissionPreview.ts +297 -0
  694. package/frontend-vue/layers/dms-core/app/build/composables/page/usePageRecordLabel.ts +31 -0
  695. package/frontend-vue/layers/dms-core/app/build/utils/permission-preview.ts +266 -0
  696. package/frontend-vue/layers/dms-core/app/composables/data-types/useDataType.ts +27 -0
  697. package/frontend-vue/layers/dms-core/app/composables/period/compareResolvers.ts +35 -1
  698. package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +522 -0
  699. package/frontend-vue/layers/dms-core/app/composables/useFormValidation.ts +209 -0
  700. package/frontend-vue/layers/dms-core/app/composables/user/useRegionalFormat.ts +65 -0
  701. package/frontend-vue/layers/dms-core/app/composables/user/useUserRegionalPreferences.ts +57 -0
  702. package/frontend-vue/layers/dms-core/app/types/confirm-dialog.ts +68 -0
  703. package/frontend-vue/layers/dms-core/app/types/menu.ts +12 -0
  704. package/frontend-vue/layers/dms-core/app/types/row-action.ts +14 -0
  705. package/frontend-vue/layers/dms-core/app/utils/formatter.ts +76 -53
  706. package/frontend-vue/layers/dms-core/app/utils/regional.ts +269 -0
  707. package/frontend-vue/layers/dms-core/app/utils/url-interpolation.ts +23 -2
  708. package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +46 -7
  709. package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +46 -7
  710. package/frontend-vue/layers/dms-core/shared/types/runtime-config.d.ts +0 -8
  711. package/frontend-vue/layers/dms-layout/app/app.config.ts +81 -149
  712. package/frontend-vue/layers/dms-layout/app/assets/css/main.css +379 -74
  713. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +24 -3
  714. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardFrame.vue +97 -0
  715. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +136 -114
  716. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardPageBody.vue +72 -0
  717. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidebar.vue +118 -34
  718. package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +148 -26
  719. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeader.vue +10 -8
  720. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionBar.vue +237 -0
  721. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionsOutlet.vue +62 -0
  722. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageSkeleton.vue +35 -0
  723. package/frontend-vue/layers/dms-layout/app/build/components/layout/QuickActionsPopover.vue +35 -12
  724. package/frontend-vue/layers/dms-layout/app/build/components/layout/RolePreviewBar.vue +137 -0
  725. package/frontend-vue/layers/dms-layout/app/build/components/layout/SidebarUserMenu.vue +113 -0
  726. package/frontend-vue/layers/dms-layout/app/build/components/layout/StageCard.vue +88 -0
  727. package/frontend-vue/layers/dms-layout/app/build/components/layout/UserIdentity.vue +34 -0
  728. package/frontend-vue/layers/dms-layout/app/build/components/layout/sidebarState.ts +5 -1
  729. package/frontend-vue/layers/dms-layout/app/build/components/notification/NotificationPopover.vue +122 -68
  730. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleCatalogTile.vue +99 -0
  731. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreTile.vue +75 -0
  732. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTile.vue +102 -0
  733. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/members/MemberRolePicker.vue +184 -0
  734. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxDisplay.vue +138 -0
  735. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxItem.vue +118 -0
  736. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationMatrixCategory.vue +87 -0
  737. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationMatrixSubject.vue +88 -0
  738. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationPreferencesForm.vue +168 -273
  739. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/notificationDisplay.ts +86 -0
  740. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileAccountData.vue +40 -0
  741. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileAvatar.vue +47 -0
  742. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfilePersonalInfo.vue +344 -0
  743. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfilePreferencesSummary.vue +68 -0
  744. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileSecuritySummary.vue +75 -0
  745. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileSummaryRow.vue +101 -0
  746. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionFormatPreview.vue +90 -0
  747. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionTimeZoneInput.vue +62 -0
  748. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/timeZones.ts +96 -0
  749. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RoleEditor.vue +370 -0
  750. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RoleMemberAvatars.vue +30 -0
  751. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RoleOwnerPanel.vue +57 -0
  752. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePanelHead.vue +41 -0
  753. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionArea.vue +141 -0
  754. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionBranch.vue +82 -0
  755. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionGroup.vue +63 -0
  756. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionLeaf.vue +209 -0
  757. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionTree.vue +183 -0
  758. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolesList.vue +158 -0
  759. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolesListItem.vue +95 -0
  760. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +463 -0
  761. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-types.ts +89 -0
  762. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRoleEditor.ts +204 -0
  763. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRolesApi.ts +71 -0
  764. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityBackupCodesModal.vue +160 -0
  765. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityCodeModal.vue +110 -0
  766. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityDialogFrame.vue +75 -0
  767. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityEditPanel.vue +169 -0
  768. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityEmail.vue +402 -0
  769. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityPanelField.vue +56 -0
  770. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityPassword.vue +330 -0
  771. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityPasswordModal.vue +102 -0
  772. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecuritySessions.vue +369 -0
  773. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityStatus.vue +177 -0
  774. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityTotpSetupModal.vue +189 -0
  775. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityTwoFactor.vue +597 -0
  776. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shell/SettingsNav.vue +225 -0
  777. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shell/SettingsShell.vue +22 -0
  778. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shortcut/KeyboardShortcut.vue +3 -8
  779. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceAccessibility.vue +62 -0
  780. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceDeveloper.vue +50 -0
  781. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceOptionTile.vue +76 -0
  782. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceScale.vue +55 -0
  783. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceSidebar.vue +19 -0
  784. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/AppearanceTheme.vue +60 -0
  785. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/CssVariablesList.vue +276 -168
  786. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/theme/useAppearanceSave.ts +76 -0
  787. package/frontend-vue/layers/dms-layout/app/build/composables/dev-reload/useDevReloadHolder.ts +358 -0
  788. package/frontend-vue/layers/dms-layout/app/build/composables/general/useSidebarStartCollapsed.ts +14 -0
  789. package/frontend-vue/layers/dms-layout/app/build/composables/navigation/useCategoryNavCards.ts +73 -0
  790. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationCatalog.ts +85 -0
  791. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationPreferences.ts +90 -0
  792. package/frontend-vue/layers/dms-layout/app/build/composables/security/useSessionHandoff.ts +55 -0
  793. package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/preferencesSummary.ts +209 -0
  794. package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useAccountData.ts +329 -0
  795. package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useProfileAvatar.ts +95 -0
  796. package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useProfilePreferences.ts +198 -0
  797. package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useCodeFieldError.ts +63 -0
  798. package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useRevealedBackupCodes.ts +53 -0
  799. package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useSecurityFormat.ts +95 -0
  800. package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useSecurityOverview.ts +85 -0
  801. package/frontend-vue/layers/dms-layout/app/build/composables/settings/useSettingsNavigation.ts +101 -0
  802. package/frontend-vue/layers/dms-layout/app/build/utils/categoryPages.ts +44 -0
  803. package/frontend-vue/layers/dms-layout/app/build/utils/dev-reload-stream.ts +80 -0
  804. package/frontend-vue/layers/dms-layout/app/build/utils/module-store-catalog.ts +137 -0
  805. package/frontend-vue/layers/dms-layout/app/build/utils/modules-catalog.ts +197 -0
  806. package/frontend-vue/layers/dms-layout/app/components/AppWidgetsDock.vue +49 -16
  807. package/frontend-vue/layers/dms-layout/app/components/layout/DashboardSearch.vue +18 -1
  808. package/frontend-vue/layers/dms-layout/app/components/layout/HStack.vue +2 -1
  809. package/frontend-vue/layers/dms-layout/app/components/layout/Spacer.vue +25 -0
  810. package/frontend-vue/layers/dms-layout/app/components/layout/VStack.vue +2 -1
  811. package/frontend-vue/layers/dms-layout/app/components/navigation/CollapsedMenuItem.vue +65 -4
  812. package/frontend-vue/layers/dms-layout/app/components/navigation/NavigationMenu.vue +109 -4
  813. package/frontend-vue/layers/dms-layout/app/composables/general/useAccessibilityPreferences.ts +52 -0
  814. package/frontend-vue/layers/dms-layout/app/composables/layout/useInstantSaveHeader.ts +34 -0
  815. package/frontend-vue/layers/dms-layout/app/composables/layout/usePageHeaderActions.ts +158 -0
  816. package/frontend-vue/layers/dms-layout/app/composables/notification/useNotifications.ts +169 -110
  817. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleHistory.ts +60 -12
  818. package/frontend-vue/layers/dms-layout/app/composables/page/useModulesListing.ts +62 -26
  819. package/frontend-vue/layers/dms-layout/app/composables/page/usePageComponentPreload.ts +16 -14
  820. package/frontend-vue/layers/dms-layout/app/composables/page/useQuickActions.ts +1 -61
  821. package/frontend-vue/layers/dms-layout/app/composables/profile/useUserLanguage.ts +4 -3
  822. package/frontend-vue/layers/dms-layout/app/composables/useDevReload.ts +4 -359
  823. package/frontend-vue/layers/dms-layout/app/composables/useFooterLinks.ts +20 -1
  824. package/frontend-vue/layers/dms-layout/app/custom-layouts/DefaultLayout.vue +17 -43
  825. package/frontend-vue/layers/dms-layout/app/custom-layouts/EmptyLayout.vue +42 -4
  826. package/frontend-vue/layers/dms-layout/app/custom-layouts/SettingsLayout.vue +42 -0
  827. package/frontend-vue/layers/dms-layout/app/custom-pages/modules.vue +564 -70
  828. package/frontend-vue/layers/dms-layout/app/custom-pages/settings/roles.vue +298 -0
  829. package/frontend-vue/layers/dms-layout/app/custom-pages/settings/shortcuts.vue +162 -109
  830. package/frontend-vue/layers/dms-layout/app/emails/EmailChangeNotice.vue +28 -0
  831. package/frontend-vue/layers/dms-layout/app/emails/EmailChangeVerification.vue +32 -0
  832. package/frontend-vue/layers/dms-layout/app/error.vue +75 -84
  833. package/frontend-vue/layers/dms-layout/app/middleware/page-leave-guard.global.ts +8 -0
  834. package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +8 -0
  835. package/frontend-vue/layers/dms-layout/app/plugins/accessibility.ts +22 -0
  836. package/frontend-vue/layers/dms-layout/app/plugins/dms-dev-reload.client.ts +13 -16
  837. package/frontend-vue/layers/dms-layout/app/plugins/font-preload.ts +23 -0
  838. package/frontend-vue/layers/dms-layout/app/plugins/notification-stream.client.ts +15 -2
  839. package/frontend-vue/layers/dms-layout/app/plugins/permission-preview-prepaint.ts +40 -0
  840. package/frontend-vue/layers/dms-layout/app/plugins/permission-preview.client.ts +35 -0
  841. package/frontend-vue/layers/dms-layout/app/plugins/profile-sync.client.ts +10 -4
  842. package/frontend-vue/layers/dms-layout/app/plugins/regional-preferences.ts +19 -0
  843. package/frontend-vue/layers/dms-layout/app/theme/actions.ts +385 -0
  844. package/frontend-vue/layers/dms-layout/app/theme/data.ts +174 -0
  845. package/frontend-vue/layers/dms-layout/app/theme/form-controls.ts +657 -0
  846. package/frontend-vue/layers/dms-layout/app/theme/navigation.ts +295 -0
  847. package/frontend-vue/layers/dms-layout/app/theme/surfaces.ts +319 -0
  848. package/frontend-vue/layers/dms-layout/app/types/page.ts +22 -0
  849. package/frontend-vue/layers/dms-layout/app/utils/account-menu.ts +1 -1
  850. package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +639 -63
  851. package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +638 -62
  852. package/frontend-vue/layers/dms-layout/public/images/antelope-logo/dark.svg +12 -12
  853. package/frontend-vue/layers/dms-layout/public/images/antelope-logo/light.svg +12 -12
  854. package/frontend-vue/layers/dms-onboarding/app/build/components/onboarding/StepIndicator.vue +44 -0
  855. package/frontend-vue/layers/dms-onboarding/app/build/components/onboarding/StepMeta.vue +41 -0
  856. package/frontend-vue/layers/dms-onboarding/app/build/components/onboarding/steps/platform.vue +153 -0
  857. package/frontend-vue/layers/dms-onboarding/app/build/components/onboarding/steps/ready.vue +191 -0
  858. package/frontend-vue/layers/dms-onboarding/app/build/composables/onboarding/steps.ts +16 -0
  859. package/frontend-vue/layers/dms-onboarding/app/components/onboarding/steps/register.vue +152 -115
  860. package/frontend-vue/layers/dms-onboarding/app/custom-pages/onboarding.vue +60 -1
  861. package/frontend-vue/layers/dms-onboarding/i18n/locales/onboarding-en-GB.json +46 -15
  862. package/frontend-vue/layers/dms-onboarding/i18n/locales/onboarding-fr-FR.json +46 -15
  863. package/frontend-vue/layers/dms-ui/app/build/components/activity-feed/activityFeedDays.ts +173 -0
  864. package/frontend-vue/layers/dms-ui/app/build/components/blocks/BlockActions.vue +72 -0
  865. package/frontend-vue/layers/dms-ui/app/build/components/blocks/BlockStatus.vue +69 -0
  866. package/frontend-vue/layers/dms-ui/app/build/components/chart/internal/ChartSkeleton.vue +56 -0
  867. package/frontend-vue/layers/dms-ui/app/build/components/containers/constants.ts +2 -0
  868. package/frontend-vue/layers/dms-ui/app/build/components/containers/drawer/DynamicDrawer.vue +70 -12
  869. package/frontend-vue/layers/dms-ui/app/build/components/containers/modal/DynamicModal.vue +91 -16
  870. package/frontend-vue/layers/dms-ui/app/build/components/form/ChipGroup.vue +113 -0
  871. package/frontend-vue/layers/dms-ui/app/build/components/form/FormEntries.vue +101 -0
  872. package/frontend-vue/layers/dms-ui/app/build/components/form/FormErrorSummary.vue +51 -0
  873. package/frontend-vue/layers/dms-ui/app/build/components/form/FormErrorText.vue +15 -0
  874. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldControl.vue +109 -0
  875. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldNotes.vue +96 -0
  876. package/frontend-vue/layers/dms-ui/app/build/components/form/FormRequiredLegend.vue +6 -0
  877. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSectionNav.vue +94 -0
  878. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSections.vue +131 -0
  879. package/frontend-vue/layers/dms-ui/app/build/components/form/OtpInput.vue +108 -0
  880. package/frontend-vue/layers/dms-ui/app/build/components/form/PasswordInput.vue +95 -0
  881. package/frontend-vue/layers/dms-ui/app/build/components/form/SearchInput.vue +102 -0
  882. package/frontend-vue/layers/dms-ui/app/build/components/form/UnsavedStatus.vue +30 -0
  883. package/frontend-vue/layers/dms-ui/app/build/components/period/PeriodRangeCalendar.vue +294 -0
  884. package/frontend-vue/layers/dms-ui/app/build/components/permission/PermissionVeil.vue +118 -0
  885. package/frontend-vue/layers/dms-ui/app/build/components/section/context.ts +10 -0
  886. package/frontend-vue/layers/dms-ui/app/build/components/skeleton/RowSkeleton.vue +38 -0
  887. package/frontend-vue/layers/dms-ui/app/build/components/stat/StatCell.vue +183 -0
  888. package/frontend-vue/layers/dms-ui/app/build/components/table/Actions.vue +397 -37
  889. package/frontend-vue/layers/dms-ui/app/build/components/table/Empty.vue +154 -61
  890. package/frontend-vue/layers/dms-ui/app/build/components/table/FiltersRow.vue +147 -68
  891. package/frontend-vue/layers/dms-ui/app/build/components/table/Menu.vue +13 -1
  892. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuDensity.vue +80 -0
  893. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuFilter.vue +11 -3
  894. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuRoot.vue +11 -0
  895. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuSort.vue +98 -4
  896. package/frontend-vue/layers/dms-ui/app/build/components/table/MenuViewMode.vue +37 -16
  897. package/frontend-vue/layers/dms-ui/app/build/components/table/MonoCell.vue +47 -0
  898. package/frontend-vue/layers/dms-ui/app/build/components/table/Pagination.vue +251 -36
  899. package/frontend-vue/layers/dms-ui/app/build/components/table/RowSelection.vue +210 -32
  900. package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +999 -176
  901. package/frontend-vue/layers/dms-ui/app/build/components/table/Tabs.vue +157 -22
  902. package/frontend-vue/layers/dms-ui/app/build/components/table/Views.vue +286 -0
  903. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardGridSkeleton.vue +61 -0
  904. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +186 -0
  905. package/frontend-vue/layers/dms-ui/app/build/components/table-view/ExpandedRowDetail.vue +147 -0
  906. package/frontend-vue/layers/dms-ui/app/build/components/table-view/IdentityCell.vue +126 -0
  907. package/frontend-vue/layers/dms-ui/app/build/composables/actions/bulkSelection.ts +67 -0
  908. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +85 -0
  909. package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +452 -0
  910. package/frontend-vue/layers/dms-ui/app/build/composables/blocks/useBlockItems.ts +67 -0
  911. package/frontend-vue/layers/dms-ui/app/build/composables/chart/apexTheme.ts +168 -0
  912. package/frontend-vue/layers/dms-ui/app/build/composables/chart/sparklinePath.ts +81 -0
  913. package/frontend-vue/layers/dms-ui/app/build/composables/clipboard/useCopyFeedback.ts +49 -0
  914. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/actionError.ts +142 -0
  915. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/confirmDialogTexts.ts +66 -0
  916. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/useActionConfirm.ts +102 -0
  917. package/frontend-vue/layers/dms-ui/app/build/composables/containers/context.ts +16 -0
  918. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/cellHelpers.ts +39 -0
  919. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +265 -0
  920. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +339 -93
  921. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerFieldTypes.ts +64 -0
  922. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationValue.ts +66 -0
  923. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +122 -0
  924. package/frontend-vue/layers/dms-ui/app/build/composables/form/formEntryContext.ts +55 -0
  925. package/frontend-vue/layers/dms-ui/app/build/composables/form/formFooter.ts +110 -0
  926. package/frontend-vue/layers/dms-ui/app/build/composables/form/formLayout.ts +91 -0
  927. package/frontend-vue/layers/dms-ui/app/build/composables/form/formSections.ts +110 -0
  928. package/frontend-vue/layers/dms-ui/app/build/composables/form/formValidation.ts +180 -0
  929. package/frontend-vue/layers/dms-ui/app/build/composables/form/keyValueRows.ts +64 -0
  930. package/frontend-vue/layers/dms-ui/app/build/composables/form/tagValues.ts +43 -0
  931. package/frontend-vue/layers/dms-ui/app/build/composables/form/useControlError.ts +34 -0
  932. package/frontend-vue/layers/dms-ui/app/build/composables/form/useInstantForm.ts +125 -0
  933. package/frontend-vue/layers/dms-ui/app/build/composables/global/searchShortcuts.ts +61 -0
  934. package/frontend-vue/layers/dms-ui/app/build/composables/global/shortcuts.ts +31 -0
  935. package/frontend-vue/layers/dms-ui/app/build/composables/instant-save/useInstantSave.ts +260 -0
  936. package/frontend-vue/layers/dms-ui/app/build/composables/navigation/useNavBadges.ts +24 -0
  937. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodDisplay.ts +154 -0
  938. package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodDraft.ts +127 -0
  939. package/frontend-vue/layers/dms-ui/app/build/composables/shortcuts/useShortcutRegistry.ts +18 -0
  940. package/frontend-vue/layers/dms-ui/app/build/composables/table/constants.ts +7 -1
  941. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +27 -10
  942. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableColumns.ts +437 -72
  943. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableConfigClipboard.ts +8 -1
  944. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableStates.ts +0 -7
  945. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/clearTableFilters.ts +80 -0
  946. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/columnOrder.ts +34 -0
  947. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/pageSizeOptions.ts +18 -0
  948. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/displayRegistry.ts +30 -0
  949. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useAccumulatedPages.ts +46 -0
  950. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useExpandedRowDetails.ts +56 -0
  951. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useGroupedRows.ts +125 -0
  952. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useServerRenderedAsyncData.ts +23 -0
  953. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableFooter.ts +119 -0
  954. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableReorder.ts +77 -0
  955. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +175 -0
  956. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewConfig.ts +11 -5
  957. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +322 -344
  958. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViews.ts +266 -0
  959. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/bulkActions.ts +152 -0
  960. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/card.ts +75 -0
  961. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/chrome.ts +70 -0
  962. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/expandedRowProps.ts +24 -0
  963. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/expandedRows.ts +51 -0
  964. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/formTexts.ts +127 -0
  965. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/groupedRows.ts +180 -0
  966. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/quickFilters.ts +178 -0
  967. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +32 -0
  968. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/reorder.ts +68 -0
  969. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/sortableColumns.ts +189 -0
  970. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableQuery.ts +1 -1
  971. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +202 -0
  972. package/frontend-vue/layers/dms-ui/app/build/composables/unsaved-changes/formValue.ts +97 -0
  973. package/frontend-vue/layers/dms-ui/app/build/composables/unsaved-changes/registry.ts +216 -0
  974. package/frontend-vue/layers/dms-ui/app/build/types/tree.ts +1 -0
  975. package/frontend-vue/layers/dms-ui/app/build/utils/accessibilityPreferences.ts +138 -0
  976. package/frontend-vue/layers/dms-ui/app/build/utils/codeCells.ts +12 -0
  977. package/frontend-vue/layers/dms-ui/app/build/utils/codeEditor.ts +304 -0
  978. package/frontend-vue/layers/dms-ui/app/build/utils/dispatchQuickActionTarget.ts +74 -0
  979. package/frontend-vue/layers/dms-ui/app/build/utils/eyebrow.ts +7 -0
  980. package/frontend-vue/layers/dms-ui/app/build/utils/fieldOptionsI18n.ts +60 -0
  981. package/frontend-vue/layers/dms-ui/app/build/utils/fieldTrigger.ts +46 -0
  982. package/frontend-vue/layers/dms-ui/app/build/utils/link.ts +33 -0
  983. package/frontend-vue/layers/dms-ui/app/build/utils/literalText.ts +21 -0
  984. package/frontend-vue/layers/dms-ui/app/build/utils/monoChip.ts +13 -0
  985. package/frontend-vue/layers/dms-ui/app/build/utils/permissionPreview.ts +6 -0
  986. package/frontend-vue/layers/dms-ui/app/build/utils/quickActionTargets.ts +54 -0
  987. package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +67 -0
  988. package/frontend-vue/layers/dms-ui/app/build/utils/selectionScope.ts +20 -0
  989. package/frontend-vue/layers/dms-ui/app/build/utils/textLink.ts +7 -0
  990. package/frontend-vue/layers/dms-ui/app/build/utils/tileRow.ts +10 -0
  991. package/frontend-vue/layers/dms-ui/app/build/utils/tone.ts +74 -0
  992. package/frontend-vue/layers/dms-ui/app/components/RecursiveComponent.vue +106 -37
  993. package/frontend-vue/layers/dms-ui/app/components/activity/ActivityItem.vue +80 -54
  994. package/frontend-vue/layers/dms-ui/app/components/activity-feed/ActivityFeed.vue +250 -0
  995. package/frontend-vue/layers/dms-ui/app/components/banner/Banner.vue +100 -57
  996. package/frontend-vue/layers/dms-ui/app/components/blocks/BannerBlock.vue +117 -0
  997. package/frontend-vue/layers/dms-ui/app/components/blocks/CardBlock.vue +99 -0
  998. package/frontend-vue/layers/dms-ui/app/components/blocks/EmptyStateBlock.vue +69 -0
  999. package/frontend-vue/layers/dms-ui/app/components/blocks/KeyValueListBlock.vue +113 -0
  1000. package/frontend-vue/layers/dms-ui/app/components/blocks/NavCardGridBlock.vue +199 -0
  1001. package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +92 -0
  1002. package/frontend-vue/layers/dms-ui/app/components/card/Card.vue +82 -3
  1003. package/frontend-vue/layers/dms-ui/app/components/card/NavCard.vue +94 -28
  1004. package/frontend-vue/layers/dms-ui/app/components/chart/ApexChartHost.vue +149 -10
  1005. package/frontend-vue/layers/dms-ui/app/components/chart/Chart.vue +76 -24
  1006. package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +62 -25
  1007. package/frontend-vue/layers/dms-ui/app/components/chart/internal/Sparkline.vue +98 -81
  1008. package/frontend-vue/layers/dms-ui/app/components/chart/internal/TrendBadge.vue +67 -26
  1009. package/frontend-vue/layers/dms-ui/app/components/check-list/CheckList.vue +228 -0
  1010. package/frontend-vue/layers/dms-ui/app/components/check-list/PasswordRules.vue +140 -0
  1011. package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +446 -13
  1012. package/frontend-vue/layers/dms-ui/app/components/copy/CopyButton.vue +5 -5
  1013. package/frontend-vue/layers/dms-ui/app/components/empty-state/EmptyState.vue +139 -0
  1014. package/frontend-vue/layers/dms-ui/app/components/field-error/FieldError.vue +31 -0
  1015. package/frontend-vue/layers/dms-ui/app/components/field-row/FieldRow.vue +156 -0
  1016. package/frontend-vue/layers/dms-ui/app/components/flow-canvas/FlowCanvas.vue +8 -0
  1017. package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +652 -274
  1018. package/frontend-vue/layers/dms-ui/app/components/form/LocalizedField.vue +114 -37
  1019. package/frontend-vue/layers/dms-ui/app/components/form/components/BooleanCard.vue +55 -0
  1020. package/frontend-vue/layers/dms-ui/app/components/form/components/Calendar.vue +59 -7
  1021. package/frontend-vue/layers/dms-ui/app/components/form/components/Cascader.vue +32 -4
  1022. package/frontend-vue/layers/dms-ui/app/components/form/components/Checkbox.vue +9 -1
  1023. package/frontend-vue/layers/dms-ui/app/components/form/components/ChoiceCards.vue +64 -0
  1024. package/frontend-vue/layers/dms-ui/app/components/form/components/CopyableText.vue +26 -0
  1025. package/frontend-vue/layers/dms-ui/app/components/form/components/DatePicker.vue +140 -12
  1026. package/frontend-vue/layers/dms-ui/app/components/form/components/DatePickerRange.vue +17 -0
  1027. package/frontend-vue/layers/dms-ui/app/components/form/components/File.vue +35 -21
  1028. package/frontend-vue/layers/dms-ui/app/components/form/components/Image.vue +86 -38
  1029. package/frontend-vue/layers/dms-ui/app/components/form/components/InputAddress.vue +113 -1
  1030. package/frontend-vue/layers/dms-ui/app/components/form/components/InputCode.vue +196 -0
  1031. package/frontend-vue/layers/dms-ui/app/components/form/components/InputColor.vue +37 -7
  1032. package/frontend-vue/layers/dms-ui/app/components/form/components/InputNumber.vue +27 -5
  1033. package/frontend-vue/layers/dms-ui/app/components/form/components/InputPassword.vue +21 -39
  1034. package/frontend-vue/layers/dms-ui/app/components/form/components/InputPercentage.vue +16 -8
  1035. package/frontend-vue/layers/dms-ui/app/components/form/components/InputSecret.vue +107 -0
  1036. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTags.vue +132 -0
  1037. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTime.vue +16 -4
  1038. package/frontend-vue/layers/dms-ui/app/components/form/components/KeyValue.vue +85 -0
  1039. package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +21 -2
  1040. package/frontend-vue/layers/dms-ui/app/components/form/components/Repeater.vue +258 -0
  1041. package/frontend-vue/layers/dms-ui/app/components/form/components/RichText.vue +66 -15
  1042. package/frontend-vue/layers/dms-ui/app/components/form/components/SegmentedSelect.vue +49 -0
  1043. package/frontend-vue/layers/dms-ui/app/components/form/components/Select.vue +2 -0
  1044. package/frontend-vue/layers/dms-ui/app/components/grid/Grid.vue +47 -10
  1045. package/frontend-vue/layers/dms-ui/app/components/grid/GridRow.vue +42 -15
  1046. package/frontend-vue/layers/dms-ui/app/components/grid/columns.ts +84 -0
  1047. package/frontend-vue/layers/dms-ui/app/components/grid/constants.ts +16 -0
  1048. package/frontend-vue/layers/dms-ui/app/components/icon-well/IconWell.vue +84 -0
  1049. package/frontend-vue/layers/dms-ui/app/components/key-value-list/KeyValueList.vue +223 -0
  1050. package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +184 -64
  1051. package/frontend-vue/layers/dms-ui/app/components/link/AutoLink.vue +33 -0
  1052. package/frontend-vue/layers/dms-ui/app/components/list-row/ListRow.vue +301 -0
  1053. package/frontend-vue/layers/dms-ui/app/components/master-detail/MasterDetail.vue +3 -1
  1054. package/frontend-vue/layers/dms-ui/app/components/meter/Meter.vue +241 -0
  1055. package/frontend-vue/layers/dms-ui/app/components/meter/MeterBlock.vue +182 -0
  1056. package/frontend-vue/layers/dms-ui/app/components/period/PeriodSelector.vue +520 -166
  1057. package/frontend-vue/layers/dms-ui/app/components/record-card/RecordCard.vue +170 -0
  1058. package/frontend-vue/layers/dms-ui/app/components/save-bar/InstantSaveBadge.vue +54 -0
  1059. package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +167 -0
  1060. package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveStatus.vue +69 -0
  1061. package/frontend-vue/layers/dms-ui/app/components/section/Section.vue +96 -0
  1062. package/frontend-vue/layers/dms-ui/app/components/section-header/Eyebrow.vue +68 -0
  1063. package/frontend-vue/layers/dms-ui/app/components/section-header/SectionHeader.vue +121 -0
  1064. package/frontend-vue/layers/dms-ui/app/components/segmented/Segmented.vue +142 -33
  1065. package/frontend-vue/layers/dms-ui/app/components/stat-group/StatGroup.vue +186 -0
  1066. package/frontend-vue/layers/dms-ui/app/components/status/StatusSummary.vue +145 -43
  1067. package/frontend-vue/layers/dms-ui/app/components/status-pill/StatusPill.vue +167 -0
  1068. package/frontend-vue/layers/dms-ui/app/components/tab/Tab.vue +80 -6
  1069. package/frontend-vue/layers/dms-ui/app/components/table-view/FilePreview.vue +1 -1
  1070. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanBoard.vue +165 -34
  1071. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanDisplay.vue +9 -12
  1072. package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +990 -110
  1073. package/frontend-vue/layers/dms-ui/app/components/top-list/TopListCard.vue +158 -70
  1074. package/frontend-vue/layers/dms-ui/app/components/top-list/internal/TopListRow.vue +53 -19
  1075. package/frontend-vue/layers/dms-ui/app/composables/chart/apexPlotOptions.ts +37 -6
  1076. package/frontend-vue/layers/dms-ui/app/composables/chart/apexTypeConfigs.ts +4 -3
  1077. package/frontend-vue/layers/dms-ui/app/composables/chart/resolveSparklineAccent.ts +6 -3
  1078. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.ts +157 -113
  1079. package/frontend-vue/layers/dms-ui/app/composables/chart/useChartFetch.ts +56 -17
  1080. package/frontend-vue/layers/dms-ui/app/composables/chart/useChartTheme.ts +58 -9
  1081. package/frontend-vue/layers/dms-ui/app/composables/confirm/index.ts +1 -0
  1082. package/frontend-vue/layers/dms-ui/app/composables/confirm/types.ts +102 -0
  1083. package/frontend-vue/layers/dms-ui/app/composables/confirm/useConfirm.ts +6 -8
  1084. package/frontend-vue/layers/dms-ui/app/composables/containers/openDynamicContainer.ts +1 -0
  1085. package/frontend-vue/layers/dms-ui/app/composables/containers/types.ts +30 -1
  1086. package/frontend-vue/layers/dms-ui/app/composables/form/types/api.ts +1 -1
  1087. package/frontend-vue/layers/dms-ui/app/composables/form/types/field.ts +34 -0
  1088. package/frontend-vue/layers/dms-ui/app/composables/form/types/props.ts +34 -3
  1089. package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +392 -94
  1090. package/frontend-vue/layers/dms-ui/app/composables/global/keyboardPlatform.ts +125 -0
  1091. package/frontend-vue/layers/dms-ui/app/composables/resolveDmsComponent.ts +14 -17
  1092. package/frontend-vue/layers/dms-ui/app/composables/tab/types/props.ts +8 -0
  1093. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +6 -10
  1094. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/column.ts +14 -0
  1095. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +216 -4
  1096. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/custom-button.ts +8 -0
  1097. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +94 -3
  1098. package/frontend-vue/layers/dms-ui/app/composables/table-view/useTableDataChanges.ts +41 -0
  1099. package/frontend-vue/layers/dms-ui/app/composables/table-view/useTableViewDisplays.ts +42 -27
  1100. package/frontend-vue/layers/dms-ui/app/composables/unsaved-changes/index.ts +2 -0
  1101. package/frontend-vue/layers/dms-ui/app/composables/unsaved-changes/useFormDirty.ts +54 -0
  1102. package/frontend-vue/layers/dms-ui/app/composables/unsaved-changes/useUnsavedChanges.ts +120 -0
  1103. package/frontend-vue/layers/dms-ui/app/composables/usePasswordStrength.ts +12 -6
  1104. package/frontend-vue/layers/dms-ui/app/config/shortcuts-registry.ts +5 -5
  1105. package/frontend-vue/layers/dms-ui/app/plugins/shortcuts.ts +2 -0
  1106. package/frontend-vue/layers/dms-ui/app/plugins/table-view-displays.ts +55 -0
  1107. package/frontend-vue/layers/dms-ui/app/types/modal.ts +3 -1
  1108. package/frontend-vue/layers/dms-ui/app/types/row-action.ts +27 -0
  1109. package/frontend-vue/layers/dms-ui/app/types/tone.ts +13 -0
  1110. package/frontend-vue/layers/dms-ui/app/utils/semanticTint.ts +1 -1
  1111. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +330 -86
  1112. package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +326 -82
  1113. package/frontend-vue/package.json +14 -3
  1114. package/frontend-vue/pnpm-lock.yaml +284 -492
  1115. package/frontend-vue/tests/accessibility-preferences.test.ts +320 -0
  1116. package/frontend-vue/tests/activity-feed-days.test.ts +125 -0
  1117. package/frontend-vue/tests/category-nav-cards.test.ts +97 -0
  1118. package/frontend-vue/tests/chart-colors.test.ts +1 -1
  1119. package/frontend-vue/tests/chart-series-styles.test.ts +9 -9
  1120. package/frontend-vue/tests/chip-group.test.ts +68 -0
  1121. package/frontend-vue/tests/confirm-action-errors.test.ts +324 -0
  1122. package/frontend-vue/tests/confirm-dialog-fields.test.ts +271 -0
  1123. package/frontend-vue/tests/confirm-typed-text.test.ts +201 -0
  1124. package/frontend-vue/tests/copy-feedback.test.ts +48 -0
  1125. package/frontend-vue/tests/custom-action-confirm-from.test.ts +85 -0
  1126. package/frontend-vue/tests/dev-reload-stream.test.ts +139 -0
  1127. package/frontend-vue/tests/dev-reload.test.ts +2 -2
  1128. package/frontend-vue/tests/error-page-message.test.ts +15 -0
  1129. package/frontend-vue/tests/field-errors.test.ts +212 -0
  1130. package/frontend-vue/tests/field-options-i18n.test.ts +41 -0
  1131. package/frontend-vue/tests/field-row.test.ts +101 -0
  1132. package/frontend-vue/tests/file-unavailable.test.ts +7 -1
  1133. package/frontend-vue/tests/form-action-reset.test.ts +106 -0
  1134. package/frontend-vue/tests/form-actions.test.ts +6 -7
  1135. package/frontend-vue/tests/form-control-error-state.test.ts +164 -0
  1136. package/frontend-vue/tests/form-footer-kind.test.ts +96 -0
  1137. package/frontend-vue/tests/form-reload-on-reopen.test.ts +20 -0
  1138. package/frontend-vue/tests/form-required-fields.test.ts +16 -0
  1139. package/frontend-vue/tests/form-required-validation.test.ts +407 -0
  1140. package/frontend-vue/tests/form-sections.test.ts +94 -0
  1141. package/frontend-vue/tests/form-server-field-errors.test.ts +187 -0
  1142. package/frontend-vue/tests/form-submit-clear.test.ts +406 -0
  1143. package/frontend-vue/tests/form-submit-only-changed.test.ts +195 -0
  1144. package/frontend-vue/tests/form-validation.test.ts +213 -0
  1145. package/frontend-vue/tests/grid-responsive-columns.test.ts +68 -1
  1146. package/frontend-vue/tests/header-action-press-in-place.test.ts +231 -0
  1147. package/frontend-vue/tests/image-hydration-ids.test.ts +10 -1
  1148. package/frontend-vue/tests/image-reference-preservation.test.ts +18 -2
  1149. package/frontend-vue/tests/input-tags.test.ts +146 -0
  1150. package/frontend-vue/tests/instant-save-badge.test.ts +195 -0
  1151. package/frontend-vue/tests/instant-save.test.ts +217 -0
  1152. package/frontend-vue/tests/key-value-rows.test.ts +52 -0
  1153. package/frontend-vue/tests/keyboard-platform.test.ts +87 -0
  1154. package/frontend-vue/tests/kpi-no-comparison.test.ts +92 -0
  1155. package/frontend-vue/tests/member-role-picker.test.ts +227 -0
  1156. package/frontend-vue/tests/metadata-retry.test.ts +12 -1
  1157. package/frontend-vue/tests/meter-block-load-error.test.ts +70 -0
  1158. package/frontend-vue/tests/module-store-catalog.test.ts +152 -0
  1159. package/frontend-vue/tests/modules-catalog.test.ts +152 -0
  1160. package/frontend-vue/tests/notification-inbox-display.test.ts +169 -0
  1161. package/frontend-vue/tests/notification-popover-errors.test.ts +136 -17
  1162. package/frontend-vue/tests/onboarding-register.test.ts +71 -44
  1163. package/frontend-vue/tests/otp-input.test.ts +97 -0
  1164. package/frontend-vue/tests/page-fill-height.test.ts +82 -16
  1165. package/frontend-vue/tests/password-input.test.ts +122 -0
  1166. package/frontend-vue/tests/period-draft.test.ts +120 -0
  1167. package/frontend-vue/tests/period-presets.test.ts +12 -0
  1168. package/frontend-vue/tests/period-scope-first-fetch.test.ts +93 -8
  1169. package/frontend-vue/tests/permission-preview-partial.test.ts +301 -0
  1170. package/frontend-vue/tests/permission-preview-session.test.ts +69 -0
  1171. package/frontend-vue/tests/permission-preview.test.ts +196 -0
  1172. package/frontend-vue/tests/permission-veil-stable-content.test.ts +191 -0
  1173. package/frontend-vue/tests/profile-preferences-summary.test.ts +510 -0
  1174. package/frontend-vue/tests/quick-actions.test.ts +2 -2
  1175. package/frontend-vue/tests/record-card.test.ts +73 -0
  1176. package/frontend-vue/tests/regional-format.test.ts +67 -0
  1177. package/frontend-vue/tests/regional-preferences.test.ts +209 -0
  1178. package/frontend-vue/tests/relation-value.test.ts +39 -0
  1179. package/frontend-vue/tests/resolve-dms-component.test.ts +47 -0
  1180. package/frontend-vue/tests/response-warning-toast.test.ts +1 -1
  1181. package/frontend-vue/tests/revealed-backup-codes.test.ts +58 -0
  1182. package/frontend-vue/tests/role-permission-tree.test.ts +470 -0
  1183. package/frontend-vue/tests/role-permissions.test.ts +539 -0
  1184. package/frontend-vue/tests/roles-name-errors.test.ts +295 -0
  1185. package/frontend-vue/tests/save-bar.test.ts +106 -0
  1186. package/frontend-vue/tests/save-status-error.test.ts +66 -0
  1187. package/frontend-vue/tests/search-input.test.ts +91 -0
  1188. package/frontend-vue/tests/section-description-only.test.ts +33 -0
  1189. package/frontend-vue/tests/security-email-panel.test.ts +378 -0
  1190. package/frontend-vue/tests/security-password-modal.test.ts +128 -0
  1191. package/frontend-vue/tests/security-password-panel.test.ts +267 -0
  1192. package/frontend-vue/tests/security-sessions-load-error.test.ts +123 -0
  1193. package/frontend-vue/tests/security-status-load-error.test.ts +106 -0
  1194. package/frontend-vue/tests/selection-scope.test.ts +24 -0
  1195. package/frontend-vue/tests/session-handoff.test.ts +60 -0
  1196. package/frontend-vue/tests/settings-navigation.test.ts +170 -0
  1197. package/frontend-vue/tests/settings-search-shortcuts.test.ts +191 -0
  1198. package/frontend-vue/tests/shortcuts-aggregate.test.ts +12 -5
  1199. package/frontend-vue/tests/sidebar-footer-navigation.test.ts +10 -0
  1200. package/frontend-vue/tests/sidebar-search-hint.test.ts +191 -0
  1201. package/frontend-vue/tests/signup-invitation-link.test.ts +6 -2
  1202. package/frontend-vue/tests/stat-cell-shared.test.ts +64 -0
  1203. package/frontend-vue/tests/tab-slot-spacing.test.ts +21 -0
  1204. package/frontend-vue/tests/table-actions-column-width.test.ts +85 -0
  1205. package/frontend-vue/tests/table-cell-wrap.test.ts +8 -3
  1206. package/frontend-vue/tests/table-clear-filters.test.ts +254 -0
  1207. package/frontend-vue/tests/table-density-menu.test.ts +128 -0
  1208. package/frontend-vue/tests/table-header-placement.test.ts +21 -0
  1209. package/frontend-vue/tests/table-metric-cells.test.ts +139 -0
  1210. package/frontend-vue/tests/table-page-size-options.test.ts +20 -0
  1211. package/frontend-vue/tests/table-row-action-errors.test.ts +360 -0
  1212. package/frontend-vue/tests/table-row-hover.test.ts +6 -1
  1213. package/frontend-vue/tests/table-scroll-area.test.ts +43 -0
  1214. package/frontend-vue/tests/table-view-bulk-actions.test.ts +154 -0
  1215. package/frontend-vue/tests/table-view-bulk-drawer.test.ts +311 -0
  1216. package/frontend-vue/tests/table-view-card-props.test.ts +226 -0
  1217. package/frontend-vue/tests/table-view-chrome.test.ts +175 -0
  1218. package/frontend-vue/tests/table-view-display-registry.test.ts +59 -0
  1219. package/frontend-vue/tests/table-view-expanded-band.test.ts +143 -0
  1220. package/frontend-vue/tests/table-view-expanded-row-details.test.ts +88 -0
  1221. package/frontend-vue/tests/table-view-expanded-rows.test.ts +55 -0
  1222. package/frontend-vue/tests/table-view-form-texts.test.ts +124 -0
  1223. package/frontend-vue/tests/table-view-grouped.test.ts +277 -0
  1224. package/frontend-vue/tests/table-view-pagination-modes.test.ts +48 -0
  1225. package/frontend-vue/tests/table-view-reorder.test.ts +122 -0
  1226. package/frontend-vue/tests/table-view-selection-footer-empty.test.ts +379 -0
  1227. package/frontend-vue/tests/table-view-sortable-columns.test.ts +293 -0
  1228. package/frontend-vue/tests/table-view-sources.test.ts +115 -0
  1229. package/frontend-vue/tests/table-view-views.test.ts +540 -0
  1230. package/frontend-vue/tests/tag-values.test.ts +32 -0
  1231. package/frontend-vue/tests/time-span.test.ts +37 -0
  1232. package/frontend-vue/tests/tone.test.ts +45 -0
  1233. package/frontend-vue/tests/unsaved-changes.test.ts +184 -0
  1234. package/frontend-vue/tests/url-interpolation.test.ts +40 -0
  1235. package/frontend-vue/tests/vue-inventory.test.ts +24 -9
  1236. package/frontend-vue/vitest.config.ts +6 -0
  1237. package/package.json +8 -5
  1238. package/skills/dms/REFERENCE.md +1 -1
  1239. package/skills/dms/SKILL.md +1 -1
  1240. package/skills/dms-auth/SKILL.md +2 -1
  1241. package/skills/dms-module/SKILL.md +1 -1
  1242. package/skills/dms-pages/REFERENCE.md +3 -3
  1243. package/skills/dms-pages/SKILL.md +5 -4
  1244. package/frontend-vue/antelope.config.json +0 -5
  1245. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationsList.vue +0 -226
  1246. package/frontend-vue/layers/dms-layout/app/components/profile/ProfileLanguage.vue +0 -51
  1247. package/frontend-vue/layers/dms-layout/app/components/profile/ProfileSessions.vue +0 -321
  1248. package/frontend-vue/layers/dms-layout/app/components/profile/ProfileTwoFactor.vue +0 -501
  1249. package/frontend-vue/layers/dms-layout/app/custom-pages/settings/appearance.vue +0 -174
  1250. package/frontend-vue/layers/dms-layout/app/custom-pages/settings/index.vue +0 -164
  1251. package/frontend-vue/layers/dms-layout/app/custom-pages/settings/notifications.vue +0 -15
  1252. package/frontend-vue/layers/dms-layout/app/plugins/language-sync.ts +0 -10
  1253. package/frontend-vue/layers/dms-ui/app/build/components/form/PermissionsTreeNode.vue +0 -148
  1254. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTree.vue +0 -98
  1255. package/frontend-vue/layers/dms-ui/app/components/form/components/PermissionsTree.vue +0 -133
  1256. package/frontend-vue/layers/dms-ui/app/components/tree/Tree.vue +0 -196
  1257. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/index.ts +0 -65
  1258. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/treeArrowDown.ts +0 -11
  1259. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/treeArrowUp.ts +0 -11
  1260. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/treeEnd.ts +0 -11
  1261. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/treeEnter.ts +0 -11
  1262. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/treeEscape.ts +0 -35
  1263. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/treeHome.ts +0 -11
  1264. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/treeShiftA.ts +0 -32
  1265. package/frontend-vue/layers/dms-ui/app/composables/tree/shortcuts/treeSpace.ts +0 -11
  1266. package/frontend-vue/layers/dms-ui/app/composables/tree/types/events.ts +0 -8
  1267. package/frontend-vue/layers/dms-ui/app/composables/tree/types/index.ts +0 -4
  1268. package/frontend-vue/layers/dms-ui/app/composables/tree/types/navigation.ts +0 -7
  1269. package/frontend-vue/layers/dms-ui/app/composables/tree/types/node.ts +0 -12
  1270. package/frontend-vue/layers/dms-ui/app/composables/tree/types/props.ts +0 -34
  1271. package/frontend-vue/layers/dms-ui/app/composables/tree/useTree.ts +0 -334
  1272. package/frontend-vue/layers/dms-ui/app/plugins/table-view-displays.client.ts +0 -31
  1273. package/frontend-vue/tests/tree-escape-shortcut.test.ts +0 -138
  1274. package/frontend-vue/tests/tree-without-source.test.ts +0 -79
  1275. /package/frontend-vue/layers/dms-ui/app/{utils → build/utils}/responseWarning.ts +0 -0
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts" generic="T extends Data">
2
2
  import type {
3
3
  ColumnSizingState,
4
+ ExpandedState,
4
5
  PaginationState,
5
6
  RowSelectionState,
6
7
  SortingState,
@@ -15,16 +16,28 @@ import {
15
16
  type QuickActionIntent,
16
17
  readQuickActionIntent,
17
18
  } from "../../types/quick-actions";
19
+ import { registerQuickActionTarget } from "../../build/utils/quickActionTargets";
18
20
  import type {
19
21
  KanbanConfig,
20
22
  TableViewConfig,
23
+ TableViewExpandableConfig,
24
+ TableViewFooter,
25
+ TableViewQuickFilter,
21
26
  TableViewListResponse,
22
27
  TableViewDisplayContext,
23
28
  TableViewDisplayConfig,
29
+ TableViewExpandedRowProps,
30
+ TableViewViewsConfig,
31
+ TableViewGroupedConfig,
32
+ TableViewEmptyStatesConfig,
33
+ TableViewPaginationMode,
34
+ TableViewSourceConfig,
35
+ TableViewReorderConfig,
24
36
  } from "../../composables/table-view/types";
25
37
  import {
26
38
  TABLE_DISPLAY_ID,
27
39
  KANBAN_DISPLAY_ID,
40
+ GROUPED_DISPLAY_ID,
28
41
  TableViewEvents,
29
42
  } from "../../composables/table-view/types";
30
43
  import {
@@ -35,11 +48,53 @@ import { useTableRowActions } from "../../build/composables/table-view/useTableV
35
48
  import {
36
49
  buildTableDataKey,
37
50
  buildTableQuery,
51
+ isFilterEffective,
38
52
  } from "../../build/composables/table-view/utils/tableQuery";
39
53
  import { buildTableViewShortcuts } from "../../composables/table-view/shortcuts";
54
+ import {
55
+ defaultExpandedRows,
56
+ type ExpandedRowMap,
57
+ keepListedRows,
58
+ nextExpandedRows,
59
+ } from "../../build/composables/table-view/utils/expandedRows";
60
+ import { resolveTableChrome } from "../../build/composables/table-view/utils/chrome";
61
+ import {
62
+ isSameSorting,
63
+ isUnsortableFieldError,
64
+ defaultSortingState,
65
+ resolveDefaultSortConfig,
66
+ sanitizeSorting,
67
+ sortableColumnIds,
68
+ sortValueKind,
69
+ } from "../../build/composables/table-view/utils/sortableColumns";
70
+ import { selectedRowIds } from "../../build/composables/table-view/utils/bulkActions";
71
+ import { isBulkAction } from "../../build/composables/actions/bulkSelection";
72
+ import { selectionScopeKey } from "../../build/utils/selectionScope";
73
+ import { readRecordId } from "../../build/composables/table-view/utils/recordLink";
74
+ import type { CustomRowAction } from "../../types/row-action";
75
+ import {
76
+ type QuickFilterItem,
77
+ quickFilterMode,
78
+ relationQuickFilterItems,
79
+ relationQuickFilterSource,
80
+ type ResolvedQuickFilter,
81
+ staticQuickFilterItems,
82
+ } from "../../build/composables/table-view/utils/quickFilters";
83
+ import { useNavBadges } from "../../build/composables/navigation/useNavBadges";
84
+ import { resolveRowClickAction } from "../../utils/rowClickAction";
85
+ import { usePermissionPreview } from "#dms-core/app/build/composables/auth/usePermissionPreview";
40
86
 
41
87
  import UTable from "../../build/components/table/Table.vue";
42
- import type { TableViewSwitcherItem } from "../../build/components/table/Table.vue";
88
+ import ExpandedRowDetail from "../../build/components/table-view/ExpandedRowDetail.vue";
89
+ import { buildExpandedRowProps } from "../../build/composables/table-view/utils/expandedRowProps";
90
+ import {
91
+ type ExpandedRowLoadState,
92
+ useExpandedRowDetails,
93
+ } from "../../build/composables/table-view/useExpandedRowDetails";
94
+ import type {
95
+ TableAccumulation,
96
+ TableViewSwitcherItem,
97
+ } from "../../build/components/table/Table.vue";
43
98
  import {
44
99
  defineAsyncComponent,
45
100
  type Component,
@@ -47,6 +102,23 @@ import {
47
102
  type WatchSource,
48
103
  } from "vue";
49
104
  import { useTableViewConfig } from "../../build/composables/table-view/useTableViewConfig";
105
+ import { useTableViews } from "../../build/composables/table-view/useTableViews";
106
+ import { useGroupedRows } from "../../build/composables/table-view/useGroupedRows";
107
+ import { useTableFooter } from "../../build/composables/table-view/useTableFooter";
108
+ import { useAccumulatedPages } from "../../build/composables/table-view/useAccumulatedPages";
109
+ import { useTableRows } from "../../build/composables/table-view/useTableRows";
110
+ import { useTableReorder } from "../../build/composables/table-view/useTableReorder";
111
+ import {
112
+ groupedOptionsFor,
113
+ groupedSorting,
114
+ isGroupableColumn,
115
+ } from "../../build/composables/table-view/utils/groupedRows";
116
+ import { readTableUrlKey } from "../../build/composables/table-view/utils/views";
117
+ import TableViews, {
118
+ type TableViewItem,
119
+ } from "../../build/components/table/Views.vue";
120
+ import { useServerRenderedAsyncData } from "../../build/composables/table-view/useServerRenderedAsyncData";
121
+ import { useTableDataChanges } from "../../composables/table-view/useTableDataChanges";
50
122
 
51
123
  const REALTIME_ROW_TOPIC_PREFIX = "tableview:row:";
52
124
  const REALTIME_PRESENCE_TOPIC_PREFIX = "tableview:presence:";
@@ -72,7 +144,34 @@ interface RealtimePresenceActor {
72
144
 
73
145
  type RealtimePresenceMap = Record<string, RealtimePresenceActor[]>;
74
146
 
75
- interface TableViewProps<T extends Data> extends TableViewConfig<T> {}
147
+ // The backend options of a table view, declared here as well so the
148
+ // component's runtime props never depend on resolving the imported config.
149
+ interface TableViewProps<T extends Data> extends TableViewConfig<T> {
150
+ /** Expandable rows: caret column + detail band (backend `expandable`). */
151
+ expandable?: TableViewExpandableConfig;
152
+ /** Placeholder of the search field. */
153
+ searchPlaceholder?: string;
154
+ /** One-click dropdown filters of the toolbar. */
155
+ quickFilters?: TableViewQuickFilter[];
156
+ /** Rows per page while the user picked none. */
157
+ pageSize?: number;
158
+ /** How the rows beyond the first page are reached. */
159
+ pagination?: TableViewPaginationMode;
160
+ /** A `TableView.fromSource` table's route, instead of a data controller. */
161
+ source?: TableViewSourceConfig;
162
+ /** Rows ordered by hand on a number column (backend `reorder`). */
163
+ reorder?: TableViewReorderConfig;
164
+ /** Footer texts and figures: row count, hint, summaries and legend. */
165
+ footer?: TableViewFooter;
166
+ /** What the empty body says, per reason it is empty. */
167
+ emptyStates?: TableViewEmptyStatesConfig;
168
+ /** Named states of the table (backend `views`). */
169
+ views?: TableViewViewsConfig;
170
+ /** Key of the table view in its page, prefixing its URL keys. */
171
+ tableId?: string;
172
+ /** The page carries no other table view: `?view=` / `?tab=` are its own. */
173
+ isSoleTableView?: boolean;
174
+ }
76
175
 
77
176
  const props = defineProps<TableViewProps<T>>();
78
177
 
@@ -126,6 +225,9 @@ const optionsForDisplay = (id: string): Record<string, unknown> | undefined =>
126
225
  const kanbanOptions = optionsForDisplay(KANBAN_DISPLAY_ID) as
127
226
  | KanbanConfig
128
227
  | undefined;
228
+ const groupedOptions = optionsForDisplay(GROUPED_DISPLAY_ID) as
229
+ | TableViewGroupedConfig
230
+ | undefined;
129
231
 
130
232
  // Stored under the legacy "viewMode" key (free migration of "table"/"kanban");
131
233
  // clamped to the offered set so a stale/removed id never renders an un-offered display.
@@ -133,10 +235,22 @@ const persistedDisplay = getPreference<string>(
133
235
  getTablePreferenceKey("viewMode"),
134
236
  defaultDisplay,
135
237
  );
238
+ // A default display that draws its whole interface (no table chrome, hence no
239
+ // switcher) is the only way into the page: a saved choice cannot override it.
240
+ const isDefaultDisplayStandalone =
241
+ resolvedDisplay(defaultDisplay)?.capabilities?.header === false;
136
242
  const activeDisplayId = ref<string>(
137
- offeredDisplayIds.has(persistedDisplay) ? persistedDisplay : TABLE_DISPLAY_ID,
243
+ isDefaultDisplayStandalone
244
+ ? defaultDisplay
245
+ : offeredDisplayIds.has(persistedDisplay)
246
+ ? persistedDisplay
247
+ : TABLE_DISPLAY_ID,
138
248
  );
139
249
 
250
+ /** A display the backend config renders by itself, with no client plugin. */
251
+ const isConfigRenderedDisplay = (id: string): boolean =>
252
+ !!resolvedDisplay(id)?.component;
253
+
140
254
  const availableDisplays = computed<TableViewSwitcherItem[]>(() =>
141
255
  registeredDisplays.value
142
256
  .filter((display) => offeredDisplayIds.has(display.id))
@@ -153,11 +267,14 @@ const availableDisplays = computed<TableViewSwitcherItem[]>(() =>
153
267
 
154
268
  // SSR-safe: capabilities + self-managed flag come from config, not the
155
269
  // client-only registry, so the chrome and list-query decision match across SSR.
156
- const activeCapabilities = computed(() =>
157
- resolveDisplayCapabilities(
270
+ // A hand-ordered table is listed by its position: no sort to pick.
271
+ const reorderConfig = props.reorder;
272
+ const activeCapabilities = computed(() => {
273
+ const capabilities = resolveDisplayCapabilities(
158
274
  resolvedDisplay(activeDisplayId.value)?.capabilities,
159
- ),
160
- );
275
+ );
276
+ return reorderConfig ? { ...capabilities, sorting: false } : capabilities;
277
+ });
161
278
 
162
279
  const isActiveDisplaySelfManaged = computed(
163
280
  () => !!resolvedDisplay(activeDisplayId.value)?.selfManagedData,
@@ -183,10 +300,12 @@ const resolveDisplayComponentRef = (
183
300
  const activeDisplayComponent = computed<Component | string | undefined>(() => {
184
301
  const id = activeDisplayId.value;
185
302
  if (id === TABLE_DISPLAY_ID || !offeredDisplayIds.has(id)) return undefined;
186
- const registered = getById(id)?.component;
187
- if (registered) return resolveDisplayComponentRef(registered);
303
+ // The instance's own component wins over the registered one: the server
304
+ // renders it, so the client must hydrate the same tree.
188
305
  const fromConfig = resolvedDisplay(id)?.component;
189
306
  if (fromConfig) return resolveDisplayComponentRef(fromConfig);
307
+ const registered = getById(id)?.component;
308
+ if (registered) return resolveDisplayComponentRef(registered);
190
309
  return STATIC_DISPLAY_COMPONENTS[id];
191
310
  });
192
311
 
@@ -205,23 +324,116 @@ if (
205
324
  kanbanGroupBy.value = kanbanOptions.groupByField;
206
325
  }
207
326
 
208
- const DEFAULT_PAGINATION: PaginationState = { pageIndex: 0, pageSize: 10 };
327
+ const DEFAULT_DENSITY = "default";
328
+ // The module's density is the default; the user's pick in the ⋯ menu is kept
329
+ // with the rest of the table's state.
330
+ const density = ref<"default" | "compact">(
331
+ getPreference(
332
+ getTablePreferenceKey("density"),
333
+ props.density ?? DEFAULT_DENSITY,
334
+ ),
335
+ );
336
+
337
+ const DEFAULT_PAGE_SIZE = 10;
338
+ const DEFAULT_PAGINATION: PaginationState = {
339
+ pageIndex: 0,
340
+ pageSize: props.pageSize ?? DEFAULT_PAGE_SIZE,
341
+ };
342
+ const resolvedChrome = resolveTableChrome(props.layout, {
343
+ hasCaption: !!caption,
344
+ isSearchable: !!props.searchable,
345
+ isFilterable: allColumns.some((column) => column.enableColumnFilter),
346
+ });
209
347
  const GLOBAL_FILTER_DEBOUNCE_MS = 400;
210
348
 
211
- const pagination = ref<PaginationState>(
349
+ const paginationState = ref<PaginationState>(
212
350
  getPreference<PaginationState>(
213
351
  getTablePreferenceKey("pagination"),
214
352
  DEFAULT_PAGINATION,
215
353
  ),
216
354
  );
217
355
  const rowSelect = ref<RowSelectionState>({});
218
- const defaultSortState: SortingState = defaultSort
219
- ? [{ id: defaultSort.field, desc: defaultSort.desc ?? false }]
356
+ // A column's grid header, for the sort messages.
357
+ const columnLabel = (id: string): string => {
358
+ const column = allColumns.find((c) => (c.id ?? c.accessorKey) === id);
359
+ return column ? processI18n(column.header) : id;
360
+ };
361
+
362
+ // The list route sorts on one `@Sortable()` column and refuses any other key
363
+ // with a 400 that would leave the table on its error panel: every sort it is
364
+ // sent (default, saved, pasted, picked) is checked against the columns first.
365
+ const declaredSortableIds = sortableColumnIds(allColumns);
366
+ // Columns the route refused although declared sortable (see the recovery
367
+ // below): a backend change since the page loaded.
368
+ const refusedSortIds = ref<string[]>([]);
369
+ const sortableIds = computed(
370
+ () =>
371
+ new Set(
372
+ [...declaredSortableIds].filter(
373
+ (id) => !refusedSortIds.value.includes(id),
374
+ ),
375
+ ),
376
+ );
377
+
378
+ // The grouped display's column, picked in the options menu as the kanban's
379
+ // is: the rows of a group follow each other only when the route sorts on it.
380
+ const groupedGroupByOptions = groupedOptions
381
+ ? allColumns
382
+ .filter(
383
+ (column) =>
384
+ column.accessorKey === groupedOptions.groupByField ||
385
+ (isGroupableColumn(column) &&
386
+ declaredSortableIds.has(column.accessorKey)),
387
+ )
388
+ .map((column) => ({
389
+ label: processI18n(column.header),
390
+ value: column.accessorKey,
391
+ }))
220
392
  : [];
393
+ const groupedGroupBy = ref<string>(
394
+ getPreference<string>(
395
+ getTablePreferenceKey("groupedGroupBy"),
396
+ groupedOptions?.groupByField ?? "",
397
+ ),
398
+ );
399
+ if (
400
+ groupedOptions &&
401
+ !groupedGroupByOptions.some((o) => o.value === groupedGroupBy.value)
402
+ ) {
403
+ groupedGroupBy.value = groupedOptions.groupByField;
404
+ }
405
+ const activeGroupedOptions = computed<TableViewGroupedConfig | undefined>(
406
+ () =>
407
+ groupedOptions &&
408
+ groupedOptionsFor(groupedOptions, groupedGroupBy.value, allColumns),
409
+ );
410
+ // The declared default sort when the route accepts it; without one, the
411
+ // sortable creation date, newest first, rather than the database's natural
412
+ // order (see `resolveDefaultSortConfig`).
413
+ const tableDefaultSort = resolveDefaultSortConfig(
414
+ defaultSort,
415
+ declaredSortableIds,
416
+ import.meta.env.DEV ? (message) => console.warn(message) : undefined,
417
+ );
418
+ const defaultSortState: SortingState = defaultSortingState(tableDefaultSort);
419
+ // The toolbar sort menu names the default sort even when its field is not a
420
+ // displayed column.
421
+ const defaultSortLabel = tableDefaultSort
422
+ ? columnLabel(tableDefaultSort.field)
423
+ : undefined;
424
+ const defaultSortKind = tableDefaultSort
425
+ ? sortValueKind(
426
+ allColumns.find((c) => (c.id ?? c.accessorKey) === tableDefaultSort.field)
427
+ ?.type?.id,
428
+ )
429
+ : undefined;
221
430
  const sorting = ref<SortingState>(
222
- getPreference<SortingState>(
223
- getTablePreferenceKey("sorting"),
224
- defaultSortState,
431
+ sanitizeSorting(
432
+ getPreference<SortingState>(
433
+ getTablePreferenceKey("sorting"),
434
+ defaultSortState,
435
+ ),
436
+ declaredSortableIds,
225
437
  ),
226
438
  );
227
439
 
@@ -258,6 +470,9 @@ const columnVisibility = ref<VisibilityState>(
258
470
  const columnSizing = ref<ColumnSizingState>(
259
471
  getPreference<ColumnSizingState>(getTablePreferenceKey("columnSizing"), {}),
260
472
  );
473
+ const columnOrder = ref<string[]>(
474
+ getPreference<string[]>(getTablePreferenceKey("columnOrder"), []),
475
+ );
261
476
  const hasEmptyDefaultFilter = (defaultFilters || []).some(
262
477
  (f) => f.value === undefined || f.value === null || f.value === "",
263
478
  );
@@ -274,12 +489,67 @@ const globalFilterDebounced = refDebounced(
274
489
  );
275
490
  const showArchived = ref(false);
276
491
 
492
+ const urlScope = {
493
+ tableId: props.tableId,
494
+ isSoleTableView: props.isSoleTableView,
495
+ };
496
+
497
+ // Views: named states of the whole table, the module's and the user's own.
498
+ const {
499
+ items: tableViewItems,
500
+ activeViewId,
501
+ isModified: isViewModified,
502
+ canSaveViews,
503
+ openView,
504
+ resetView,
505
+ saveView,
506
+ saveAsNewView,
507
+ deleteView,
508
+ } = useTableViews({
509
+ views: props.views,
510
+ defaults: {
511
+ pinnedFilters: (defaultFilters || []).map((filter) => ({
512
+ accessorKey: filter.accessorKey,
513
+ mode: filter.mode,
514
+ value: filter.value,
515
+ pinned: true,
516
+ initialValue: filter.value,
517
+ })),
518
+ sorting: defaultSortState,
519
+ visibility: initialVisibility,
520
+ columnOrder: listableColumns.map(
521
+ (column) => column.id ?? column.accessorKey,
522
+ ),
523
+ display: offeredDisplayIds.has(defaultDisplay)
524
+ ? defaultDisplay
525
+ : TABLE_DISPLAY_ID,
526
+ density: props.density ?? DEFAULT_DENSITY,
527
+ displays: offeredDisplayIds,
528
+ },
529
+ state: {
530
+ columnFilters,
531
+ globalFilter,
532
+ sorting,
533
+ columnVisibility,
534
+ columnOrder,
535
+ display: activeDisplayId,
536
+ density,
537
+ pagination: paginationState,
538
+ },
539
+ preferenceKey: getTablePreferenceKey,
540
+ urlScope,
541
+ });
542
+
277
543
  const ALL_TAB_ID = "all";
278
544
 
279
545
  const { t, te } = useI18n();
280
546
 
547
+ const TAB_URL_KEY = "tab";
548
+ const urlTab = readTableUrlKey(useDmsRoute().query, urlScope, TAB_URL_KEY);
549
+ // A tab named by the URL wins over the one kept from the last visit.
281
550
  const activeTabId = ref<string>(
282
- getPreference<string>(getTablePreferenceKey("activeTab"), ALL_TAB_ID),
551
+ urlTab.value ??
552
+ getPreference<string>(getTablePreferenceKey("activeTab"), ALL_TAB_ID),
283
553
  );
284
554
 
285
555
  interface ResolvedTab {
@@ -289,29 +559,38 @@ interface ResolvedTab {
289
559
  icon?: string;
290
560
  textColor?: string;
291
561
  iconColor?: string;
562
+ /** Link tab: the page it opens. */
563
+ to?: string;
564
+ toPage?: string;
565
+ countFrom?: string;
566
+ navBadge?: boolean;
292
567
  }
293
568
 
569
+ // A configured "all" tab stands in for the implicit one, at its own place.
570
+ const hasConfiguredAllTab = (tabs ?? []).some((tab) => tab.id === ALL_TAB_ID);
571
+
294
572
  const resolvedTabs = computed<ResolvedTab[]>(() => {
295
573
  // Tabs are a transverse-but-table-shaped concept; displays that opt out of the
296
574
  // `tabs` capability (e.g. kanban) hide them and have their own grouping.
297
575
  if (!activeCapabilities.value.tabs) return [];
298
576
  if (!tabs || tabs.length === 0) return [];
577
+ const implicitAll: ResolvedTab[] = hasConfiguredAllTab
578
+ ? []
579
+ : [{ id: ALL_TAB_ID, label: t("dms.table.tabs.all"), filters: [] }];
299
580
  return [
300
- {
301
- id: ALL_TAB_ID,
302
- label: t("dms.table.tabs.all"),
303
- filters: [] as TableFilter[],
304
- icon: undefined,
305
- textColor: undefined,
306
- iconColor: undefined,
307
- },
581
+ ...implicitAll,
308
582
  ...tabs.map((tab) => ({
309
583
  id: tab.id,
310
584
  label: processI18n(tab.label),
311
- filters: tab.filters.map((f) => ({ ...f })),
585
+ // A link tab filters nothing: it opens another page.
586
+ filters: tab.filter && !tab.to ? [{ ...tab.filter }] : [],
312
587
  icon: tab.icon,
313
588
  textColor: tab.textColor,
314
589
  iconColor: tab.iconColor,
590
+ to: tab.to,
591
+ toPage: tab.toPage,
592
+ countFrom: tab.countFrom,
593
+ navBadge: tab.navBadge,
315
594
  })),
316
595
  ];
317
596
  });
@@ -323,12 +602,19 @@ const activeTabFilters = computed<TableFilter[]>(() => {
323
602
 
324
603
  watch(resolvedTabs, (next) => {
325
604
  if (next.length === 0) return;
326
- if (!next.some((tab) => tab.id === activeTabId.value)) {
605
+ if (!next.some((tab) => !tab.to && tab.id === activeTabId.value)) {
327
606
  activeTabId.value = ALL_TAB_ID;
328
607
  }
329
608
  });
330
609
 
331
610
  const { $authFetch } = useAuthFetch();
611
+ // The controller's routes, or a `TableView.fromSource` table's route.
612
+ const tableRows = useTableRows<T>({
613
+ api: $authFetch,
614
+ location,
615
+ source: props.source,
616
+ columns: props.columns,
617
+ });
332
618
  const route = useDmsRoute();
333
619
 
334
620
  const DEFAULT_FILTER_MODE = "is";
@@ -357,6 +643,66 @@ const routeParamHiddenFilters = computed<TableFilter[]>(() => {
357
643
  }));
358
644
  });
359
645
 
646
+ // Quick filters: dropdowns of the toolbar over a column's values (a select's
647
+ // items, a boolean, the rows a relation points to), writing that column's
648
+ // filter like the filters row does.
649
+ const relationQuickFilterValues = ref<Record<string, QuickFilterItem[]>>({});
650
+ // Relation values load after mount: until then their buttons hold their place.
651
+ const relationQuickFiltersLoaded = ref(false);
652
+ const quickFilterDefinitions = (props.quickFilters ?? []).map((filter) => {
653
+ const column = allColumns.find(
654
+ (candidate) => candidate.accessorKey === filter.field,
655
+ );
656
+ return {
657
+ filter,
658
+ column,
659
+ mode: quickFilterMode(column, filter.mode),
660
+ items: staticQuickFilterItems(column, processI18n),
661
+ source: relationQuickFilterSource(column),
662
+ };
663
+ });
664
+
665
+ const RELATION_QUICK_FILTER_LIMIT = 200;
666
+
667
+ const loadRelationQuickFilters = async () => {
668
+ await Promise.allSettled(
669
+ quickFilterDefinitions
670
+ .filter((definition) => !definition.items && definition.source)
671
+ .map(async ({ filter, source }) => {
672
+ try {
673
+ const response = await $authFetch<
674
+ TableViewListResponse<Record<string, unknown>>
675
+ >(source!.url, { query: { limit: RELATION_QUICK_FILTER_LIMIT } });
676
+ relationQuickFilterValues.value = {
677
+ ...relationQuickFilterValues.value,
678
+ [filter.field]: relationQuickFilterItems(response.results, source!),
679
+ };
680
+ } catch {
681
+ // A picker the caller may not read just stays out of the toolbar.
682
+ }
683
+ }),
684
+ );
685
+ relationQuickFiltersLoaded.value = true;
686
+ };
687
+
688
+ // A quick filter with nothing to pick is left out of the toolbar; one whose
689
+ // relation values are still loading shows disabled, holding its place.
690
+ const resolvedQuickFilters = computed<ResolvedQuickFilter[]>(() =>
691
+ quickFilterDefinitions
692
+ .map(({ filter, column, mode, items, source }) => ({
693
+ field: filter.field,
694
+ label: processI18n(filter.label ?? column?.header ?? filter.field),
695
+ icon: filter.icon ?? "i-ph-funnel",
696
+ allLabel: filter.allLabel
697
+ ? processI18n(filter.allLabel)
698
+ : t("dms.table.quick_filter.all"),
699
+ mode,
700
+ items: items ?? relationQuickFilterValues.value[filter.field] ?? [],
701
+ pending: !items && !!source && !relationQuickFiltersLoaded.value,
702
+ }))
703
+ .filter((filter) => filter.items.length > 0 || filter.pending),
704
+ );
705
+
360
706
  const hiddenFilters = computed<TableFilter[]>(() => [
361
707
  ...queryParamHiddenFilters.value,
362
708
  ...routeParamHiddenFilters.value,
@@ -397,13 +743,40 @@ const effectiveColumnFilters = computed<TableFilter[]>(() =>
397
743
  const effectiveGlobalFilter = computed(() =>
398
744
  activeCapabilities.value.search ? globalFilterDebounced.value : undefined,
399
745
  );
400
- const effectiveSorting = computed<SortingState>(() =>
401
- activeCapabilities.value.sorting ? sorting.value : defaultSortState,
746
+ const isGroupedDisplay = computed(
747
+ () => activeDisplayId.value === GROUPED_DISPLAY_ID && !!groupedOptions,
402
748
  );
749
+ const effectiveSorting = computed<SortingState>(() => {
750
+ if (reorderConfig) return [{ id: reorderConfig.field, desc: false }];
751
+ const picked = activeCapabilities.value.sorting
752
+ ? sorting.value
753
+ : defaultSortState;
754
+ return sanitizeSorting(
755
+ isGroupedDisplay.value && activeGroupedOptions.value
756
+ ? groupedSorting(picked, activeGroupedOptions.value)
757
+ : picked,
758
+ sortableIds.value,
759
+ );
760
+ });
761
+
762
+ // A feed grows by pages (`loadMore`, `infinite`) rather than paging.
763
+ const paginationMode = props.pagination ?? "pages";
764
+ const { isAccumulating, requestedPagination, loadNextPage } =
765
+ useAccumulatedPages({
766
+ mode: paginationMode,
767
+ pagination: paginationState,
768
+ resetOn: [
769
+ effectiveSorting,
770
+ effectiveColumnFilters,
771
+ hiddenFilters,
772
+ effectiveGlobalFilter,
773
+ showArchived,
774
+ ],
775
+ });
403
776
 
404
777
  const queryRequest = computed(() =>
405
778
  buildTableQuery({
406
- pagination: pagination.value,
779
+ pagination: requestedPagination.value,
407
780
  sorting: effectiveSorting.value,
408
781
  columnFilters: effectiveColumnFilters.value,
409
782
  hiddenFilters: hiddenFilters.value,
@@ -429,7 +802,7 @@ const tableDataKey = buildTableDataKey({
429
802
  isSelfManaged: isActiveDisplaySelfManaged.value,
430
803
  });
431
804
 
432
- const { data, status, error, refresh } = await useDmsAsyncData(
805
+ const { data, status, error, refresh } = await useServerRenderedAsyncData(
433
806
  tableDataKey,
434
807
  (): Promise<TableViewListResponse<T>> => {
435
808
  // Self-managed displays (e.g. kanban) fetch their own data; skip the
@@ -437,13 +810,18 @@ const { data, status, error, refresh } = await useDmsAsyncData(
437
810
  if (isActiveDisplaySelfManaged.value) {
438
811
  return Promise.resolve(EMPTY_LIST_RESULT);
439
812
  }
440
- return $authFetch<TableViewListResponse<T>>(location + "/list", {
441
- query: { ...queryRequest.value, ...archiveQuery.value },
442
- });
813
+ return tableRows.list({ ...queryRequest.value, ...archiveQuery.value });
443
814
  },
444
815
  { watch: [queryRequest, archiveQuery, isActiveDisplaySelfManaged] },
445
816
  );
446
817
 
818
+ // Nothing listed yet (a client navigation paints before the first page
819
+ // arrives): the table draws its skeleton, never the empty state.
820
+ const isFirstPageLoading = computed(() => data.value === null && !error.value);
821
+ const isListLoading = computed(
822
+ () => status.value === "pending" || isFirstPageLoading.value,
823
+ );
824
+
447
825
  // A refused or failed list query must show as an error, never as an empty
448
826
  // table: "no data" on a 403 would tell a blocked caller there is nothing
449
827
  // to see.
@@ -477,6 +855,51 @@ watch(listLoadError, (message) => {
477
855
  if (message) rowSelect.value = {};
478
856
  });
479
857
 
858
+ // Whatever sets the sort (a header, the sort menu, a pasted table config), the
859
+ // route only ever receives a sort it accepts. A new order lists from page 1:
860
+ // the page reached in the previous order shows unrelated rows in the new one.
861
+ // Synchronous, so the list is queried once, with both changes.
862
+ watch(
863
+ sorting,
864
+ (next, previous) => {
865
+ const sanitized = sanitizeSorting(next, sortableIds.value);
866
+ if (!isSameSorting(sanitized, next)) {
867
+ sorting.value = sanitized;
868
+ return;
869
+ }
870
+ const before = sanitizeSorting(previous, sortableIds.value);
871
+ if (
872
+ !isSameSorting(sanitized, before) &&
873
+ paginationState.value.pageIndex !== 0
874
+ ) {
875
+ paginationState.value = { ...paginationState.value, pageIndex: 0 };
876
+ }
877
+ },
878
+ { deep: true, flush: "sync" },
879
+ );
880
+
881
+ const toast = useToast();
882
+
883
+ // The route refused the sort key anyway: a column whose `@Sortable()` was
884
+ // removed since the page loaded. Stop sorting on it (the next query drops it)
885
+ // and list again, with a warning, rather than leaving the table on its error
886
+ // panel.
887
+ watch(error, (failure) => {
888
+ if (!failure || !isUnsortableFieldError(failure)) return;
889
+ const refused = effectiveSorting.value[0]?.id;
890
+ if (!refused) return;
891
+ refusedSortIds.value = [...refusedSortIds.value, refused];
892
+ sorting.value = sanitizeSorting(sorting.value, sortableIds.value);
893
+ toast.add({
894
+ title: t("dms.sort.reset_title"),
895
+ description: t("dms.sort.reset_description", {
896
+ column: columnLabel(refused),
897
+ }),
898
+ color: Color.warning,
899
+ icon: "i-ph-warning",
900
+ });
901
+ });
902
+
480
903
  // A non-self-managed display consumes the shared query, and nothing
481
904
  // guarantees it knows how to render a failure. While that query is in error,
482
905
  // fall back to the table body so the error panel and its retry replace the
@@ -486,49 +909,77 @@ const activeDisplayBlockedByError = computed(
486
909
  );
487
910
 
488
911
  watch(
489
- [() => data.value?.total, () => pagination.value.pageSize],
912
+ [() => data.value?.total, () => paginationState.value.pageSize],
490
913
  ([total, pageSize]) => {
491
914
  if (total === undefined || total === null || pageSize <= 0) return;
492
915
  const maxPageIndex = Math.max(0, Math.ceil(total / pageSize) - 1);
493
- if (pagination.value.pageIndex > maxPageIndex) {
494
- pagination.value = { ...pagination.value, pageIndex: maxPageIndex };
916
+ if (paginationState.value.pageIndex > maxPageIndex) {
917
+ paginationState.value = {
918
+ ...paginationState.value,
919
+ pageIndex: maxPageIndex,
920
+ };
495
921
  }
496
922
  },
497
923
  );
498
924
 
499
- const tabCountsQuery = computed(() =>
500
- resolvedTabs.value.map((tab) => ({
501
- id: tab.id,
502
- query: buildTableQuery({
503
- pagination: { pageIndex: 0, pageSize: 0 },
504
- sorting: [],
505
- columnFilters: [],
506
- hiddenFilters: [...queryParamHiddenFilters.value, ...tab.filters],
507
- }),
508
- })),
509
- );
925
+ // A view's counter shares the tab counters' request, under its own id.
926
+ const VIEW_COUNT_ID_PREFIX = "view:";
927
+ const countQuery = (filters: TableFilter[], search?: string) =>
928
+ buildTableQuery({
929
+ pagination: { pageIndex: 0, pageSize: 0 },
930
+ sorting: [],
931
+ columnFilters: filters,
932
+ hiddenFilters: queryParamHiddenFilters.value,
933
+ globalFilter: search,
934
+ });
935
+
936
+ const tabCountsQuery = computed(() => [
937
+ ...resolvedTabs.value
938
+ .filter((tab) => !tab.to)
939
+ .map((tab) => ({ id: tab.id, query: countQuery(tab.filters) })),
940
+ ...tableViewItems.value
941
+ .filter((view) => view.count)
942
+ .map((view) => ({
943
+ id: `${VIEW_COUNT_ID_PREFIX}${view.id}`,
944
+ query: countQuery(view.filters ?? [], view.search),
945
+ })),
946
+ ]);
510
947
 
948
+ // No default: `null` until the counts arrive, so the tabs draw placeholders
949
+ // instead of a count of nothing.
511
950
  const { data: tabCountsData, refresh: refreshTabCounts } =
512
- await useDmsAsyncData<Record<string, number>>(
951
+ await useServerRenderedAsyncData<Record<string, number>>(
513
952
  `table-view-${componentId}-${pageId}-tab-counts`,
514
953
  async () => {
515
- if (resolvedTabs.value.length === 0) return {};
516
- return await $authFetch<Record<string, number>>(
517
- location + "/count/batch",
518
- {
519
- method: "POST",
520
- body: {
521
- queries: tabCountsQuery.value.map(({ id, query }) => ({
522
- id,
523
- query: { ...query, ...archiveQuery.value },
524
- })),
525
- },
526
- },
954
+ if (tabCountsQuery.value.length === 0) return {};
955
+ return await tableRows.countBatch(
956
+ tabCountsQuery.value.map(({ id, query }) => ({
957
+ id,
958
+ query: { ...query, ...archiveQuery.value },
959
+ })),
527
960
  );
528
961
  },
529
- { watch: [tabCountsQuery, archiveQuery], default: () => ({}) },
962
+ { watch: [tabCountsQuery, archiveQuery] },
530
963
  );
531
964
 
965
+ const viewItems = computed<TableViewItem[]>(() =>
966
+ tableViewItems.value.map((view) => ({
967
+ id: view.id,
968
+ label: view.label,
969
+ icon: view.icon,
970
+ tone: view.tone,
971
+ dot: view.dot,
972
+ isUserView: view.isUserView,
973
+ count: view.count
974
+ ? tabCountsData.value?.[`${VIEW_COUNT_ID_PREFIX}${view.id}`]
975
+ : undefined,
976
+ countPending: !!view.count && tabCountsData.value == null,
977
+ })),
978
+ );
979
+ const viewsLayout = props.views?.layout ?? "tabs";
980
+ const hasViews =
981
+ !!props.views && (props.views.items.length > 0 || canSaveViews);
982
+
532
983
  interface ActiveDisplayExposed {
533
984
  refresh?: () => Promise<void> | void;
534
985
  }
@@ -554,6 +1005,75 @@ const baseQuery = computed<Record<string, unknown>>(() => {
554
1005
  return { ...query, ...archiveQuery.value };
555
1006
  });
556
1007
 
1008
+ const { footer: resolvedFooter, refreshSummaries } = await useTableFooter({
1009
+ footer: props.footer,
1010
+ columns: props.columns,
1011
+ location,
1012
+ query: baseQuery,
1013
+ dataKey: `table-view-${componentId}-${pageId}`,
1014
+ });
1015
+
1016
+ const hasMoreRows = computed(
1017
+ () => (data.value?.total ?? 0) > (shownResults.value?.length ?? 0),
1018
+ );
1019
+ const loadMoreRows = () => {
1020
+ if (hasMoreRows.value && !isListLoading.value) loadNextPage();
1021
+ };
1022
+ const accumulation = computed<TableAccumulation | undefined>(() =>
1023
+ isAccumulating
1024
+ ? {
1025
+ mode: paginationMode as TableAccumulation["mode"],
1026
+ shown: shownResults.value?.length ?? 0,
1027
+ hasMore: hasMoreRows.value,
1028
+ loading: isListLoading.value,
1029
+ load: loadMoreRows,
1030
+ }
1031
+ : undefined,
1032
+ );
1033
+
1034
+ // Rows ordered by hand: moving is off while anything narrows the rows.
1035
+ const { reorderState } = useTableReorder<T>({
1036
+ reorder: reorderConfig,
1037
+ data,
1038
+ rowIdKey: props.rowIdKey ?? ROW_ID_DEFAULT_KEY,
1039
+ location,
1040
+ api: $authFetch,
1041
+ canEdit: computed(() => isActionEnabled(tableProps.value.rowActions?.edit)),
1042
+ isNarrowed: computed(
1043
+ () =>
1044
+ effectiveColumnFilters.value.some(isFilterEffective) ||
1045
+ !!effectiveGlobalFilter.value ||
1046
+ activeTabFilters.value.length > 0,
1047
+ ),
1048
+ isGrid: computed(() => activeDisplayId.value === TABLE_DISPLAY_ID),
1049
+ refresh: () => refresh(),
1050
+ onError: (failure) =>
1051
+ toast.add({
1052
+ title: t("dms.table.reorder.error"),
1053
+ description: resolveApiErrorMessage(failure),
1054
+ color: Color.error,
1055
+ icon: "i-ph-warning-circle",
1056
+ }),
1057
+ });
1058
+
1059
+ const { grouping, refreshCounts: refreshGroupCounts } = useGroupedRows({
1060
+ grouped: activeGroupedOptions,
1061
+ isActive: isGroupedDisplay,
1062
+ columns: props.columns,
1063
+ rows: shownResults,
1064
+ countQuery: (filter) => ({
1065
+ ...buildTableQuery({
1066
+ pagination: { pageIndex: 0, pageSize: 0 },
1067
+ sorting: [],
1068
+ columnFilters: [...effectiveColumnFilters.value, filter],
1069
+ hiddenFilters: hiddenFilters.value,
1070
+ globalFilter: effectiveGlobalFilter.value,
1071
+ }),
1072
+ ...archiveQuery.value,
1073
+ }),
1074
+ countBatch: tableRows.countBatch,
1075
+ });
1076
+
557
1077
  // Only what the (unchanged) KanbanBoard needs beyond the generic context: the
558
1078
  // two-way group-by ref and the raw action configs for per-row rule evaluation.
559
1079
  provide(KANBAN_DISPLAY_BRIDGE_KEY, {
@@ -562,25 +1082,105 @@ provide(KANBAN_DISPLAY_BRIDGE_KEY, {
562
1082
  deleteAction: tableProps.value.rowActions?.delete,
563
1083
  });
564
1084
 
1085
+ // A link tab counts the rows of the list it opens; a list the caller may not
1086
+ // read shows no counter.
1087
+ const linkTabCounts = ref<Record<string, number>>({});
1088
+ // The link counters load after mount: until then their tabs hold a placeholder.
1089
+ const linkTabCountsLoaded = ref(false);
1090
+ const LINK_TAB_COUNT_QUERY = { limit: 1, offset: 0 };
1091
+
1092
+ const refreshLinkTabCounts = async () => {
1093
+ const linked = resolvedTabs.value.filter((tab) => tab.to && tab.countFrom);
1094
+ if (linked.length === 0) {
1095
+ linkTabCountsLoaded.value = true;
1096
+ return;
1097
+ }
1098
+ const entries = await Promise.all(
1099
+ linked.map(async (tab) => {
1100
+ try {
1101
+ const response = await $authFetch<TableViewListResponse<unknown>>(
1102
+ `${tab.countFrom}/list`,
1103
+ { query: LINK_TAB_COUNT_QUERY },
1104
+ );
1105
+ return [tab.id, response.total] as const;
1106
+ } catch {
1107
+ return undefined;
1108
+ }
1109
+ }),
1110
+ );
1111
+ linkTabCounts.value = Object.fromEntries(
1112
+ entries.filter((entry) => entry !== undefined),
1113
+ );
1114
+ linkTabCountsLoaded.value = true;
1115
+ };
1116
+
1117
+ // Each re-read follows a change of the rows (a save, an action, a realtime
1118
+ // event) or a refresh: what summarises them elsewhere (a navigation count)
1119
+ // is told to read its figure again.
1120
+ const { notifyTableDataChanged } = useTableDataChanges();
565
1121
  const refreshAll = async () => {
1122
+ notifyTableDataChanged(location);
566
1123
  await Promise.all([
567
1124
  refresh(),
568
1125
  refreshTabCounts(),
1126
+ refreshLinkTabCounts(),
1127
+ refreshGroupCounts(),
1128
+ refreshSummaries(),
569
1129
  activeDisplayRef.value?.refresh?.(),
570
1130
  ]);
571
1131
  };
572
1132
 
1133
+ // "Preview as role": a link tab to a page the previewed role could not open
1134
+ // is drawn locked, one to a page it opens partially is drawn partially
1135
+ // locked. Never outside a preview (`entryState` is null then).
1136
+ const permissionPreview = usePermissionPreview();
1137
+ const previewSiteLayout = useSiteLayout();
1138
+ const linkTabPreviewState = (tab: ResolvedTab) => {
1139
+ if (!tab.to || !permissionPreview.isActive.value) return null;
1140
+ const fullId =
1141
+ tab.toPage ??
1142
+ previewSiteLayout.findMatchingRoute(stripQueryAndHash(tab.to))?.metadata
1143
+ .fullId;
1144
+ return permissionPreview.entryState(fullId);
1145
+ };
1146
+
1147
+ const isTabCountPending = (tab: ResolvedTab): boolean => {
1148
+ if (!tab.to) return tabCountsData.value == null;
1149
+ return !!tab.countFrom && !linkTabCountsLoaded.value;
1150
+ };
1151
+
573
1152
  const tabsWithCount = computed(() =>
574
1153
  resolvedTabs.value.map((tab) => ({
575
1154
  id: tab.id,
576
1155
  label: tab.label,
577
- count: tabCountsData.value?.[tab.id],
1156
+ count: tab.to ? linkTabCounts.value[tab.id] : tabCountsData.value?.[tab.id],
1157
+ countPending: isTabCountPending(tab),
578
1158
  icon: tab.icon,
579
1159
  textColor: tab.textColor,
580
1160
  iconColor: tab.iconColor,
1161
+ to: tab.to,
1162
+ previewLocked: linkTabPreviewState(tab) === "hidden",
1163
+ previewPartial: linkTabPreviewState(tab) === "partial",
581
1164
  })),
582
1165
  );
583
1166
 
1167
+ // A tab declared with `navBadge` keeps the navigation badge the server
1168
+ // counted for the page it stands for (the linked page, or this one) up to
1169
+ // date with its own counter; an empty badge stands for zero.
1170
+ const { setNavBadge } = useNavBadges();
1171
+ watch(
1172
+ tabsWithCount,
1173
+ (next) => {
1174
+ for (const tab of next) {
1175
+ const source = resolvedTabs.value.find((entry) => entry.id === tab.id);
1176
+ if (!source?.navBadge || tab.count === undefined) continue;
1177
+ const fullId = source.to ? source.toPage : pageId;
1178
+ if (fullId) setNavBadge(fullId, tab.count > 0 ? String(tab.count) : "");
1179
+ }
1180
+ },
1181
+ { immediate: true },
1182
+ );
1183
+
584
1184
  const { exportTable } = useTableViewExport({ componentId });
585
1185
  const {
586
1186
  openRow,
@@ -593,6 +1193,8 @@ const {
593
1193
  restoreRows: restoreRowsAction,
594
1194
  handleCustomButton,
595
1195
  handleCustomRowAction,
1196
+ handleBulkCustomAction,
1197
+ runConfirmedBuiltIn,
596
1198
  } = useTableRowActions<T>({
597
1199
  api: $authFetch,
598
1200
  location,
@@ -607,25 +1209,56 @@ const {
607
1209
  componentId: componentId!,
608
1210
  pageId: pageId!,
609
1211
  queryParamFilters,
1212
+ rowNavigation: {
1213
+ rows: () => (shownResults.value ?? []) as Data[],
1214
+ rowIdKey: props.rowIdKey ?? ROW_ID_DEFAULT_KEY,
1215
+ },
1216
+ recordScope: urlScope,
610
1217
  });
611
1218
 
612
- const customNavItems = computed(() => {
613
- const items = [];
1219
+ // Custom actions offered on the selection bar. "Select all N matching"
1220
+ // hands them the table's filters instead of ids; a new query lists other
1221
+ // rows, so it ends with it.
1222
+ const bulkCustomActions = computed(() =>
1223
+ (tableProps.value.rowActions?.custom ?? []).filter(isBulkAction),
1224
+ );
1225
+ const allMatching = ref(false);
1226
+ const runBulkAction = (action: CustomRowAction) =>
1227
+ handleBulkCustomAction(
1228
+ action,
1229
+ allMatching.value
1230
+ ? { matching: baseQuery.value, count: data.value?.total ?? 0 }
1231
+ : { ids: selectedIds.value, count: selectedIds.value.length },
1232
+ );
614
1233
 
615
- const hasViewArchivedPermission =
616
- tableProps.value.rowActions?.showArchived === true;
1234
+ // Archive mode: the toolbar carries an "Archived" toggle for callers allowed
1235
+ // to see archived rows.
1236
+ const canToggleArchived = computed(
1237
+ () => !!archiveMode && tableProps.value.rowActions?.showArchived === true,
1238
+ );
617
1239
 
618
- if (archiveMode && hasViewArchivedPermission) {
619
- items.push({
620
- label: showArchived.value
621
- ? t("dms.table.show_active")
622
- : t("dms.table.show_archived"),
623
- icon: showArchived.value ? "i-ph-folder-open" : "i-ph-archive",
624
- onSelect: () => {
625
- showArchived.value = !showArchived.value;
626
- },
627
- });
628
- }
1240
+ // A selection made among the rows a filter, a search or a tab listed would
1241
+ // let a bulk action reach rows no longer shown: it goes with them.
1242
+ const selectionScope = computed(() =>
1243
+ selectionScopeKey({
1244
+ columnFilters: effectiveColumnFilters.value,
1245
+ hiddenFilters: hiddenFilters.value,
1246
+ globalFilter: effectiveGlobalFilter.value,
1247
+ }),
1248
+ );
1249
+ watch(selectionScope, () => {
1250
+ rowSelect.value = {};
1251
+ });
1252
+
1253
+ // A selection made among active rows means nothing among archived ones, and
1254
+ // the page reached in one list rarely exists in the other: start over.
1255
+ watch(showArchived, () => {
1256
+ rowSelect.value = {};
1257
+ paginationState.value = { ...paginationState.value, pageIndex: 0 };
1258
+ });
1259
+
1260
+ const customNavItems = computed(() => {
1261
+ const items = [];
629
1262
 
630
1263
  if (enableTableExport) {
631
1264
  items.push({
@@ -638,29 +1271,72 @@ const customNavItems = computed(() => {
638
1271
  return items;
639
1272
  });
640
1273
 
641
- const deleteRows = (ids: string[]) =>
642
- deleteRowsAction(ids, tableProps.value.rowActions?.delete);
1274
+ // Deleted, archived and restored rows leave the listed set: a selection kept
1275
+ // on them would offer bulk actions on rows no longer shown. A cancelled
1276
+ // confirmation (or a failed request) keeps the selection as it was.
1277
+ const deselectRows = (ids: string[]) => {
1278
+ const removed = new Set(ids);
1279
+ rowSelect.value = Object.fromEntries(
1280
+ Object.entries(rowSelect.value).filter(([id]) => !removed.has(id)),
1281
+ );
1282
+ };
643
1283
 
644
- const archiveRows = (ids: string[]) =>
645
- archiveRowsAction(ids, tableProps.value.rowActions?.archive);
1284
+ // From the archive, a delete is a permanent one: its confirmation says so.
1285
+ const deleteRows = async (ids: string[]) => {
1286
+ const done = await deleteRowsAction(
1287
+ ids,
1288
+ tableProps.value.rowActions?.delete,
1289
+ {
1290
+ permanently: !!archiveMode && showArchived.value,
1291
+ },
1292
+ );
1293
+ if (done) deselectRows(ids);
1294
+ };
1295
+
1296
+ const archiveRows = async (ids: string[]) => {
1297
+ if (await archiveRowsAction(ids, tableProps.value.rowActions?.archive)) {
1298
+ deselectRows(ids);
1299
+ }
1300
+ };
646
1301
 
647
- const restoreRows = (ids: string[]) =>
648
- restoreRowsAction(ids, tableProps.value.rowActions?.restore);
1302
+ const restoreRows = async (ids: string[]) => {
1303
+ if (await restoreRowsAction(ids, tableProps.value.rowActions?.restore)) {
1304
+ deselectRows(ids);
1305
+ }
1306
+ };
649
1307
 
650
1308
  const handleExportTable = () =>
651
1309
  exportTable(location, { ...queryRequest.value, ...archiveQuery.value });
652
1310
  const handleExportSelection = (ids: string[]) =>
653
1311
  exportTable(location, queryRequest.value, ids);
654
- const handleRowClick = (item: T) => openRow(item);
655
- const handleRowDuplicate = (itemId: string) => duplicateRow(itemId);
656
- const handleRowAdd = () => newRow(queryParamDefaults.value);
1312
+ // A built-in action declaring a `confirm` asks it first.
1313
+ const rowActionConfig = (key: "details" | "duplicate" | "add" | "edit") =>
1314
+ tableProps.value.rowActions?.[key];
1315
+ const handleRowClick = (item: T) =>
1316
+ runConfirmedBuiltIn(rowActionConfig("details"), item, () => openRow(item));
1317
+ const handleRowDuplicate = (itemId: string) =>
1318
+ runConfirmedBuiltIn(
1319
+ rowActionConfig("duplicate"),
1320
+ { [props.rowIdKey ?? ROW_ID_DEFAULT_KEY]: itemId },
1321
+ () => duplicateRow(itemId),
1322
+ );
1323
+ const handleRowAdd = () =>
1324
+ runConfirmedBuiltIn(rowActionConfig("add"), undefined, () =>
1325
+ newRow(queryParamDefaults.value),
1326
+ );
657
1327
 
658
1328
  const rowIdKey = props.rowIdKey ?? ROW_ID_DEFAULT_KEY;
1329
+ // A source table has no realtime: its route is no data controller's.
1330
+ const realtimeLocation = tableRows.isSource ? undefined : location;
659
1331
  const realtimeRowTopic = computed(() =>
660
- location ? `${REALTIME_ROW_TOPIC_PREFIX}${location}` : undefined,
1332
+ realtimeLocation
1333
+ ? `${REALTIME_ROW_TOPIC_PREFIX}${realtimeLocation}`
1334
+ : undefined,
661
1335
  );
662
1336
  const realtimePresenceTopic = computed(() =>
663
- location ? `${REALTIME_PRESENCE_TOPIC_PREFIX}${location}` : undefined,
1337
+ realtimeLocation
1338
+ ? `${REALTIME_PRESENCE_TOPIC_PREFIX}${realtimeLocation}`
1339
+ : undefined,
664
1340
  );
665
1341
 
666
1342
  const presenceByRow = ref<RealtimePresenceMap>({});
@@ -687,7 +1363,8 @@ const patchRowLocal = async (id: string) => {
687
1363
  const idx = data.value.results.findIndex((row) => getRowId(row) === id);
688
1364
  if (idx === -1) return;
689
1365
  try {
690
- const fresh = await $authFetch<T>(`${location}/get`, { query: { id } });
1366
+ const fresh = await tableRows.getRow(id);
1367
+ if (!fresh) return;
691
1368
  const next = [...data.value.results];
692
1369
  next[idx] = fresh as unknown as T;
693
1370
  data.value = { ...data.value, results: next };
@@ -702,6 +1379,8 @@ const realtimeEventHandlers: Record<
702
1379
  > = {
703
1380
  [REALTIME_EVENT_TYPE.DELETED]: (ids) => {
704
1381
  removeRowsLocal(ids);
1382
+ // Rows gone elsewhere leave the selection too, or it would count them.
1383
+ deselectRows(ids);
705
1384
  return refreshAll();
706
1385
  },
707
1386
  [REALTIME_EVENT_TYPE.CREATED]: () => refreshAll(),
@@ -820,6 +1499,78 @@ const presenceByRowFiltered = computed<RealtimePresenceMap>(() => {
820
1499
  return result;
821
1500
  });
822
1501
 
1502
+ // Expandable rows: which rows are open. A newly listed set (page, filter,
1503
+ // search, sort, tab, archive view) starts from `defaultExpanded`; a refresh of
1504
+ // the same set keeps what the user opened, minus rows no longer listed.
1505
+ const expandableConfig = props.expandable;
1506
+ const expanded = ref<ExpandedRowMap>({});
1507
+
1508
+ const rowIdsOf = (rows: T[] | undefined): string[] =>
1509
+ (rows ?? []).map((row) => getRowId(row)).filter((id): id is string => !!id);
1510
+
1511
+ const expandedModel = computed<ExpandedState>({
1512
+ get: () => expanded.value,
1513
+ set: (next) => {
1514
+ expanded.value = nextExpandedRows(
1515
+ expanded.value,
1516
+ next,
1517
+ rowIdsOf(shownResults.value),
1518
+ expandableConfig?.single,
1519
+ );
1520
+ },
1521
+ });
1522
+
1523
+ let expandedQueryKey: string | undefined;
1524
+ if (expandableConfig) {
1525
+ watch(
1526
+ shownResults,
1527
+ (rows) => {
1528
+ const queryKey = JSON.stringify([queryRequest.value, archiveQuery.value]);
1529
+ if (queryKey === expandedQueryKey) {
1530
+ expanded.value = keepListedRows(expanded.value, rowIdsOf(rows));
1531
+ return;
1532
+ }
1533
+ expandedQueryKey = queryKey;
1534
+ expanded.value = defaultExpandedRows(
1535
+ rowIdsOf(rows),
1536
+ expandableConfig.defaultExpanded,
1537
+ expandableConfig.single,
1538
+ );
1539
+ },
1540
+ { immediate: true },
1541
+ );
1542
+ }
1543
+
1544
+ // `lazyLoad` bands read their row when it opens; any reload of the listed
1545
+ // rows drops what they read, and the open ones read it again.
1546
+ const expandedDetails = useExpandedRowDetails<T>((id) => tableRows.getRow(id));
1547
+ if (expandableConfig?.lazyLoad) {
1548
+ watch(shownResults, () => expandedDetails.reset());
1549
+ watch(
1550
+ [expanded, shownResults],
1551
+ () =>
1552
+ expandedDetails.ensure(
1553
+ Object.keys(expanded.value).filter((id) => expanded.value[id]),
1554
+ ),
1555
+ { immediate: true },
1556
+ );
1557
+ }
1558
+
1559
+ const expandedRowLoadState = (id: string): ExpandedRowLoadState =>
1560
+ expandableConfig?.lazyLoad
1561
+ ? (expandedDetails.entryOf(id)?.state ?? "loading")
1562
+ : "ready";
1563
+
1564
+ // The band takes any row: its props are the table's, for the row type it lists.
1565
+ const expandedRowProps = (listed: T): TableViewExpandedRowProps => {
1566
+ const id = getRowId(listed);
1567
+ const read = id ? expandedDetails.entryOf(id)?.row : undefined;
1568
+ return buildExpandedRowProps<T>(
1569
+ read ? { ...listed, ...read } : listed,
1570
+ displayContext.value,
1571
+ ) as unknown as TableViewExpandedRowProps;
1572
+ };
1573
+
823
1574
  const { warnBeforeEdit } = usePresenceEditWarning();
824
1575
 
825
1576
  const handleRowEdit = async (item: T) => {
@@ -828,14 +1579,37 @@ const handleRowEdit = async (item: T) => {
828
1579
  const others = otherEditorsForRow(itemId);
829
1580
  if (others.length > 0 && !(await warnBeforeEdit(others))) return;
830
1581
  }
831
- return editRow(item, queryParamDefaults.value);
1582
+ return runConfirmedBuiltIn(rowActionConfig("edit"), item, () =>
1583
+ editRow(item, queryParamDefaults.value),
1584
+ );
832
1585
  };
833
1586
 
834
1587
  const EMPTY_ITEMS: T[] = [];
835
1588
 
836
- const selectedIds = computed(() =>
837
- Object.keys(rowSelect.value).filter((key) => rowSelect.value[key]),
1589
+ watch(
1590
+ baseQuery,
1591
+ () => {
1592
+ allMatching.value = false;
1593
+ },
1594
+ { deep: true },
838
1595
  );
1596
+ watch(rowSelect, (selection) => {
1597
+ if (Object.keys(selection).length === 0) allMatching.value = false;
1598
+ });
1599
+
1600
+ // A deep-linked action reopens on the row the URL names, listed or not.
1601
+ const deepLinkAction = (tableProps.value.rowActions?.custom ?? []).find(
1602
+ (action) => action.deepLink,
1603
+ );
1604
+ const openRecordFromUrl = async () => {
1605
+ const id = deepLinkAction ? readRecordId(route.query, urlScope) : undefined;
1606
+ if (!deepLinkAction || !id) return;
1607
+ const listed = shownResults.value?.find((row) => getRowId(row) === id);
1608
+ const row = listed ?? (await tableRows.getRow(id).catch(() => undefined));
1609
+ if (row) handleCustomRowAction(deepLinkAction, row as Data);
1610
+ };
1611
+
1612
+ const selectedIds = computed(() => selectedRowIds(rowSelect.value));
839
1613
 
840
1614
  const isRowActionEnabled = (
841
1615
  config: boolean | RowActionConfig | undefined,
@@ -889,19 +1663,43 @@ const displaySelection = {
889
1663
 
890
1664
  const displayPagination = {
891
1665
  setPage: (index: number) => {
892
- pagination.value = { ...pagination.value, pageIndex: index };
1666
+ paginationState.value = { ...paginationState.value, pageIndex: index };
893
1667
  },
894
1668
  setPageSize: (size: number) => {
895
- pagination.value = { ...pagination.value, pageSize: size, pageIndex: 0 };
1669
+ paginationState.value = {
1670
+ ...paginationState.value,
1671
+ pageSize: size,
1672
+ pageIndex: 0,
1673
+ };
896
1674
  },
897
1675
  };
898
1676
 
1677
+ // A display opens an item the way a click opens a row of the grid: its
1678
+ // default custom action, else edit, else details.
1679
+ const builtInRowClicks: Record<"edit" | "details", (item: T) => unknown> = {
1680
+ edit: handleRowEdit,
1681
+ details: handleRowClick,
1682
+ };
1683
+ const openDisplayItem = (item: T) => {
1684
+ const action = resolveRowClickAction(
1685
+ tableProps.value.rowActions,
1686
+ item as Record<string, unknown>,
1687
+ );
1688
+ if (!action) return;
1689
+ if (typeof action === "string") {
1690
+ void builtInRowClicks[action](item);
1691
+ return;
1692
+ }
1693
+ handleCustomRowAction(action, item);
1694
+ };
1695
+
899
1696
  const displayRowActions = {
900
1697
  add: handleRowAdd,
901
1698
  edit: handleRowEdit,
902
1699
  delete: deleteRows,
903
1700
  duplicate: handleRowDuplicate,
904
1701
  details: handleRowClick,
1702
+ open: openDisplayItem,
905
1703
  custom: handleCustomRowAction,
906
1704
  canEditRow: (item: T) =>
907
1705
  isRowActionEnabled(tableProps.value.rowActions?.edit, item),
@@ -920,13 +1718,16 @@ const displayContext = computed(
920
1718
  (): TableViewDisplayContext<T> => ({
921
1719
  items: shownResults.value ?? EMPTY_ITEMS,
922
1720
  columns: props.columns,
923
- loading: status.value === "pending",
1721
+ loading: isListLoading.value,
924
1722
  selection: { ids: selectedIds.value, ...displaySelection },
925
1723
  pagination: {
926
- pageIndex: pagination.value.pageIndex,
927
- pageSize: pagination.value.pageSize,
1724
+ pageIndex: paginationState.value.pageIndex,
1725
+ pageSize: paginationState.value.pageSize,
928
1726
  total: data.value?.total ?? 0,
929
1727
  ...displayPagination,
1728
+ mode: paginationMode,
1729
+ hasMore: hasMoreRows.value,
1730
+ loadMore: loadMoreRows,
930
1731
  },
931
1732
  actions: {
932
1733
  canAdd: isActionEnabled(tableProps.value.rowActions?.add),
@@ -981,6 +1782,14 @@ const quickActionHandlers: {
981
1782
  button: (intent) => pressCustomButton(intent.button),
982
1783
  };
983
1784
 
1785
+ function runQuickActionIntent(intent: QuickActionIntent) {
1786
+ // Keyed by the intent's own discriminant, so the handler always matches.
1787
+ const handler = quickActionHandlers[intent.kind] as (
1788
+ value: QuickActionIntent,
1789
+ ) => void;
1790
+ handler(intent);
1791
+ }
1792
+
984
1793
  // Watched key by key rather than through the parsed intent: a fresh intent
985
1794
  // object on every unrelated query change would press the button twice.
986
1795
  watch(
@@ -989,19 +1798,36 @@ watch(
989
1798
  QUICK_ACTION_COMPONENT_KEY,
990
1799
  QUICK_ACTION_BUTTON_KEY,
991
1800
  ].map((key) => () => route.query[key]),
992
- async () => {
1801
+ () => {
993
1802
  const intent = readQuickActionIntent(route.query, componentId);
994
1803
  if (!intent) return;
995
- await clearQuickActionQuery();
996
- // Keyed by the intent's own discriminant, so the handler always matches.
997
- const handler = quickActionHandlers[intent.kind] as (
998
- value: QuickActionIntent,
999
- ) => void;
1000
- handler(intent);
1804
+ // A server render only drops the query (a redirect): it opens nothing.
1805
+ if (import.meta.env.SSR) {
1806
+ void clearQuickActionQuery();
1807
+ return;
1808
+ }
1809
+ // Run first, then drop the query: dropping it is a server visit, and a
1810
+ // visit cut short by a navigation still settles, so awaiting it first
1811
+ // opened the form over the page navigated to.
1812
+ runQuickActionIntent(intent);
1813
+ void clearQuickActionQuery();
1001
1814
  },
1002
1815
  { immediate: true },
1003
1816
  );
1004
1817
 
1818
+ // A header button of this page presses this table view's buttons in place
1819
+ // (see `runMountedQuickAction`): the modal opens on the click.
1820
+ let unregisterQuickActionTarget: (() => void) | undefined;
1821
+ onMounted(() => {
1822
+ if (!componentId) return;
1823
+ unregisterQuickActionTarget = registerQuickActionTarget({
1824
+ path: route.path,
1825
+ componentId,
1826
+ run: runQuickActionIntent,
1827
+ });
1828
+ });
1829
+ onBeforeUnmount(() => unregisterQuickActionTarget?.());
1830
+
1005
1831
  defineShortcuts(
1006
1832
  buildTableViewShortcuts({
1007
1833
  refresh: refreshAll,
@@ -1016,13 +1842,16 @@ defineShortcuts(
1016
1842
 
1017
1843
  const tableStatePreferences = {
1018
1844
  sorting,
1019
- pagination,
1845
+ pagination: paginationState,
1020
1846
  columnFilters: columnFilters,
1021
1847
  columnVisibility,
1022
1848
  filtersOpen: filtersRowOpen,
1023
1849
  activeTab: activeTabId,
1024
1850
  viewMode: activeDisplayId,
1851
+ columnOrder,
1025
1852
  kanbanGroupBy,
1853
+ groupedGroupBy,
1854
+ density,
1026
1855
  } as const;
1027
1856
 
1028
1857
  Object.entries(tableStatePreferences).forEach(([key, ref]) => {
@@ -1087,7 +1916,7 @@ if (componentId) {
1087
1916
  TableViewEvents.ROW_SELECT,
1088
1917
  componentId,
1089
1918
  (selection) => ({
1090
- selectedIds: Object.keys(selection).filter((key) => selection[key]),
1919
+ selectedIds: selectedRowIds(selection),
1091
1920
  }),
1092
1921
  );
1093
1922
  }
@@ -1103,10 +1932,14 @@ const checkUrlParameter = () => {
1103
1932
 
1104
1933
  onMounted(() => {
1105
1934
  checkUrlParameter();
1935
+ void openRecordFromUrl();
1936
+ void loadRelationQuickFilters();
1937
+ void refreshLinkTabCounts();
1106
1938
  // The registry is client-only; once hydrated, degrade to the table display if
1107
1939
  // the active id is no longer available (e.g. kanban with no eligible column).
1108
1940
  if (
1109
1941
  activeDisplayId.value !== TABLE_DISPLAY_ID &&
1942
+ !isConfigRenderedDisplay(activeDisplayId.value) &&
1110
1943
  !availableDisplays.value.some((d) => d.id === activeDisplayId.value)
1111
1944
  ) {
1112
1945
  activeDisplayId.value = TABLE_DISPLAY_ID;
@@ -1117,34 +1950,56 @@ onMounted(() => {
1117
1950
  <template>
1118
1951
  <UTable
1119
1952
  v-bind="tableProps"
1120
- v-model:pagination="pagination"
1953
+ v-model:pagination="paginationState"
1121
1954
  v-model:global-filter="globalFilter"
1122
1955
  v-model:sorting="sorting"
1123
1956
  v-model:row-selection="rowSelect"
1124
1957
  v-model:column-filters="columnFilters"
1125
1958
  v-model:column-visibility="columnVisibility"
1126
1959
  v-model:column-sizing="columnSizing"
1960
+ v-model:column-order-state="columnOrder"
1127
1961
  v-model:filters-row-open="filtersRowOpen"
1128
1962
  v-model:active-tab="activeTabId"
1129
1963
  v-model:active-display="activeDisplayId"
1130
1964
  v-model:kanban-group-by="kanbanGroupBy"
1965
+ v-model:grouped-group-by="groupedGroupBy"
1966
+ v-model:show-archived="showArchived"
1967
+ v-model:expanded="expandedModel"
1968
+ v-model:density="density"
1969
+ :chrome="resolvedChrome"
1970
+ :grouping="grouping"
1971
+ :accumulation="accumulation"
1972
+ :reorder="reorderState"
1973
+ :views-placement="viewsLayout === 'menu' ? 'header' : 'band'"
1974
+ :search-placeholder="props.searchPlaceholder"
1975
+ :quick-filters="resolvedQuickFilters"
1976
+ :footer="resolvedFooter"
1977
+ :empty-states="props.emptyStates"
1978
+ :default-page-size="props.pageSize"
1979
+ :archive-toggle="canToggleArchived"
1131
1980
  :displays="availableDisplays"
1132
1981
  :active-capabilities="activeCapabilities"
1133
1982
  :kanban-group-by-options="kanbanGroupByOptions"
1983
+ :grouped-group-by-options="groupedGroupByOptions"
1134
1984
  :tabs="tabsWithCount"
1135
1985
  :initial-column-visibility="initialVisibility"
1136
- :loading="status === 'pending'"
1986
+ :loading="isListLoading"
1137
1987
  :load-error="listLoadError"
1138
1988
  :data="shownResults || []"
1139
1989
  :pagination-options="{ manualPagination: true, rowCount: data?.total }"
1140
1990
  :sorting-options="{ manualSorting: true }"
1991
+ :default-sort="tableDefaultSort"
1992
+ :default-sort-label="defaultSortLabel"
1993
+ :default-sort-kind="defaultSortKind"
1141
1994
  :global-filter-options="{ enableGlobalFilter: false }"
1142
1995
  :columns="listableColumns"
1143
1996
  :custom-nav-items="customNavItems"
1144
1997
  :custom-buttons="customButtons"
1145
- :enable-export="enableTableExport"
1998
+ :can-export="enableTableExport"
1146
1999
  :on-custom-button="handleCustomButton"
1147
2000
  :on-custom-row-action="handleCustomRowAction"
2001
+ :bulk-actions="bulkCustomActions"
2002
+ v-model:all-matching="allMatching"
1148
2003
  :presence-by-row="presenceByRowFiltered"
1149
2004
  @add="handleRowAdd"
1150
2005
  @refresh="refreshAll"
@@ -1153,9 +2008,34 @@ onMounted(() => {
1153
2008
  @archive="(e) => archiveRows(e)"
1154
2009
  @restore="(e) => restoreRows(e)"
1155
2010
  @export="handleExportSelection"
2011
+ @export-all="handleExportTable"
2012
+ @bulk-action="runBulkAction"
1156
2013
  @duplicate="handleRowDuplicate"
1157
2014
  @edit="handleRowEdit"
1158
2015
  >
2016
+ <template v-if="hasViews" #views>
2017
+ <TableViews
2018
+ :items="viewItems"
2019
+ :active-id="activeViewId"
2020
+ :layout="viewsLayout"
2021
+ :modified="isViewModified"
2022
+ :can-save-as="canSaveViews"
2023
+ :divided="tabsWithCount.length === 0"
2024
+ @open="openView"
2025
+ @reset="resetView"
2026
+ @save="saveView"
2027
+ @save-as="saveAsNewView"
2028
+ @delete="deleteView"
2029
+ />
2030
+ </template>
2031
+ <template v-if="expandableConfig" #expanded="{ row }">
2032
+ <ExpandedRowDetail
2033
+ :row-props="expandedRowProps(row.original)"
2034
+ :config="expandableConfig"
2035
+ :load-state="expandedRowLoadState(row.id)"
2036
+ @retry="expandedDetails.load(row.id)"
2037
+ />
2038
+ </template>
1159
2039
  <template
1160
2040
  v-if="activeDisplayComponent && !activeDisplayBlockedByError"
1161
2041
  #body="{ table }"