@antelopejs/dms 0.9.8 → 0.10.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 (420) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/README.md +1 -1
  3. package/data/module-store/catalog.json +2 -2
  4. package/dist/attachments/table-view.js +2 -2
  5. package/dist/attachments/table-view.js.map +1 -1
  6. package/dist/automation/actions.d.ts +2 -0
  7. package/dist/automation/actions.js +116 -71
  8. package/dist/automation/actions.js.map +1 -1
  9. package/dist/automation/i18n.d.ts +4 -0
  10. package/dist/automation/i18n.js +19 -0
  11. package/dist/automation/i18n.js.map +1 -0
  12. package/dist/automation/send-notification.d.ts +21 -0
  13. package/dist/automation/send-notification.js +163 -0
  14. package/dist/automation/send-notification.js.map +1 -0
  15. package/dist/automation/triggers.js +19 -25
  16. package/dist/automation/triggers.js.map +1 -1
  17. package/dist/client-origin-cors.d.ts +1 -0
  18. package/dist/client-origin-cors.js +19 -0
  19. package/dist/client-origin-cors.js.map +1 -0
  20. package/dist/config.d.ts +3 -0
  21. package/dist/config.js +5 -3
  22. package/dist/config.js.map +1 -1
  23. package/dist/frontend-module.d.ts +4 -0
  24. package/dist/frontend-module.js +37 -0
  25. package/dist/frontend-module.js.map +1 -0
  26. package/dist/implementations/dms/client-ip.js +1 -1
  27. package/dist/implementations/dms/client-ip.js.map +1 -1
  28. package/dist/implementations/dms/dev-reload.d.ts +5 -0
  29. package/dist/implementations/dms/dev-reload.js +23 -3
  30. package/dist/implementations/dms/dev-reload.js.map +1 -1
  31. package/dist/implementations/dms/frontend-modules.d.ts +2 -4
  32. package/dist/implementations/dms/frontend-modules.js +22 -89
  33. package/dist/implementations/dms/frontend-modules.js.map +1 -1
  34. package/dist/implementations/dms/frontend-ready.d.ts +12 -2
  35. package/dist/implementations/dms/frontend-ready.js +34 -4
  36. package/dist/implementations/dms/frontend-ready.js.map +1 -1
  37. package/dist/implementations/dms/layout-banners.d.ts +2 -1
  38. package/dist/implementations/dms/layout-banners.js +9 -0
  39. package/dist/implementations/dms/layout-banners.js.map +1 -1
  40. package/dist/implementations/dms/manifest.d.ts +1 -2
  41. package/dist/implementations/dms/manifest.js +2 -0
  42. package/dist/implementations/dms/manifest.js.map +1 -1
  43. package/dist/implementations/dms/page.d.ts +4 -3
  44. package/dist/implementations/dms/page.js +49 -18
  45. package/dist/implementations/dms/page.js.map +1 -1
  46. package/dist/implementations/dms/permissions-resolver.d.ts +2 -2
  47. package/dist/implementations/dms/permissions-resolver.js +2 -2
  48. package/dist/implementations/dms/permissions-resolver.js.map +1 -1
  49. package/dist/implementations/dms/realtime.js +1 -0
  50. package/dist/implementations/dms/realtime.js.map +1 -1
  51. package/dist/implementations/dms-base/bulk-selection.d.ts +1 -1
  52. package/dist/implementations/dms-base/bulk-selection.js +23 -1
  53. package/dist/implementations/dms-base/bulk-selection.js.map +1 -1
  54. package/dist/implementations/dms-base/filter-tokens.js +5 -3
  55. package/dist/implementations/dms-base/filter-tokens.js.map +1 -1
  56. package/dist/implementations/dms-base/search-route.d.ts +1 -0
  57. package/dist/implementations/dms-base/search-route.js +35 -13
  58. package/dist/implementations/dms-base/search-route.js.map +1 -1
  59. package/dist/implementations/dms-base/table-view.js +11 -6
  60. package/dist/implementations/dms-base/table-view.js.map +1 -1
  61. package/dist/implementations/dms-notifications/index.d.ts +2 -2
  62. package/dist/implementations/dms-notifications/index.js +5 -5
  63. package/dist/implementations/dms-notifications/index.js.map +1 -1
  64. package/dist/index.js +28 -48
  65. package/dist/index.js.map +1 -1
  66. package/dist/pages/modules/index.d.ts +1 -0
  67. package/dist/pages/modules/index.js +1 -0
  68. package/dist/pages/modules/index.js.map +1 -1
  69. package/dist/pages/modules/modules-store.d.ts +9 -0
  70. package/dist/pages/modules/modules-store.js +30 -0
  71. package/dist/pages/modules/modules-store.js.map +1 -0
  72. package/dist/pages/settings/users/account-credentials.js +2 -2
  73. package/dist/pages/settings/users/account-credentials.js.map +1 -1
  74. package/dist/pages/settings/users/account-data-store.js +25 -8
  75. package/dist/pages/settings/users/account-data-store.js.map +1 -1
  76. package/dist/pages/settings/users/invite-extension-routes.js +9 -3
  77. package/dist/pages/settings/users/invite-extension-routes.js.map +1 -1
  78. package/dist/pages/settings/users/member-management.js +13 -14
  79. package/dist/pages/settings/users/member-management.js.map +1 -1
  80. package/dist/pages/settings/users/profile.d.ts +1 -4
  81. package/dist/pages/settings/users/profile.js +0 -35
  82. package/dist/pages/settings/users/profile.js.map +1 -1
  83. package/dist/pages/settings/users/role-editor-store.js +26 -18
  84. package/dist/pages/settings/users/role-editor-store.js.map +1 -1
  85. package/dist/pages/settings/users/role-editor.d.ts +0 -1
  86. package/dist/pages/settings/users/role-editor.js +1 -2
  87. package/dist/pages/settings/users/role-editor.js.map +1 -1
  88. package/dist/pages/settings/users/role-preview.js +1 -2
  89. package/dist/pages/settings/users/role-preview.js.map +1 -1
  90. package/dist/pages/settings/users/roles.js +2 -2
  91. package/dist/pages/settings/users/roles.js.map +1 -1
  92. package/dist/pages/settings/users/two-factor-operations.js.map +1 -1
  93. package/dist/realtime/broker.d.ts +6 -0
  94. package/dist/realtime/broker.js +8 -1
  95. package/dist/realtime/broker.js.map +1 -1
  96. package/dist/realtime/presence.d.ts +8 -3
  97. package/dist/realtime/presence.js +8 -4
  98. package/dist/realtime/presence.js.map +1 -1
  99. package/dist/realtime/sessions.d.ts +11 -1
  100. package/dist/realtime/sessions.js +21 -3
  101. package/dist/realtime/sessions.js.map +1 -1
  102. package/dist/realtime/table-view.d.ts +2 -2
  103. package/dist/realtime/table-view.js +4 -3
  104. package/dist/realtime/table-view.js.map +1 -1
  105. package/dist/routes/auth/client-ip.d.ts +1 -0
  106. package/dist/routes/auth/client-ip.js +18 -0
  107. package/dist/routes/auth/client-ip.js.map +1 -1
  108. package/dist/routes/auth/oauth/config.d.ts +2 -1
  109. package/dist/routes/auth/oauth/config.js +5 -1
  110. package/dist/routes/auth/oauth/config.js.map +1 -1
  111. package/dist/routes/auth/session-handoff.d.ts +0 -1
  112. package/dist/routes/auth/session-handoff.js +0 -2
  113. package/dist/routes/auth/session-handoff.js.map +1 -1
  114. package/dist/routes/auth.js +3 -2
  115. package/dist/routes/auth.js.map +1 -1
  116. package/dist/routes/index.d.ts +0 -1
  117. package/dist/routes/index.js +0 -1
  118. package/dist/routes/index.js.map +1 -1
  119. package/dist/routes/realtime.d.ts +13 -1
  120. package/dist/routes/realtime.js +114 -29
  121. package/dist/routes/realtime.js.map +1 -1
  122. package/dist/startup-config.d.ts +2 -0
  123. package/dist/startup-config.js +62 -0
  124. package/dist/startup-config.js.map +1 -0
  125. package/dist/store/interfaces.d.ts +3 -2
  126. package/dist/store/interfaces.js +16 -6
  127. package/dist/store/interfaces.js.map +1 -1
  128. package/dist/store/listing.js +24 -13
  129. package/dist/store/listing.js.map +1 -1
  130. package/dist/store/operations.js +4 -0
  131. package/dist/store/operations.js.map +1 -1
  132. package/dist/store/requirements.js +3 -2
  133. package/dist/store/requirements.js.map +1 -1
  134. package/dist/store/runtime.d.ts +10 -1
  135. package/dist/store/runtime.js +33 -6
  136. package/dist/store/runtime.js.map +1 -1
  137. package/dist/store/types.d.ts +10 -0
  138. package/dist/validation/auth.schema.d.ts +2 -2
  139. package/dist/validation/member-invite.schema.d.ts +2 -10
  140. package/dist/validation/member-invite.schema.js +2 -15
  141. package/dist/validation/member-invite.schema.js.map +1 -1
  142. package/frontend-vue/dms.frontend.ts +24 -5
  143. package/frontend-vue/dms.server.ts +17 -0
  144. package/frontend-vue/layers/dms-auth/server/accounts.ts +3 -4
  145. package/frontend-vue/layers/dms-core/app/build/composables/renderNow.ts +34 -0
  146. package/frontend-vue/layers/dms-core/app/build/composables/user/tablePreferences.ts +5 -1
  147. package/frontend-vue/layers/dms-core/app/build/utils/crossTab.ts +199 -0
  148. package/frontend-vue/layers/dms-core/app/build/utils/sharedRealtimeConnection.ts +410 -0
  149. package/frontend-vue/layers/dms-core/app/composables/auth/useApiData.ts +77 -12
  150. package/frontend-vue/layers/dms-core/app/composables/data-types/useDataType.ts +26 -0
  151. package/frontend-vue/layers/dms-core/app/composables/hydration/isHydratingComponent.ts +29 -0
  152. package/frontend-vue/layers/dms-core/app/composables/live/livePauseSource.ts +29 -0
  153. package/frontend-vue/layers/dms-core/app/composables/period/compareResolvers.ts +150 -9
  154. package/frontend-vue/layers/dms-core/app/composables/period/usePeriod.ts +6 -4
  155. package/frontend-vue/layers/dms-core/app/composables/period/usePeriodScope.ts +27 -1
  156. package/frontend-vue/layers/dms-core/app/composables/realtime/useUserRealtime.ts +256 -119
  157. package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +21 -8
  158. package/frontend-vue/layers/dms-core/app/composables/translation/useTranslation.ts +22 -5
  159. package/frontend-vue/layers/dms-core/app/plugins/dev-error-log.ts +16 -0
  160. package/frontend-vue/layers/dms-core/app/types/user.ts +6 -0
  161. package/frontend-vue/layers/dms-core/app/utils/composedText.ts +7 -2
  162. package/frontend-vue/layers/dms-core/app/utils/formatter.ts +166 -35
  163. package/frontend-vue/layers/dms-core/app/utils/url-interpolation.ts +18 -1
  164. package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +134 -2
  165. package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +134 -2
  166. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +3 -2
  167. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +41 -21
  168. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardPageBody.vue +9 -0
  169. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidebar.vue +4 -19
  170. package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +11 -3
  171. package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +18 -7
  172. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionBar.vue +8 -0
  173. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionsOutlet.vue +14 -0
  174. package/frontend-vue/layers/dms-layout/app/build/components/layout/RowSidePanel.vue +43 -82
  175. package/frontend-vue/layers/dms-layout/app/build/components/layout/SidebarUserMenu.vue +44 -3
  176. package/frontend-vue/layers/dms-layout/app/build/components/layout/UserIdentity.vue +11 -3
  177. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleCatalogTile.vue +132 -35
  178. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleManageMenu.vue +59 -0
  179. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleSourceLabel.vue +25 -0
  180. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreBanners.vue +73 -0
  181. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreOperation.vue +116 -0
  182. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreRequirements.vue +8 -3
  183. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreTile.vue +85 -207
  184. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTile.vue +10 -3
  185. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTileSkeleton.vue +68 -0
  186. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxDisplay.vue +24 -8
  187. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxItem.vue +8 -5
  188. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionTimeZoneInput.vue +1 -0
  189. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +19 -0
  190. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRoleEditor.ts +2 -1
  191. package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +31 -70
  192. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +11 -1
  193. package/frontend-vue/layers/dms-layout/app/build/utils/dev-reload-stream.ts +81 -0
  194. package/frontend-vue/layers/dms-layout/app/build/utils/module-store-catalog.ts +232 -36
  195. package/frontend-vue/layers/dms-layout/app/build/utils/modules-catalog.ts +122 -14
  196. package/frontend-vue/layers/dms-layout/app/composables/layout/useLayoutBanners.ts +32 -3
  197. package/frontend-vue/layers/dms-layout/app/composables/layout/usePageRecord.ts +50 -0
  198. package/frontend-vue/layers/dms-layout/app/composables/layout/useServedHeaderActions.ts +25 -7
  199. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleHistory.ts +3 -2
  200. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStore.ts +51 -4
  201. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStoreActions.ts +194 -0
  202. package/frontend-vue/layers/dms-layout/app/composables/page/usePageComponentPreload.ts +23 -3
  203. package/frontend-vue/layers/dms-layout/app/composables/page/usePageLayout.ts +4 -2
  204. package/frontend-vue/layers/dms-layout/app/composables/page/useSiteLayout.ts +6 -1
  205. package/frontend-vue/layers/dms-layout/app/custom-layouts/DefaultLayout.vue +9 -0
  206. package/frontend-vue/layers/dms-layout/app/custom-layouts/SettingsLayout.vue +9 -0
  207. package/frontend-vue/layers/dms-layout/app/custom-pages/modules-store.vue +291 -0
  208. package/frontend-vue/layers/dms-layout/app/custom-pages/modules.vue +87 -474
  209. package/frontend-vue/layers/dms-layout/app/middleware/module-routing.global.ts +3 -0
  210. package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +6 -22
  211. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-navigation.client.ts +2 -1
  212. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-personal-pages.client.ts +14 -44
  213. package/frontend-vue/layers/dms-layout/app/plugins/dms-dev-reload.client.ts +14 -9
  214. package/frontend-vue/layers/dms-layout/app/theme/form-controls.ts +9 -4
  215. package/frontend-vue/layers/dms-layout/app/theme/surfaces.ts +22 -6
  216. package/frontend-vue/layers/dms-layout/app/types/module-store.ts +9 -0
  217. package/frontend-vue/layers/dms-layout/app/types/page.ts +15 -1
  218. package/frontend-vue/layers/dms-layout/app/utils/account-menu.ts +11 -0
  219. package/frontend-vue/layers/dms-layout/app/utils/breadcrumb.ts +57 -0
  220. package/frontend-vue/layers/dms-layout/app/utils/pageQuery.ts +26 -0
  221. package/frontend-vue/layers/dms-layout/app/utils/pageRecord.ts +71 -0
  222. package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +39 -14
  223. package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +38 -13
  224. package/frontend-vue/layers/dms-ui/app/build/components/containers/TargetComponentTree.vue +31 -0
  225. package/frontend-vue/layers/dms-ui/app/build/components/containers/constants.ts +25 -0
  226. package/frontend-vue/layers/dms-ui/app/build/components/containers/drawer/DynamicDrawer.vue +244 -15
  227. package/frontend-vue/layers/dms-ui/app/build/components/containers/modal/DynamicModal.vue +42 -25
  228. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowHeader.vue +153 -0
  229. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowNotFound.vue +44 -0
  230. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/drawerRowHeader.ts +35 -0
  231. package/frontend-vue/layers/dms-ui/app/build/components/form/FormEntries.vue +44 -9
  232. package/frontend-vue/layers/dms-ui/app/build/components/form/FormErrorSummary.vue +11 -4
  233. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldControl.vue +38 -5
  234. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldNotes.vue +29 -5
  235. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSectionNav.vue +3 -1
  236. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSections.vue +106 -27
  237. package/frontend-vue/layers/dms-ui/app/build/components/table/Actions.vue +12 -4
  238. package/frontend-vue/layers/dms-ui/app/build/components/table/Empty.vue +4 -2
  239. package/frontend-vue/layers/dms-ui/app/build/components/table/FiltersRow.vue +38 -1
  240. package/frontend-vue/layers/dms-ui/app/build/components/table/Pagination.vue +55 -54
  241. package/frontend-vue/layers/dms-ui/app/build/components/table/RowSelection.vue +2 -1
  242. package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +396 -288
  243. package/frontend-vue/layers/dms-ui/app/build/components/table/Tabs.vue +2 -1
  244. package/frontend-vue/layers/dms-ui/app/build/components/table/Views.vue +2 -1
  245. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardAvatar.vue +59 -0
  246. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardGridSkeleton.vue +19 -2
  247. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardRowActions.vue +38 -0
  248. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +148 -104
  249. package/frontend-vue/layers/dms-ui/app/build/components/table-view/LiveHoldBanner.vue +17 -2
  250. package/frontend-vue/layers/dms-ui/app/build/composables/actions/bulkSelection.ts +43 -9
  251. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowComponentOptions.ts +76 -0
  252. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +172 -27
  253. package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +270 -46
  254. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/confirmDialogTexts.ts +2 -0
  255. package/frontend-vue/layers/dms-ui/app/build/composables/containers/closingLayers.ts +186 -0
  256. package/frontend-vue/layers/dms-ui/app/build/composables/containers/context.ts +14 -0
  257. package/frontend-vue/layers/dms-ui/app/build/composables/containers/drawerSize.ts +229 -0
  258. package/frontend-vue/layers/dms-ui/app/build/composables/containers/useResizableSize.ts +175 -0
  259. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +18 -35
  260. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/numberSuffix.ts +47 -0
  261. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +99 -24
  262. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerFieldTypes.ts +2 -1
  263. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationFilter.ts +75 -0
  264. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationRows.ts +71 -0
  265. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationValue.ts +39 -0
  266. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +3 -3
  267. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +6 -2
  268. package/frontend-vue/layers/dms-ui/app/build/composables/form/createFormFields.ts +15 -0
  269. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldSaved.ts +40 -0
  270. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldValueRule.ts +62 -0
  271. package/frontend-vue/layers/dms-ui/app/build/composables/form/formEntryContext.ts +5 -0
  272. package/frontend-vue/layers/dms-ui/app/build/composables/form/formFooter.ts +42 -7
  273. package/frontend-vue/layers/dms-ui/app/build/composables/form/formLayout.ts +106 -4
  274. package/frontend-vue/layers/dms-ui/app/build/composables/form/formSections.ts +32 -0
  275. package/frontend-vue/layers/dms-ui/app/build/composables/form/readonlyValue.ts +19 -0
  276. package/frontend-vue/layers/dms-ui/app/build/composables/form/registerFormFunctions.ts +27 -0
  277. package/frontend-vue/layers/dms-ui/app/build/composables/form/repeaterTable.ts +65 -0
  278. package/frontend-vue/layers/dms-ui/app/build/composables/form/serverFieldErrors.ts +49 -0
  279. package/frontend-vue/layers/dms-ui/app/build/composables/form/toasterClearance.ts +118 -0
  280. package/frontend-vue/layers/dms-ui/app/build/composables/form/useInstantForm.ts +12 -1
  281. package/frontend-vue/layers/dms-ui/app/build/composables/live/currentPageLive.ts +41 -3
  282. package/frontend-vue/layers/dms-ui/app/build/composables/live/livePoller.ts +10 -2
  283. package/frontend-vue/layers/dms-ui/app/build/composables/live/pageReadClock.ts +28 -0
  284. package/frontend-vue/layers/dms-ui/app/build/composables/live/shortcuts.ts +1 -1
  285. package/frontend-vue/layers/dms-ui/app/build/composables/live/usePageLiveHost.ts +17 -3
  286. package/frontend-vue/layers/dms-ui/app/build/composables/live/useUpdatedLabel.ts +38 -0
  287. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/pageToolbarContext.ts +75 -0
  288. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/toolbarControlHeight.ts +29 -0
  289. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodComparison.ts +52 -0
  290. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodDisplay.ts +21 -0
  291. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodShortLabels.ts +28 -0
  292. package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodDraft.ts +1 -0
  293. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRelationFilterLabels.ts +73 -0
  294. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRowScrollAnchor.ts +106 -0
  295. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +9 -0
  296. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableColumns.ts +1 -2
  297. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/archivedCount.ts +31 -0
  298. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/filterEditorValue.ts +38 -0
  299. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/formatFilterValue.ts +33 -2
  300. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/scrollEdges.ts +31 -0
  301. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useCardFields.ts +33 -0
  302. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useMobileDisplay.ts +48 -0
  303. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useScrolledPastTop.ts +41 -18
  304. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableFooter.ts +3 -2
  305. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLinkedVisit.ts +78 -0
  306. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLiveHold.ts +135 -22
  307. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +56 -25
  308. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +77 -32
  309. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViews.ts +86 -10
  310. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/bulkActions.ts +14 -4
  311. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/card.ts +127 -2
  312. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/compareValues.ts +13 -0
  313. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/expandedRows.ts +28 -0
  314. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/groupedRows.ts +114 -1
  315. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/linkedArrival.ts +308 -0
  316. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/locateRow.ts +106 -0
  317. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pageArrival.ts +34 -0
  318. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pinnedRows.ts +17 -0
  319. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/quickFilters.ts +41 -33
  320. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +24 -8
  321. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableCounts.ts +113 -0
  322. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableQuery.ts +27 -4
  323. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +22 -6
  324. package/frontend-vue/layers/dms-ui/app/build/utils/addressSuggestions.ts +49 -0
  325. package/frontend-vue/layers/dms-ui/app/build/utils/eyebrow.ts +12 -0
  326. package/frontend-vue/layers/dms-ui/app/build/utils/fieldOptionsI18n.ts +51 -11
  327. package/frontend-vue/layers/dms-ui/app/build/utils/inputWidth.ts +53 -0
  328. package/frontend-vue/layers/dms-ui/app/build/utils/numberAdjustment.ts +6 -3
  329. package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +19 -5
  330. package/frontend-vue/layers/dms-ui/app/build/utils/scrollWithin.ts +99 -0
  331. package/frontend-vue/layers/dms-ui/app/build/utils/urlVariables.ts +36 -14
  332. package/frontend-vue/layers/dms-ui/app/components/PasswordStrength.vue +1 -1
  333. package/frontend-vue/layers/dms-ui/app/components/RecursiveComponent.vue +9 -1
  334. package/frontend-vue/layers/dms-ui/app/components/blocks/LiveToggleBlock.vue +80 -32
  335. package/frontend-vue/layers/dms-ui/app/components/blocks/PageToolbarBlock.vue +137 -0
  336. package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +5 -0
  337. package/frontend-vue/layers/dms-ui/app/components/chart/ApexChartHost.vue +16 -2
  338. package/frontend-vue/layers/dms-ui/app/components/chart/Chart.vue +24 -5
  339. package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +41 -23
  340. package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +1 -1
  341. package/frontend-vue/layers/dms-ui/app/components/container-footer/ContainerFooter.vue +34 -0
  342. package/frontend-vue/layers/dms-ui/app/components/field-row/FieldRow.vue +25 -2
  343. package/frontend-vue/layers/dms-ui/app/components/flow-canvas/FlowCanvas.vue +2 -2
  344. package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +118 -36
  345. package/frontend-vue/layers/dms-ui/app/components/form/components/DatePicker.vue +20 -1
  346. package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +13 -1
  347. package/frontend-vue/layers/dms-ui/app/components/form/components/Image.vue +8 -3
  348. package/frontend-vue/layers/dms-ui/app/components/form/components/InputAddress.vue +53 -5
  349. package/frontend-vue/layers/dms-ui/app/components/form/components/InputCode.vue +29 -5
  350. package/frontend-vue/layers/dms-ui/app/components/form/components/InputNumber.vue +45 -8
  351. package/frontend-vue/layers/dms-ui/app/components/form/components/InputPercentage.vue +28 -5
  352. package/frontend-vue/layers/dms-ui/app/components/form/components/InputSecret.vue +5 -0
  353. package/frontend-vue/layers/dms-ui/app/components/form/components/InputText.vue +19 -2
  354. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTime.vue +2 -1
  355. package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +205 -65
  356. package/frontend-vue/layers/dms-ui/app/components/form/components/Repeater.vue +80 -30
  357. package/frontend-vue/layers/dms-ui/app/components/form/components/RepeaterTable.vue +203 -0
  358. package/frontend-vue/layers/dms-ui/app/components/form/components/Select.vue +4 -2
  359. package/frontend-vue/layers/dms-ui/app/components/grid/GridRow.vue +11 -2
  360. package/frontend-vue/layers/dms-ui/app/components/key-value-list/KeyValueList.vue +79 -70
  361. package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +117 -21
  362. package/frontend-vue/layers/dms-ui/app/components/meter/Meter.vue +2 -1
  363. package/frontend-vue/layers/dms-ui/app/components/period/PeriodSelector.vue +113 -34
  364. package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +14 -2
  365. package/frontend-vue/layers/dms-ui/app/components/section-header/Eyebrow.vue +6 -1
  366. package/frontend-vue/layers/dms-ui/app/components/segmented/Segmented.vue +13 -0
  367. package/frontend-vue/layers/dms-ui/app/components/stat-group/StatGroup.vue +52 -3
  368. package/frontend-vue/layers/dms-ui/app/components/tab/Tab.vue +2 -1
  369. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanBoard.vue +45 -35
  370. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanDisplay.vue +4 -1
  371. package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +410 -96
  372. package/frontend-vue/layers/dms-ui/app/components/top-list/TopListCard.vue +33 -5
  373. package/frontend-vue/layers/dms-ui/app/composables/chart/apexCategoryLabels.ts +68 -0
  374. package/frontend-vue/layers/dms-ui/app/composables/chart/apexDatetimeBuckets.ts +306 -0
  375. package/frontend-vue/layers/dms-ui/app/composables/chart/formatValue.ts +4 -3
  376. package/frontend-vue/layers/dms-ui/app/composables/chart/heatmapColors.ts +93 -0
  377. package/frontend-vue/layers/dms-ui/app/composables/chart/localizeSeries.ts +62 -0
  378. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.ts +116 -8
  379. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.types.ts +7 -0
  380. package/frontend-vue/layers/dms-ui/app/composables/containers/types.ts +84 -1
  381. package/frontend-vue/layers/dms-ui/app/composables/containers/useDrawer.ts +69 -8
  382. package/frontend-vue/layers/dms-ui/app/composables/form/types/field-saved.ts +11 -0
  383. package/frontend-vue/layers/dms-ui/app/composables/form/types/field.ts +4 -0
  384. package/frontend-vue/layers/dms-ui/app/composables/form/types/functions.ts +1 -0
  385. package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +142 -21
  386. package/frontend-vue/layers/dms-ui/app/composables/live/usePageLive.ts +11 -4
  387. package/frontend-vue/layers/dms-ui/app/composables/page-toolbar/usePageToolbarSize.ts +30 -0
  388. package/frontend-vue/layers/dms-ui/app/composables/table-view/kanban.ts +4 -2
  389. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +22 -3
  390. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +4 -0
  391. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +24 -1
  392. package/frontend-vue/layers/dms-ui/app/plugins/closing-layers.client.ts +10 -0
  393. package/frontend-vue/layers/dms-ui/app/plugins/live-pause-source.ts +15 -0
  394. package/frontend-vue/layers/dms-ui/app/plugins/register.ts +2 -0
  395. package/frontend-vue/layers/dms-ui/app/types/input-number.ts +3 -2
  396. package/frontend-vue/layers/dms-ui/app/types/page-toolbar.ts +7 -0
  397. package/frontend-vue/layers/dms-ui/app/types/row-action.ts +0 -2
  398. package/frontend-vue/layers/dms-ui/app/types/row-navigation.ts +17 -0
  399. package/frontend-vue/layers/dms-ui/app/types/table/query.ts +2 -1
  400. package/frontend-vue/layers/dms-ui/app/utils/blockRefresh.ts +3 -1
  401. package/frontend-vue/layers/dms-ui/app/utils/componentTree.ts +24 -0
  402. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +16 -4
  403. package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +16 -4
  404. package/frontend-vue/package.json +2 -2
  405. package/package.json +7 -6
  406. package/skills/dms/SKILL.md +1 -1
  407. package/skills/dms-auth/SKILL.md +5 -3
  408. package/skills/dms-best-practices/REFERENCE.md +2 -0
  409. package/skills/dms-best-practices/SKILL.md +4 -0
  410. package/skills/dms-module/SKILL.md +3 -2
  411. package/skills/dms-pages/REFERENCE.md +125 -16
  412. package/skills/dms-pages/SKILL.md +1 -1
  413. package/skills/dms-project/DEV-SERVERS.md +23 -1
  414. package/skills/dms-project/REFERENCE.md +1 -1
  415. package/skills/dms-project/SKILL.md +4 -1
  416. package/skills/dms-project/scripts/dms-dev.sh +205 -17
  417. package/dist/routes/startup-gate.d.ts +0 -7
  418. package/dist/routes/startup-gate.js +0 -39
  419. package/dist/routes/startup-gate.js.map +0 -1
  420. package/frontend-vue/layers/dms-core/app/composables/period/periodRenderNow.ts +0 -42
@@ -5,6 +5,7 @@ import { useDevReloading } from "../build/composables/dev-reload/useDevReloadHol
5
5
  import { usePageLiveHost } from "#dms-ui/app/build/composables/live/usePageLiveHost";
6
6
  import { usePageDataRefresh } from "#dms-ui/app/build/composables/live/usePageDataRefresh";
7
7
  import { pageValidationRedirect } from "../build/utils/pageValidationRedirect";
8
+ import { resolveComponentChildren } from "#dms-ui/app/utils/componentTree";
8
9
 
9
10
  defineOptions({ inheritAttrs: false });
10
11
 
@@ -215,9 +216,10 @@ if (import.meta.env.DEV) {
215
216
 
216
217
  const { pageLayout } = await usePageLayout();
217
218
 
218
- watch(pageLayout, (layout) => preloadPageLayoutComponents(layout), {
219
- immediate: true,
220
- });
219
+ // A client navigation shows the page once its blocks' code is there: a lazy
220
+ // block draws nothing until its chunk lands, then pushes the page down.
221
+ await preloadPageLayoutComponents(pageLayout.value);
222
+ watch(pageLayout, (layout) => void preloadPageLayoutComponents(layout));
221
223
 
222
224
  const { refreshIfStale: refreshPermissionsIfStale } = usePermissions();
223
225
 
@@ -345,24 +347,6 @@ watch(
345
347
  onMounted(runPageSetup);
346
348
  onUnmounted(tearDownPageSetup);
347
349
 
348
- const processChildren = (
349
- children: ComponentChild[],
350
- ): ResolvedComponentInfo[] => {
351
- return children.map((child) => {
352
- const { id, component, ...additionalProps } = child;
353
- return {
354
- id,
355
- options: component.options,
356
- component: component.componentName
357
- ? resolveDmsComponent(component.componentName) || "div"
358
- : "div",
359
- componentName: component.componentName,
360
- children: component.children ? processChildren(component.children) : [],
361
- ...additionalProps,
362
- };
363
- });
364
- };
365
-
366
350
  const components = computed(() =>
367
351
  Object.keys(pageLayout.value?.components || {}).map((field) => {
368
352
  const componentInfo = pageLayout.value?.components[field];
@@ -374,7 +358,7 @@ const components = computed(() =>
374
358
  : "div",
375
359
  componentName: componentInfo?.componentName,
376
360
  children: componentInfo?.children
377
- ? processChildren(componentInfo.children)
361
+ ? resolveComponentChildren(componentInfo.children)
378
362
  : [],
379
363
  } as ResolvedComponentInfo;
380
364
  }),
@@ -22,7 +22,8 @@ function collectNavigationItems(
22
22
 
23
23
  const label = resolveI18nKey(translate, child.displayName);
24
24
  const to = buildMenuItemTarget(child);
25
- if (to && child.fullSlug) {
25
+ // The account entries (Settings, Profile) are the session group's.
26
+ if (to && child.fullSlug && !isAccountMenuRoute(to)) {
26
27
  items.push({
27
28
  label,
28
29
  suffix:
@@ -1,14 +1,14 @@
1
- import type { CommandPaletteGroup, CommandPaletteItem } from "@nuxt/ui";
1
+ import type { CommandPaletteGroup } from "@nuxt/ui";
2
+ import {
3
+ type RecentModule,
4
+ recentModules,
5
+ } from "../build/utils/modules-catalog";
2
6
 
3
7
  const PERSONAL_PAGES_SOURCE_ID = "dms-personal-pages";
4
8
  const PERSONAL_PAGES_SOURCE_ORDER = 20;
5
9
  const FAVORITES_GROUP_ID = "favorite-pages";
6
10
  const RECENT_MODULES_GROUP_ID = "recent-modules";
7
11
 
8
- type AccessibleModules = Record<string, ModuleWithAccess> | undefined;
9
-
10
- type PathLabelResolver = (path: string) => string | undefined;
11
-
12
12
  function buildFavoritesGroup(
13
13
  favorites: FavoritePage[],
14
14
  translate: I18nTranslate,
@@ -26,42 +26,20 @@ function buildFavoritesGroup(
26
26
  };
27
27
  }
28
28
 
29
- function buildRecentModuleItem(
30
- entry: ModuleHistoryEntry,
31
- modules: AccessibleModules,
32
- translate: I18nTranslate,
33
- resolvePathLabel: PathLabelResolver,
34
- ): CommandPaletteItem | null {
35
- const module = modules?.[entry.moduleId];
36
- if (!module?.hasAccess) return null;
37
-
38
- return {
39
- label: resolveI18nKey(translate, module.title),
40
- suffix: resolvePathLabel(entry.path),
41
- icon: module.icon,
42
- to: entry.path,
43
- };
44
- }
45
-
46
29
  function buildRecentModulesGroup(
47
- entries: ModuleHistoryEntry[],
48
- modules: AccessibleModules,
30
+ modules: RecentModule[],
49
31
  translate: I18nTranslate,
50
- resolvePathLabel: PathLabelResolver,
51
32
  ): CommandPaletteGroup | null {
52
- const items = entries
53
- .slice()
54
- .reverse()
55
- .map((entry) =>
56
- buildRecentModuleItem(entry, modules, translate, resolvePathLabel),
57
- )
58
- .filter((item): item is CommandPaletteItem => item !== null);
59
- if (items.length === 0) return null;
33
+ if (modules.length === 0) return null;
60
34
 
61
35
  return {
62
36
  id: RECENT_MODULES_GROUP_ID,
63
37
  label: translate("commandPalette.groups.recentModules", {}),
64
- items,
38
+ items: modules.map((module) => ({
39
+ label: resolveI18nKey(translate, module.title),
40
+ icon: module.icon,
41
+ to: module.to,
42
+ })),
65
43
  };
66
44
  }
67
45
 
@@ -69,22 +47,14 @@ export default defineDmsPlugin(() => {
69
47
  const { translate } = getPluginI18n();
70
48
  const { sortedFavorites } = useFavoritePages();
71
49
  const { entries } = useModuleHistory();
72
- const { modules, findMatchingRoute } = useSiteLayout();
73
-
74
- const resolvePathLabel: PathLabelResolver = (path) => {
75
- const match = findMatchingRoute(path);
76
- if (!match) return undefined;
77
- return resolveI18nKey(translate, match.metadata.displayName);
78
- };
50
+ const { modules, siteLayoutTree } = useSiteLayout();
79
51
 
80
52
  const groups = computed<CommandPaletteGroup[]>(() =>
81
53
  [
82
54
  buildFavoritesGroup(sortedFavorites.value, translate),
83
55
  buildRecentModulesGroup(
84
- entries.value,
85
- modules.value,
56
+ recentModules(entries.value, modules.value, siteLayoutTree.value),
86
57
  translate,
87
- resolvePathLabel,
88
58
  ),
89
59
  ].filter((group): group is CommandPaletteGroup => group !== null),
90
60
  );
@@ -1,5 +1,5 @@
1
1
  import { useDevReloadHolder } from "../build/composables/dev-reload/useDevReloadHolder";
2
- import { openDevReloadStream } from "../build/utils/dev-reload-stream";
2
+ import { followDevReload } from "../build/utils/dev-reload-stream";
3
3
 
4
4
  const RELOAD_ENDPOINT_PATH = "/dms/dev/reload";
5
5
 
@@ -11,7 +11,7 @@ function resolveBackendBase(): string | null {
11
11
  }
12
12
 
13
13
  /**
14
- * Dev-only: turn the backend's `reload` stream into a soft refresh.
14
+ * Dev-only: turn the backend's reload signal into a soft refresh.
15
15
  *
16
16
  * All the waiting lives in the dev-reload coordinator (see `useDevReloadHolder`), so
17
17
  * this plugin and the `useDevReload().awaitRoute` module frontends call
@@ -25,14 +25,19 @@ export default defineDmsPlugin(() => {
25
25
 
26
26
  const endpoint = `${backendBase}${RELOAD_ENDPOINT_PATH}`;
27
27
  const { coordinator } = useDevReloadHolder();
28
- const stream = openDevReloadStream({
29
- endpoint,
30
- onReload: () => {
31
- void coordinator.requestRefresh().catch((err: unknown) => {
32
- console.error("[dms-dev-reload] Reload handler failed:", err);
33
- });
28
+ // Carried by the user's realtime stream while it is open, by a stream of
29
+ // its own otherwise (the sign-in page).
30
+ const stream = followDevReload(
31
+ {
32
+ endpoint,
33
+ onReload: () => {
34
+ void coordinator.requestRefresh().catch((err: unknown) => {
35
+ console.error("[dms-dev-reload] Reload handler failed:", err);
36
+ });
37
+ },
34
38
  },
35
- });
39
+ useUserRealtime(),
40
+ );
36
41
 
37
42
  if (import.meta.hot) {
38
43
  import.meta.hot.dispose(() => {
@@ -117,11 +117,16 @@ const inputTheme = {
117
117
  ],
118
118
  };
119
119
 
120
- /** Select-like triggers: the input scale with explicit line heights. */
120
+ /**
121
+ * Select-like triggers: the input scale with explicit line heights, so a
122
+ * select is as tall as the text field beside it. Below md they keep the
123
+ * input's 16px (14px for sm), as a text field does, so a form on a phone
124
+ * reads in one size.
125
+ */
121
126
  const SELECT_TRIGGER_SIZES = {
122
- sm: { base: "px-2 text-[12.5px]/4" },
123
- md: { base: "text-[13px]/5" },
124
- xl: { base: "text-[15px]/6" },
127
+ sm: { base: "px-2 text-sm/4 md:text-[12.5px]/4" },
128
+ md: { base: "text-base/5 md:text-[13px]/5" },
129
+ xl: { base: "text-base/6 md:text-[15px]/6" },
125
130
  };
126
131
 
127
132
  /**
@@ -9,6 +9,10 @@
9
9
  */
10
10
 
11
11
  import { EYEBROW_CLASS } from "#dms-ui/app/build/utils/eyebrow";
12
+ import {
13
+ CLOSING_OVERLAY_CLASS,
14
+ UNCOVERED_PANEL_CLASS,
15
+ } from "#dms-ui/app/build/components/containers/constants";
12
16
 
13
17
  /** Floating panels (menus, popovers, toasts): accented hairline and the pop shadow. */
14
18
  const FLOATING_SURFACE =
@@ -18,7 +22,15 @@ const FLOATING_SURFACE =
18
22
  const OVERLAY_SURFACE =
19
23
  "bg-default ring-(--dms-border-top) shadow-(--dms-shadow-modal)";
20
24
 
21
- const BACKDROP = "bg-(--dms-overlay) backdrop-blur-[2px]";
25
+ /**
26
+ * Every modal, slideover and drawer, the DMS's or a module's: its backdrop
27
+ * lets clicks through as soon as it starts closing and fades out quickly,
28
+ * and the panel animating out no longer catches them either (reka keeps
29
+ * `pointer-events: auto` inline on both). The panel a closing dialog
30
+ * uncovered (a drawer under a confirm) takes clicks again at once.
31
+ */
32
+ const BACKDROP = `bg-(--dms-overlay) backdrop-blur-[2px] ${CLOSING_OVERLAY_CLASS}`;
33
+ const CLOSING_PANEL = `data-[state=closed]:pointer-events-none! ${UNCOVERED_PANEL_CLASS}`;
22
34
 
23
35
  const cardTheme = {
24
36
  slots: {
@@ -90,7 +102,7 @@ const tooltipTheme = {
90
102
 
91
103
  const modalTheme = {
92
104
  slots: {
93
- content: "bg-default divide-y-0",
105
+ content: `bg-default divide-y-0 ${CLOSING_PANEL}`,
94
106
  header: "items-start gap-3 min-h-0 px-5 pt-[18px] pb-0 sm:px-5",
95
107
  title: "text-[17px] leading-[1.3] font-[650] tracking-[-0.02em]",
96
108
  description: "mt-1 text-[13px]",
@@ -116,7 +128,7 @@ const modalTheme = {
116
128
  const slideoverTheme = {
117
129
  slots: {
118
130
  overlay: BACKDROP,
119
- content: `${OVERLAY_SURFACE} sm:shadow-(--dms-shadow-modal)`,
131
+ content: `${OVERLAY_SURFACE} sm:shadow-(--dms-shadow-modal) ${CLOSING_PANEL}`,
120
132
  header: "px-5 sm:px-5",
121
133
  title: "text-[17px] leading-[1.3] font-[650] tracking-[-0.02em]",
122
134
  description: "text-[13px]",
@@ -138,7 +150,7 @@ const DRAWER_EDGE_COMPOUNDS = [
138
150
  const drawerTheme = {
139
151
  slots: {
140
152
  overlay: BACKDROP,
141
- content: OVERLAY_SURFACE,
153
+ content: `${OVERLAY_SURFACE} ${CLOSING_PANEL}`,
142
154
  },
143
155
  compoundVariants: DRAWER_EDGE_COMPOUNDS,
144
156
  };
@@ -178,7 +190,10 @@ const toastTheme = {
178
190
  * New toasts rise 16px into place instead of sliding in from a full toast
179
191
  * height below: that slide started off-screen, so a toast whose animation
180
192
  * had not run yet (background tab, throttled frame) sat cut off under the
181
- * bottom edge.
193
+ * bottom edge. A bottom stack rises above a save bar on the bottom edge (the
194
+ * floating bar, a drawer's footer band): the bar sets how far it reaches
195
+ * (`--dms-toaster-clearance`, see `toasterClearance.ts`), so a toast never
196
+ * covers its buttons, and the stack drops back once the bar hides.
182
197
  */
183
198
  const toasterTheme = {
184
199
  slots: {
@@ -203,7 +218,8 @@ const toasterTheme = {
203
218
  {
204
219
  position: ["bottom-left", "bottom-center", "bottom-right"],
205
220
  class: {
206
- viewport: "bottom-5",
221
+ viewport:
222
+ "bottom-[calc(var(--dms-toaster-clearance,0px)+1.25rem)] transition-[bottom] duration-200 ease-out motion-reduce:transition-none",
207
223
  base: "data-[state=open]:animate-none starting:translate-y-4",
208
224
  },
209
225
  },
@@ -10,6 +10,9 @@ export type StoreModuleState =
10
10
  | "error"
11
11
  | "pending";
12
12
 
13
+ /** Where a module's code comes from (`ModuleSourceKind` on the backend). */
14
+ export type ModuleSourceKind = "npm" | "github" | "gitlab" | "git" | "local";
15
+
13
16
  export type StoreFrontendState = "none" | "synced" | "pending" | "unknown";
14
17
 
15
18
  export type StoreOperationKind =
@@ -86,6 +89,10 @@ export interface StoreListingEntry {
86
89
  description: string;
87
90
  state: StoreModuleState;
88
91
  installedVersion?: string;
92
+ /** Where its code comes from. */
93
+ source: ModuleSourceKind;
94
+ /** Runs from a local or git working copy: active, but no store action. */
95
+ isWorkingCopy?: boolean;
89
96
  /** The version range antelope.config.ts declares. */
90
97
  declaredRange?: string;
91
98
  latestVersion?: string;
@@ -103,6 +110,8 @@ export interface StoreListingEntry {
103
110
  missingInterfaces: MissingInterface[];
104
111
  /** Running modules that need an interface only this one implements. */
105
112
  dependents: string[];
113
+ /** The project's own code needs an interface only this module implements. */
114
+ usedByProject: boolean;
106
115
  }
107
116
 
108
117
  export interface StoreListing {
@@ -1,6 +1,7 @@
1
1
  import type { BlockText } from "#dms-core/app/types/composed-text";
2
2
  import type { BlockAction } from "#dms-ui/app/build/components/blocks/BlockActions.vue";
3
3
  import type { PageLiveOptions } from "#dms-ui/app/types/live";
4
+ import type { ModuleSourceKind } from "./module-store";
4
5
 
5
6
  export type MenuItemType = "label" | "link";
6
7
  // MenuItemVariant / MenuItemStatus / MenuItemQuery live in dms-core, the layer
@@ -88,12 +89,19 @@ export type ModuleCatalogEntry = ModuleWithAccess & {
88
89
  landingSlug: string;
89
90
  status?: ModuleStatus;
90
91
  readout?: ModuleReadoutLine[];
92
+ /**
93
+ * Where its code comes from, read from the module store; absent for a
94
+ * module the store does not list.
95
+ */
96
+ source?: ModuleSourceKind;
91
97
  };
92
98
 
93
99
  export const MODULE_URL_PREFIX = "/modules";
94
100
 
95
101
  export interface PageInfo extends Omit<CategoryInfo, "category"> {
96
102
  layoutUrl: string;
103
+ /** Full slug of the page this one is a detail of (`MenuOptions.parent`). */
104
+ parentSlug?: string;
97
105
  }
98
106
 
99
107
  export type SiteLayoutTree = Omit<PageInfo, "layoutUrl"> & {
@@ -107,15 +115,21 @@ export type SiteLayoutTree = Omit<PageInfo, "layoutUrl"> & {
107
115
  // Mirror of LayoutBannerVariant from @antelopejs/interface-dms/layout-banners.
108
116
  export type LayoutBannerVariant = "info" | "warning" | "error";
109
117
 
118
+ // Mirror of LayoutBannerScope from @antelopejs/interface-dms/layout-banners.
119
+ export type LayoutBannerScope = "app" | "modules" | "everywhere";
120
+
110
121
  /**
111
122
  * Mirror of the backend's serialized layout banner. The payload only carries
112
123
  * the banners whose visibility resolver passed for this request, so there is
113
- * nothing left to decide here but the user's own dismissals.
124
+ * nothing left to decide here but the current route against `scope` and the
125
+ * user's own dismissals.
114
126
  */
115
127
  export interface LayoutBanner {
116
128
  key: string;
117
129
  variant: LayoutBannerVariant;
118
130
  order: number;
131
+ /** The pages it shows on, the backend's `app` unless it says otherwise. */
132
+ scope: LayoutBannerScope;
119
133
  dismissible: boolean;
120
134
  icon?: string;
121
135
  /** A string (`$` for an i18n key) or a composed text. */
@@ -5,6 +5,8 @@ export interface AccountMenuEntry {
5
5
  }
6
6
 
7
7
  export const PROFILE_ROUTE = "/settings/user/profile";
8
+ // The account menu is the only way to the settings: the sidebar footer has no
9
+ // Settings entry, so this one opens all of them, not just the user's own.
8
10
  export const SETTINGS_ROUTE = "/settings";
9
11
  export const SWITCH_ACCOUNT_ROUTE = "/auth/accounts";
10
12
 
@@ -26,3 +28,12 @@ export const ACCOUNT_MENU_ENTRIES: AccountMenuEntry[] = [
26
28
  to: SWITCH_ACCOUNT_ROUTE,
27
29
  },
28
30
  ];
31
+
32
+ /**
33
+ * Whether `to` is the destination of an account menu entry. The command
34
+ * palette lists those entries in its session group, so its navigation group
35
+ * skips their pages instead of offering the same destination twice.
36
+ */
37
+ export function isAccountMenuRoute(to: string): boolean {
38
+ return ACCOUNT_MENU_ENTRIES.some((entry) => entry.to === to);
39
+ }
@@ -49,3 +49,60 @@ export function buildBreadcrumbTarget(
49
49
 
50
50
  return buildPageTarget(path, metadata.validation, currentQuery);
51
51
  }
52
+
53
+ /** The crumb a folded breadcrumb shows for the crumbs it hides. */
54
+ export interface FoldedCrumbs<T> {
55
+ isFolded: true;
56
+ slot: string;
57
+ children: T[];
58
+ }
59
+
60
+ export function isFoldedCrumbs<T>(
61
+ crumb: T | FoldedCrumbs<T>,
62
+ ): crumb is FoldedCrumbs<T> {
63
+ return (crumb as Partial<FoldedCrumbs<T>>).isFolded === true;
64
+ }
65
+
66
+ /**
67
+ * A phone's breadcrumb: the first and the last crumb, the ones between
68
+ * folded into one `slot` crumb. A single crumb between them stays as it is,
69
+ * a "…" holding one name only hid it.
70
+ */
71
+ export function foldBreadcrumb<T>(
72
+ crumbs: readonly T[],
73
+ slot: string,
74
+ ): (T | FoldedCrumbs<T>)[] {
75
+ if (crumbs.length <= 3) return [...crumbs];
76
+ return [
77
+ crumbs[0]!,
78
+ { isFolded: true, slot, children: crumbs.slice(1, -1) },
79
+ crumbs.at(-1)!,
80
+ ];
81
+ }
82
+
83
+ /** What a crumb is compared on: the URL it opens. */
84
+ interface LinkedCrumb {
85
+ to?: unknown;
86
+ }
87
+
88
+ /**
89
+ * `crumbs` with the crumb of the page the current one is a detail of
90
+ * (`MenuOptions.parent`) before the last, unless a crumb already opens it:
91
+ * a hidden detail page then leads back to its list.
92
+ */
93
+ export function withParentCrumb<T extends object>(
94
+ crumbs: readonly T[],
95
+ parent: T | null | undefined,
96
+ ): T[] {
97
+ if (!parent || crumbs.length < 2) return [...crumbs];
98
+ const parentTo = (parent as LinkedCrumb).to;
99
+ if (
100
+ crumbs.some(
101
+ (crumb) =>
102
+ parentTo !== undefined && (crumb as LinkedCrumb).to === parentTo,
103
+ )
104
+ ) {
105
+ return [...crumbs];
106
+ }
107
+ return [...crumbs.slice(0, -1), parent, crumbs.at(-1)!];
108
+ }
@@ -57,3 +57,29 @@ export function layoutUrlWithQuery(
57
57
  const search = new URLSearchParams(query).toString();
58
58
  return search ? `${layoutUrl}?${search}` : layoutUrl;
59
59
  }
60
+
61
+ /**
62
+ * A page path or layout URL with its `:name` segments filled from `params`;
63
+ * a segment `params` has no value for stays as it is. The page's layout route
64
+ * reads them as the page URL's own.
65
+ */
66
+ export function fillRouteParams(
67
+ layoutUrl: string,
68
+ params: Record<string, string>,
69
+ ): string {
70
+ return layoutUrl.replace(/:([^/]+)/g, (segment, name: string) =>
71
+ name in params ? params[name]! : segment,
72
+ );
73
+ }
74
+
75
+ /** Whether two sets of route parameters hold the same values. */
76
+ export function isSameRouteParams(
77
+ left: Record<string, string>,
78
+ right: Record<string, string>,
79
+ ): boolean {
80
+ const names = Object.keys(left);
81
+ return (
82
+ names.length === Object.keys(right).length &&
83
+ names.every((name) => left[name] === right[name])
84
+ );
85
+ }
@@ -0,0 +1,71 @@
1
+ import { get } from "@nuxt/ui/runtime/utils/index.js";
2
+ import type { ActionTarget } from "#dms-ui/app/composables/table-view/types/action-target";
3
+
4
+ // The record a page shows (`DefaultLayout({ record })`), as its header
5
+ // buttons read it: `{{record.X}}` in a target, a button acting on it.
6
+
7
+ /** The record of the page as the header knows it. */
8
+ export type PageRecord =
9
+ | { status: "loading" }
10
+ | { status: "loaded"; values: Record<string, unknown> }
11
+ /** Not found, refused, or its URL names a value the page does not carry. */
12
+ | { status: "missing" };
13
+
14
+ /** What the header needs of a button to bind it to the page's record. */
15
+ export interface RecordBoundButton {
16
+ target?: ActionTarget;
17
+ requiresRecord?: boolean;
18
+ disabled?: boolean;
19
+ }
20
+
21
+ const RECORD_TOKEN = /\{\{\s*record\.([\w.-]+)\s*\}\}/g;
22
+ const NAMES_RECORD = /\{\{\s*record\./;
23
+
24
+ const targetUrl = (target: ActionTarget | undefined): string | undefined => {
25
+ const url = (target as { url?: unknown } | undefined)?.url;
26
+ return typeof url === "string" ? url : undefined;
27
+ };
28
+
29
+ /** Whether a button acts on the page's record. */
30
+ export function isRecordBound(button: RecordBoundButton): boolean {
31
+ if (button.requiresRecord) return true;
32
+ const url = targetUrl(button.target);
33
+ return !!url && NAMES_RECORD.test(url);
34
+ }
35
+
36
+ /**
37
+ * A URL with its `{{record.X}}` tokens filled in, each value percent-encoded
38
+ * (an address is one query value). A token the record has no value for is
39
+ * left as written.
40
+ */
41
+ export function fillRecordTokens(
42
+ url: string,
43
+ record: Record<string, unknown>,
44
+ ): string {
45
+ return url.replace(RECORD_TOKEN, (match, key: string) => {
46
+ const value: unknown = get(record, key);
47
+ return typeof value === "string" || typeof value === "number"
48
+ ? encodeURIComponent(String(value))
49
+ : match;
50
+ });
51
+ }
52
+
53
+ /**
54
+ * The button as the page's record leaves it: unchanged when it does not act
55
+ * on the record; disabled while the record loads; left out (`null`) when the
56
+ * record is missing; its target's `{{record.X}}` filled in once loaded.
57
+ */
58
+ export function withPageRecord<T extends RecordBoundButton>(
59
+ button: T,
60
+ record: PageRecord | undefined,
61
+ ): T | null {
62
+ if (!record || !isRecordBound(button)) return button;
63
+ if (record.status === "missing") return null;
64
+ if (record.status === "loading") return { ...button, disabled: true };
65
+ const url = targetUrl(button.target);
66
+ if (!url) return button;
67
+ return {
68
+ ...button,
69
+ target: { ...button.target, url: fillRecordTokens(url, record.values) },
70
+ } as T;
71
+ }