@antelopejs/dms 0.9.8 → 0.11.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 (451) hide show
  1. package/CHANGELOG.md +171 -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 -2
  21. package/dist/config.js +5 -7
  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 +38 -94
  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 +7 -2
  41. package/dist/implementations/dms/manifest.js +12 -7
  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 +32 -55
  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 +25 -15
  129. package/dist/store/listing.js.map +1 -1
  130. package/dist/store/operations.js +5 -2
  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/utils/ensure-default-tenant.d.ts +2 -1
  139. package/dist/utils/ensure-default-tenant.js +13 -1
  140. package/dist/utils/ensure-default-tenant.js.map +1 -1
  141. package/dist/utils/export-jobs.js +2 -1
  142. package/dist/utils/export-jobs.js.map +1 -1
  143. package/dist/validation/auth.schema.d.ts +2 -2
  144. package/dist/validation/member-invite.schema.d.ts +2 -10
  145. package/dist/validation/member-invite.schema.js +2 -15
  146. package/dist/validation/member-invite.schema.js.map +1 -1
  147. package/frontend-vue/dms.frontend.ts +24 -5
  148. package/frontend-vue/dms.server.ts +17 -0
  149. package/frontend-vue/layers/dms-auth/server/accounts.ts +3 -4
  150. package/frontend-vue/layers/dms-core/app/build/composables/renderNow.ts +33 -0
  151. package/frontend-vue/layers/dms-core/app/build/composables/user/tablePreferences.ts +5 -1
  152. package/frontend-vue/layers/dms-core/app/build/utils/crossTab.ts +199 -0
  153. package/frontend-vue/layers/dms-core/app/build/utils/sharedRealtimeConnection.ts +410 -0
  154. package/frontend-vue/layers/dms-core/app/composables/auth/useApiData.ts +77 -12
  155. package/frontend-vue/layers/dms-core/app/composables/data-types/useDataType.ts +26 -0
  156. package/frontend-vue/layers/dms-core/app/composables/live/livePauseSource.ts +29 -0
  157. package/frontend-vue/layers/dms-core/app/composables/period/compareResolvers.ts +150 -9
  158. package/frontend-vue/layers/dms-core/app/composables/period/usePeriod.ts +6 -4
  159. package/frontend-vue/layers/dms-core/app/composables/period/usePeriodScope.ts +27 -1
  160. package/frontend-vue/layers/dms-core/app/composables/realtime/useUserRealtime.ts +256 -119
  161. package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +21 -8
  162. package/frontend-vue/layers/dms-core/app/composables/translation/useTranslation.ts +25 -5
  163. package/frontend-vue/layers/dms-core/app/composables/useApiError.ts +3 -5
  164. package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +61 -26
  165. package/frontend-vue/layers/dms-core/app/plugins/dev-error-log.ts +16 -0
  166. package/frontend-vue/layers/dms-core/app/types/user.ts +6 -0
  167. package/frontend-vue/layers/dms-core/app/utils/composedText.ts +7 -2
  168. package/frontend-vue/layers/dms-core/app/utils/formatter.ts +134 -35
  169. package/frontend-vue/layers/dms-core/app/utils/url-interpolation.ts +18 -1
  170. package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +136 -2
  171. package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +136 -2
  172. package/frontend-vue/layers/dms-core/shared/types/app-config.ts +0 -2
  173. package/frontend-vue/layers/dms-layout/app/app.config.ts +0 -1
  174. package/frontend-vue/layers/dms-layout/app/assets/css/main.css +11 -1
  175. package/frontend-vue/layers/dms-layout/app/assets/fonts/Geist-Italic-Variable.woff2 +0 -0
  176. package/frontend-vue/layers/dms-layout/app/assets/fonts/Geist-Variable.woff2 +0 -0
  177. package/frontend-vue/layers/dms-layout/app/assets/fonts/GeistMono-Italic-Variable.woff2 +0 -0
  178. package/frontend-vue/layers/dms-layout/app/assets/fonts/GeistMono-Variable.woff2 +0 -0
  179. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +3 -2
  180. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +41 -21
  181. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardPageBody.vue +6 -2
  182. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidebar.vue +4 -19
  183. package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +11 -107
  184. package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +18 -7
  185. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionsOutlet.vue +4 -0
  186. package/frontend-vue/layers/dms-layout/app/build/components/layout/RowSidePanel.vue +43 -82
  187. package/frontend-vue/layers/dms-layout/app/build/components/layout/SidebarUserMenu.vue +44 -3
  188. package/frontend-vue/layers/dms-layout/app/build/components/layout/UserIdentity.vue +11 -3
  189. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleCatalogTile.vue +132 -35
  190. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleManageMenu.vue +59 -0
  191. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleSourceLabel.vue +25 -0
  192. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreBanners.vue +73 -0
  193. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreOperation.vue +116 -0
  194. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreRequirements.vue +8 -3
  195. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreTile.vue +85 -207
  196. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTile.vue +10 -3
  197. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTileSkeleton.vue +68 -0
  198. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxDisplay.vue +24 -8
  199. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxItem.vue +8 -5
  200. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionTimeZoneInput.vue +1 -0
  201. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +19 -0
  202. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRoleEditor.ts +2 -1
  203. package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +31 -70
  204. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +11 -1
  205. package/frontend-vue/layers/dms-layout/app/build/utils/dev-reload-stream.ts +81 -0
  206. package/frontend-vue/layers/dms-layout/app/build/utils/github-repository.ts +2 -2
  207. package/frontend-vue/layers/dms-layout/app/build/utils/module-store-catalog.ts +232 -36
  208. package/frontend-vue/layers/dms-layout/app/build/utils/modules-catalog.ts +122 -14
  209. package/frontend-vue/layers/dms-layout/app/composables/layout/useLayoutBanners.ts +32 -3
  210. package/frontend-vue/layers/dms-layout/app/composables/layout/useServedHeaderActions.ts +49 -11
  211. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleHistory.ts +3 -2
  212. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStore.ts +59 -4
  213. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStoreActions.ts +194 -0
  214. package/frontend-vue/layers/dms-layout/app/composables/page/usePageComponentPreload.ts +23 -3
  215. package/frontend-vue/layers/dms-layout/app/composables/page/usePageLayout.ts +4 -2
  216. package/frontend-vue/layers/dms-layout/app/composables/page/usePageRecordDeletion.ts +162 -0
  217. package/frontend-vue/layers/dms-layout/app/composables/page/useSiteLayout.ts +6 -1
  218. package/frontend-vue/layers/dms-layout/app/custom-layouts/DefaultLayout.vue +6 -2
  219. package/frontend-vue/layers/dms-layout/app/custom-layouts/SettingsLayout.vue +6 -2
  220. package/frontend-vue/layers/dms-layout/app/custom-pages/modules-store.vue +291 -0
  221. package/frontend-vue/layers/dms-layout/app/custom-pages/modules.vue +87 -474
  222. package/frontend-vue/layers/dms-layout/app/middleware/module-routing.global.ts +3 -0
  223. package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +13 -22
  224. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-navigation.client.ts +11 -10
  225. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-personal-pages.client.ts +22 -52
  226. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-quick-actions.client.ts +7 -7
  227. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-session.client.ts +11 -10
  228. package/frontend-vue/layers/dms-layout/app/plugins/dms-dev-reload.client.ts +14 -9
  229. package/frontend-vue/layers/dms-layout/app/theme/actions.ts +5 -4
  230. package/frontend-vue/layers/dms-layout/app/theme/form-controls.ts +9 -4
  231. package/frontend-vue/layers/dms-layout/app/theme/surfaces.ts +22 -6
  232. package/frontend-vue/layers/dms-layout/app/types/module-store.ts +9 -0
  233. package/frontend-vue/layers/dms-layout/app/types/page.ts +15 -1
  234. package/frontend-vue/layers/dms-layout/app/utils/account-menu.ts +11 -0
  235. package/frontend-vue/layers/dms-layout/app/utils/breadcrumb.ts +57 -0
  236. package/frontend-vue/layers/dms-layout/app/utils/pageQuery.ts +26 -0
  237. package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +45 -18
  238. package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +44 -17
  239. package/frontend-vue/layers/dms-ui/app/build/components/containers/TargetComponentTree.vue +31 -0
  240. package/frontend-vue/layers/dms-ui/app/build/components/containers/constants.ts +25 -0
  241. package/frontend-vue/layers/dms-ui/app/build/components/containers/drawer/DynamicDrawer.vue +244 -15
  242. package/frontend-vue/layers/dms-ui/app/build/components/containers/modal/DynamicModal.vue +42 -25
  243. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowHeader.vue +153 -0
  244. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowNotFound.vue +44 -0
  245. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/drawerRowHeader.ts +35 -0
  246. package/frontend-vue/layers/dms-ui/app/build/components/form/FormEntries.vue +44 -9
  247. package/frontend-vue/layers/dms-ui/app/build/components/form/FormErrorSummary.vue +11 -4
  248. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldControl.vue +38 -5
  249. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldNotes.vue +29 -5
  250. package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +5 -1
  251. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSectionNav.vue +3 -1
  252. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSections.vue +106 -27
  253. package/frontend-vue/layers/dms-ui/app/build/components/table/Actions.vue +12 -4
  254. package/frontend-vue/layers/dms-ui/app/build/components/table/Empty.vue +4 -2
  255. package/frontend-vue/layers/dms-ui/app/build/components/table/FiltersRow.vue +48 -1
  256. package/frontend-vue/layers/dms-ui/app/build/components/table/Pagination.vue +55 -54
  257. package/frontend-vue/layers/dms-ui/app/build/components/table/RowSelection.vue +2 -1
  258. package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +396 -288
  259. package/frontend-vue/layers/dms-ui/app/build/components/table/Tabs.vue +2 -1
  260. package/frontend-vue/layers/dms-ui/app/build/components/table/Views.vue +2 -1
  261. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardAvatar.vue +59 -0
  262. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardGridSkeleton.vue +19 -2
  263. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardRowActions.vue +38 -0
  264. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +148 -104
  265. package/frontend-vue/layers/dms-ui/app/build/components/table-view/LiveHoldBanner.vue +17 -2
  266. package/frontend-vue/layers/dms-ui/app/build/composables/actions/bulkSelection.ts +43 -9
  267. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowComponentOptions.ts +76 -0
  268. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +172 -27
  269. package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +270 -46
  270. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/actionError.ts +6 -1
  271. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/confirmDialogTexts.ts +2 -0
  272. package/frontend-vue/layers/dms-ui/app/build/composables/containers/closingLayers.ts +186 -0
  273. package/frontend-vue/layers/dms-ui/app/build/composables/containers/context.ts +14 -0
  274. package/frontend-vue/layers/dms-ui/app/build/composables/containers/drawerSize.ts +229 -0
  275. package/frontend-vue/layers/dms-ui/app/build/composables/containers/useResizableSize.ts +175 -0
  276. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +18 -35
  277. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/numberSuffix.ts +44 -0
  278. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +123 -27
  279. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerFieldTypes.ts +2 -1
  280. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationFilter.ts +75 -0
  281. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationRows.ts +92 -0
  282. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationValue.ts +39 -0
  283. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +3 -3
  284. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +6 -2
  285. package/frontend-vue/layers/dms-ui/app/build/composables/form/createFormFields.ts +15 -0
  286. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldSaved.ts +40 -0
  287. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldValueRule.ts +62 -0
  288. package/frontend-vue/layers/dms-ui/app/build/composables/form/formEntryContext.ts +5 -0
  289. package/frontend-vue/layers/dms-ui/app/build/composables/form/formFooter.ts +42 -7
  290. package/frontend-vue/layers/dms-ui/app/build/composables/form/formLayout.ts +106 -4
  291. package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +11 -5
  292. package/frontend-vue/layers/dms-ui/app/build/composables/form/formSections.ts +32 -0
  293. package/frontend-vue/layers/dms-ui/app/build/composables/form/formValidation.ts +36 -4
  294. package/frontend-vue/layers/dms-ui/app/build/composables/form/readonlyValue.ts +19 -0
  295. package/frontend-vue/layers/dms-ui/app/build/composables/form/registerFormFunctions.ts +27 -0
  296. package/frontend-vue/layers/dms-ui/app/build/composables/form/repeaterTable.ts +78 -0
  297. package/frontend-vue/layers/dms-ui/app/build/composables/form/serverFieldErrors.ts +49 -0
  298. package/frontend-vue/layers/dms-ui/app/build/composables/form/toasterClearance.ts +118 -0
  299. package/frontend-vue/layers/dms-ui/app/build/composables/form/useInstantForm.ts +12 -1
  300. package/frontend-vue/layers/dms-ui/app/build/composables/live/currentPageLive.ts +41 -3
  301. package/frontend-vue/layers/dms-ui/app/build/composables/live/livePoller.ts +10 -2
  302. package/frontend-vue/layers/dms-ui/app/build/composables/live/pageReadClock.ts +28 -0
  303. package/frontend-vue/layers/dms-ui/app/build/composables/live/shortcuts.ts +1 -1
  304. package/frontend-vue/layers/dms-ui/app/build/composables/live/usePageLiveHost.ts +17 -3
  305. package/frontend-vue/layers/dms-ui/app/build/composables/live/useUpdatedLabel.ts +38 -0
  306. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/pageToolbarContext.ts +75 -0
  307. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/toolbarControlHeight.ts +29 -0
  308. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodComparison.ts +52 -0
  309. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodDisplay.ts +21 -0
  310. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodShortLabels.ts +28 -0
  311. package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodDraft.ts +1 -0
  312. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRelationFilterLabels.ts +97 -0
  313. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRowScrollAnchor.ts +106 -0
  314. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +9 -0
  315. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableColumns.ts +1 -2
  316. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/archivedCount.ts +31 -0
  317. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/filterEditorValue.ts +38 -0
  318. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/formatFilterValue.ts +33 -2
  319. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/scrollEdges.ts +31 -0
  320. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useCardFields.ts +33 -0
  321. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useMobileDisplay.ts +48 -0
  322. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useScrolledPastTop.ts +41 -18
  323. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableFooter.ts +3 -2
  324. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLinkedVisit.ts +78 -0
  325. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLiveHold.ts +135 -22
  326. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +56 -25
  327. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +90 -35
  328. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViews.ts +86 -10
  329. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/bulkActions.ts +14 -4
  330. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/card.ts +127 -2
  331. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/compareValues.ts +13 -0
  332. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/expandedRows.ts +28 -0
  333. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/groupedRows.ts +114 -1
  334. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/linkedArrival.ts +308 -0
  335. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/locateRow.ts +106 -0
  336. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pageArrival.ts +34 -0
  337. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pinnedRows.ts +17 -0
  338. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/quickFilters.ts +41 -33
  339. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +24 -8
  340. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableCounts.ts +113 -0
  341. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableQuery.ts +27 -4
  342. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +22 -6
  343. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/writeError.ts +21 -0
  344. package/frontend-vue/layers/dms-ui/app/build/utils/addressSuggestions.ts +49 -0
  345. package/frontend-vue/layers/dms-ui/app/build/utils/codeHighlight.ts +67 -29
  346. package/frontend-vue/layers/dms-ui/app/build/utils/eyebrow.ts +12 -0
  347. package/frontend-vue/layers/dms-ui/app/build/utils/fieldOptionsI18n.ts +51 -11
  348. package/frontend-vue/layers/dms-ui/app/build/utils/htmlGrammar.ts +79 -0
  349. package/frontend-vue/layers/dms-ui/app/build/utils/inputWidth.ts +53 -0
  350. package/frontend-vue/layers/dms-ui/app/build/utils/numberAdjustment.ts +6 -3
  351. package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +19 -5
  352. package/frontend-vue/layers/dms-ui/app/build/utils/scrollWithin.ts +99 -0
  353. package/frontend-vue/layers/dms-ui/app/build/utils/shellParser.ts +1 -1
  354. package/frontend-vue/layers/dms-ui/app/build/utils/streamHighlight.ts +90 -0
  355. package/frontend-vue/layers/dms-ui/app/build/utils/urlVariables.ts +36 -14
  356. package/frontend-vue/layers/dms-ui/app/components/PasswordStrength.vue +1 -1
  357. package/frontend-vue/layers/dms-ui/app/components/RecursiveComponent.vue +9 -1
  358. package/frontend-vue/layers/dms-ui/app/components/blocks/LiveToggleBlock.vue +80 -32
  359. package/frontend-vue/layers/dms-ui/app/components/blocks/PageToolbarBlock.vue +137 -0
  360. package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +5 -0
  361. package/frontend-vue/layers/dms-ui/app/components/chart/ApexChartHost.vue +16 -2
  362. package/frontend-vue/layers/dms-ui/app/components/chart/Chart.vue +24 -5
  363. package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +41 -23
  364. package/frontend-vue/layers/dms-ui/app/components/code-snippet/CodeSnippet.vue +23 -12
  365. package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +1 -1
  366. package/frontend-vue/layers/dms-ui/app/components/container-footer/ContainerFooter.vue +34 -0
  367. package/frontend-vue/layers/dms-ui/app/components/field-row/FieldRow.vue +25 -2
  368. package/frontend-vue/layers/dms-ui/app/components/flow-canvas/FlowCanvas.vue +2 -2
  369. package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +119 -36
  370. package/frontend-vue/layers/dms-ui/app/components/form/components/Cascader.vue +53 -22
  371. package/frontend-vue/layers/dms-ui/app/components/form/components/DatePicker.vue +20 -1
  372. package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +13 -1
  373. package/frontend-vue/layers/dms-ui/app/components/form/components/Image.vue +8 -3
  374. package/frontend-vue/layers/dms-ui/app/components/form/components/InputAddress.vue +53 -5
  375. package/frontend-vue/layers/dms-ui/app/components/form/components/InputCode.vue +29 -5
  376. package/frontend-vue/layers/dms-ui/app/components/form/components/InputNumber.vue +45 -8
  377. package/frontend-vue/layers/dms-ui/app/components/form/components/InputPercentage.vue +28 -5
  378. package/frontend-vue/layers/dms-ui/app/components/form/components/InputSecret.vue +5 -0
  379. package/frontend-vue/layers/dms-ui/app/components/form/components/InputText.vue +19 -2
  380. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTime.vue +2 -1
  381. package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +226 -65
  382. package/frontend-vue/layers/dms-ui/app/components/form/components/Repeater.vue +80 -30
  383. package/frontend-vue/layers/dms-ui/app/components/form/components/RepeaterTable.vue +210 -0
  384. package/frontend-vue/layers/dms-ui/app/components/form/components/Select.vue +4 -2
  385. package/frontend-vue/layers/dms-ui/app/components/grid/GridRow.vue +11 -2
  386. package/frontend-vue/layers/dms-ui/app/components/key-value-list/KeyValueList.vue +79 -70
  387. package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +117 -21
  388. package/frontend-vue/layers/dms-ui/app/components/meter/Meter.vue +2 -1
  389. package/frontend-vue/layers/dms-ui/app/components/period/PeriodSelector.vue +113 -34
  390. package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +14 -2
  391. package/frontend-vue/layers/dms-ui/app/components/section-header/Eyebrow.vue +6 -1
  392. package/frontend-vue/layers/dms-ui/app/components/segmented/Segmented.vue +13 -0
  393. package/frontend-vue/layers/dms-ui/app/components/stat-group/StatGroup.vue +52 -3
  394. package/frontend-vue/layers/dms-ui/app/components/tab/Tab.vue +2 -1
  395. package/frontend-vue/layers/dms-ui/app/components/table-view/CascaderPath.vue +74 -25
  396. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanBoard.vue +48 -44
  397. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanDisplay.vue +4 -1
  398. package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +426 -97
  399. package/frontend-vue/layers/dms-ui/app/components/top-list/TopListCard.vue +33 -5
  400. package/frontend-vue/layers/dms-ui/app/composables/chart/apexCategoryLabels.ts +68 -0
  401. package/frontend-vue/layers/dms-ui/app/composables/chart/apexDatetimeBuckets.ts +306 -0
  402. package/frontend-vue/layers/dms-ui/app/composables/chart/formatValue.ts +4 -3
  403. package/frontend-vue/layers/dms-ui/app/composables/chart/heatmapColors.ts +93 -0
  404. package/frontend-vue/layers/dms-ui/app/composables/chart/localizeSeries.ts +62 -0
  405. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.ts +116 -8
  406. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.types.ts +7 -0
  407. package/frontend-vue/layers/dms-ui/app/composables/containers/types.ts +84 -1
  408. package/frontend-vue/layers/dms-ui/app/composables/containers/useDrawer.ts +69 -8
  409. package/frontend-vue/layers/dms-ui/app/composables/form/types/field-saved.ts +11 -0
  410. package/frontend-vue/layers/dms-ui/app/composables/form/types/field.ts +16 -0
  411. package/frontend-vue/layers/dms-ui/app/composables/form/types/functions.ts +1 -0
  412. package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +189 -28
  413. package/frontend-vue/layers/dms-ui/app/composables/live/usePageLive.ts +29 -12
  414. package/frontend-vue/layers/dms-ui/app/composables/page-toolbar/usePageToolbarSize.ts +30 -0
  415. package/frontend-vue/layers/dms-ui/app/composables/table-view/kanban.ts +4 -2
  416. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +22 -3
  417. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +4 -0
  418. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +24 -1
  419. package/frontend-vue/layers/dms-ui/app/plugins/closing-layers.client.ts +10 -0
  420. package/frontend-vue/layers/dms-ui/app/plugins/live-pause-source.ts +15 -0
  421. package/frontend-vue/layers/dms-ui/app/plugins/register.ts +2 -0
  422. package/frontend-vue/layers/dms-ui/app/types/input-number.ts +3 -2
  423. package/frontend-vue/layers/dms-ui/app/types/page-toolbar.ts +7 -0
  424. package/frontend-vue/layers/dms-ui/app/types/row-action.ts +0 -2
  425. package/frontend-vue/layers/dms-ui/app/types/row-navigation.ts +17 -0
  426. package/frontend-vue/layers/dms-ui/app/types/table/query.ts +2 -1
  427. package/frontend-vue/layers/dms-ui/app/utils/blockRefresh.ts +3 -1
  428. package/frontend-vue/layers/dms-ui/app/utils/cascader.ts +94 -3
  429. package/frontend-vue/layers/dms-ui/app/utils/componentTree.ts +24 -0
  430. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +20 -5
  431. package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +20 -5
  432. package/frontend-vue/package.json +6 -2
  433. package/package.json +11 -10
  434. package/skills/dms/SKILL.md +1 -1
  435. package/skills/dms-auth/SKILL.md +5 -3
  436. package/skills/dms-best-practices/REFERENCE.md +2 -0
  437. package/skills/dms-best-practices/SKILL.md +4 -0
  438. package/skills/dms-module/SKILL.md +3 -2
  439. package/skills/dms-pages/REFERENCE.md +129 -16
  440. package/skills/dms-pages/SKILL.md +1 -1
  441. package/skills/dms-project/DEV-SERVERS.md +23 -1
  442. package/skills/dms-project/REFERENCE.md +1 -1
  443. package/skills/dms-project/SKILL.md +4 -1
  444. package/skills/dms-project/scripts/dms-dev.sh +205 -17
  445. package/dist/hooks/tenant-instances.d.ts +0 -1
  446. package/dist/hooks/tenant-instances.js +0 -13
  447. package/dist/hooks/tenant-instances.js.map +0 -1
  448. package/dist/routes/startup-gate.d.ts +0 -7
  449. package/dist/routes/startup-gate.js +0 -39
  450. package/dist/routes/startup-gate.js.map +0 -1
  451. package/frontend-vue/layers/dms-core/app/composables/period/periodRenderNow.ts +0 -42
@@ -10,7 +10,7 @@ lists them with their option schemas); `docs/04.components/` has one page per bl
10
10
 
11
11
  | Group | Blocks |
12
12
  | --- | --- |
13
- | Layout | `Grid` + `GridRow` (children must be rows; `{ colSpan }` child metadata), `HStack` / `VStack` / `Spacer`, `Card` (slots `actions`, `footer`), `Tab` (`{ slot }` per child), `Guard`, `Placeholder` |
13
+ | Layout | `Grid` + `GridRow` (children must be rows; `{ colSpan }` child metadata; a `GridRow` inside a cell, e.g. in a `Section`, spreads its own children rather than the grid's columns), `HStack` / `VStack` / `Spacer`, `PageToolbar` (`pageToolbar()`), `Card` (slots `actions`, `footer`), `Tab` (`{ slot }` per child), `Guard`, `Placeholder` |
14
14
  | Charts & widgets | `KpiCard`, `ChartCard` (wraps one chart), `TopListCard`, `PeriodSelector`, `LiveToggle`; charts `ChartLine`, `ChartArea`, `ChartRangeArea`, `ChartBar`, `ChartColumn`, `ChartScatter`, `ChartMixed`, `ChartRadar`, `ChartCandlestick`, `ChartDonut`, `ChartPie`, `ChartRadialBar`, `ChartHeatmap` |
15
15
  | Display | `StatGroup`, `KeyValueList`, `NavCardGrid`, `EmptyState` (its `code` shows a snippet), `Banner`, `CodeBlock` (`code` + `language`, or `fetchUrl` answering `{ code, language? }`) |
16
16
  | Lists & settings | `ActivityFeed`, `Meter`, `Section` + `FieldRow` |
@@ -38,7 +38,8 @@ gets `navigation` (J / K, `index` / `total` in the order shown) —
38
38
  A page's `headerActions` follow its URL: a target URL takes `{{params.X}}` / `{{query.X}}`
39
39
  (`?workspace={{query.workspace}}`, a pair the page has no value for is dropped), a label's
40
40
  translation takes the page's route and query parameters (`"Download {locale}.json"`), and an
41
- `availability` reads `context.query`, asked again when the query changes — no need to build
41
+ `availability` reads `context.query` and the route parameters in `context.params` (`:id`),
42
+ asked again when either changes (a detail page hides "Edit" for a missing record) — no need to build
42
43
  the header in Vue with `usePageHeaderActions` to carry the scope —
43
44
  `packages/interface-dms/docs/3.base/6.layout.md#buttons-that-follow-the-page-url`. An `availability`
44
45
  answering `{ hidden: true }` leaves the button out for that query (`{ reason }` only
@@ -48,13 +49,42 @@ component's client-side ones (default `0`, served first on a tie: `order: -1` pu
48
49
  "Export" before a served "Add key") — `packages/interface-dms/docs/3.base/6.layout.md#ordering-the-header`.
49
50
 
50
51
  A button or row action (`customButtons`, `rowActions.custom`, a page's `headerActions`)
51
- points at an `ActionTarget`. A `drawer` target opens from the bottom; give it
52
- `direction: "right"` for a side sheet (an inspector, a detail panel) instead of hosting your
53
- own drawer in a `CustomComponent`.
54
- To read rows one after the other next to the table (a request log), use a `sidePanel`
55
- target instead: a non-modal panel docked on the right whose header the DMS draws (title,
56
- `rowTitle` naming the row from its fields, `positionLabel` "x of y", previous / next, J / K, close), `?record=` kept by default (`deepLink: false` opts out), a "not found" state on a 404 (`notFound: { title, description }`) and the table's
57
- `rowClick: "single"` (a `TableView.fromSource` table reads a deep-linked row beyond its first page through `fetchRowUrl: "/api/x/{{row.id}}"`) — never bridge the table's DOM to build one —
52
+ points at an `ActionTarget`. A detail or record panel (an inspector, a request, a run) is a
53
+ `drawer` target — never a `sidePanel`, and never your own drawer hosted in a
54
+ `CustomComponent`. It opens from the bottom; `direction: "right"` makes it a side sheet,
55
+ 600px wide from `lg` (`size: "3xl"` opens it at a modal's width instead), which the user
56
+ resizes by its inner edge and which opens again at that size. On a row it takes the side
57
+ panel's row options: the DMS draws the row header once `rowTitle` (naming the row from its
58
+ fields) or `positionLabel` ("Request 4 of 50") is set (`rowHeader: true` with the defaults),
59
+ with previous / next next to close; J / K step in place, through every row the table lists
60
+ (the position counts them all, a step past the page loaded turns the page, a step goes to
61
+ the open row's neighbour by id so live rows never make it skip or revisit one, and a
62
+ deep-linked row past the page loaded is located in the table's result, in the order
63
+ the table shows, pinned rows leading their own page); `deepLink:
64
+ true` on the target keeps
65
+ `?record=`; `notFound: { title, description }` draws the 404 state — with the table's
66
+ `rowClick: "single"` (a `TableView.fromSource` table reads a deep-linked row beyond its first
67
+ page through `fetchRowUrl: "/api/x/{{row.id}}"`) — never bridge the table's DOM to build one —
68
+ `docs/04.components/08.tables/8.row-drawers.md#detail-drawers`.
69
+ A drawer a module opens itself through `useDrawer()` keeps the size the user gives it under
70
+ its `sizeKey`, by default its `containerId`, else its component's name — pass `sizeKey` only
71
+ when one component opens drawers that must not share a size, or when the component is
72
+ anonymous — `docs/06.frontend-composables/05.ui-toolkit.md`. On a row of a list the module draws
73
+ itself, `rowHeader: { title, positionLabel, navigation }` draws the DMS's row header (position,
74
+ previous / next, J and K; `titleClass`, `titleBreakAfter`, `subtitle`, `subtitleClass` and
75
+ `component` / `componentOptions` under the position line shape it — never a header component of
76
+ the module's own); `patch({ componentOptions, componentKey, rowHeader })` steps it — never
77
+ import the layer's `RowHeader` component —
78
+ `docs/06.frontend-composables/05.ui-toolkit.md#a-drawer-on-a-row-of-your-own`.
79
+ A drawer's body is a flex column: a body component with a growing root (`flex flex-1 flex-col`)
80
+ fills it and ends with `<DmsContainerFooter>` for its buttons — never measure the drawer nor use
81
+ `--dms-form-foot-*`; a code editor taking the height left (`DmsInputCode fill`, in a stacked
82
+ `DmsFieldRow fill`) — never count its lines from the drawer's size —
83
+ `docs/06.frontend-composables/05.ui-toolkit.md#a-body-that-fills-the-drawer-and-its-footer`.
84
+ A `useDrawer()` body injects what the component calling `useDrawer()` (in its setup) provides —
85
+ never pass a context as a prop to provide it again in the body.
86
+ A `sidePanel` target (non-modal, docked on the right) still works, but is meant for global,
87
+ page-independent panels such as an assistant dock —
58
88
  `docs/04.components/08.tables/8.row-drawers.md#side-panel`.
59
89
  A button downloading a file the user's session may read (`/api/...`) takes a `download`
60
90
  target, `{ url, filename? }`, with the same `{{row.field}}` / `{{query.X}}` tokens — never a Vue
@@ -76,9 +106,15 @@ row's ⋯ button — `docs/04.components/08.tables/0.index.md#pinned-rows`.
76
106
  - `.watch(FormEvents.SUBMIT_SUCCESS, BlockFunctions.REFRESH_PAGE)` makes the page's data blocks
77
107
  (table views included) re-fetch after a form saves.
78
108
  - `periodScope` binds a card, chart, list block, `Meter` or `TableView.fromSource` to a
79
- `PeriodSelector`, which keeps its period in the page URL (`?<id>.period=`).
80
- - `realtimeTopic` re-fetches a chart, list block, `Meter`, `Tab` badges or `TableView` on each
81
- `PublishMessage`.
109
+ `PeriodSelector`, which keeps its period in the page URL (`?<id>.period=`). Its selected
110
+ comparison drives the cards: `KpiCard` names it ("vs previous year", leave `compareLabel`
111
+ unset) and prints the route's `previousValue`; "No comparison" hides the change, the value
112
+ compared against and the label on `KpiCard`, `ChartCard` and `TopListCard`.
113
+ - `realtimeTopic` re-fetches a chart, a `KpiCard`, list block, `Meter`, `Tab` badges or `TableView` on each
114
+ `PublishMessage`. Publish tenant data with the tenant id (`{ tenantId }`): without it the message
115
+ is global and refetches the page in every workspace. A `TableView` needs no option: the DMS
116
+ publishes to every tenant for a table of the shared schema, and a platform (module) page receives
117
+ every tenant's changes.
82
118
 
83
119
  ### Live pages
84
120
 
@@ -86,7 +122,24 @@ row's ⋯ button — `docs/04.components/08.tables/0.index.md#pinned-rows`.
86
122
  options (`slowRateAfter: { period: "7d", maxRate: 60 }` for long periods, `rememberKey: "<module>"`
87
123
  to share the choice; `maxRate` is also the polling interval while the stream is down) and places a
88
124
  `LiveToggle()` (Live / Pause, L key; `variant: "pill"`, `missedLabel` for "N new requests").
89
- - `liveHold: true` keeps a table's rows while paused; `liveHold: { whileRowOpen, whileScrolled,
125
+ - A page with a period or live data starts with `pageToolbar({ leading, live, period })`
126
+ (`base/page-toolbar`): the same bar on every page — leading blocks, then "Updated N s ago",
127
+ Live / Pause, the window and the 1H / 24H / 7D / 30D presets, at one `size` and one height
128
+ (24 / 28 / 32 px, with live or not). `live: false` or `period: false` drops a control; without
129
+ `live` it shows the last read and a refresh button. A module's leading chip takes the toolbar's
130
+ height from `usePageToolbarSize().heightClass`. More than one comparison offered
131
+ (`comparisons: ["previous-period", "previous-year", "none"]`) draws a menu naming the compared window ("vs 16 – 17 Oct ▾", the range label then
132
+ without its "vs …"); a single one
133
+ stays on without a control. A `custom` preset shows as a calendar icon, named in full.
134
+ `live` / `period` also take `childId` (keep an id roles already grant, `live` / `period` by
135
+ default) and `meta` (roles-editor name), so a page never builds the toolbar by hand for that;
136
+ `transformOptions` changes a child's options at each registration (a setting read in
137
+ `construct()`) — never patch the toolbar's children afterwards;
138
+ an editor reads the default children from the block type's `initialChildren`.
139
+ A component may draw `<DmsPageToolbarBlock>` and `<DmsLiveToggleBlock>` itself, around controls
140
+ of its own: neither needs a `componentId` or `pageId` there.
141
+ - `liveHold: true` keeps a table's rows while paused, and in Direct while they are on screen (new
142
+ rows wait behind a "N new · Show" pill over the rows, counting the rows the table's query matches now beyond those held, through its count route); `liveHold: { whileRowOpen, whileScrolled,
90
143
  whileSearching, whileSorted }` also holds the table alone; `liveHold.missedLabel` words its "N new".
91
144
  Paused, an event counts as its `payload.ids` rows or its `payload.count`, so a module may batch
92
145
  publishes with `{ count }`. A hidden tab and `?live=0` pause the page too.
@@ -94,7 +147,18 @@ row's ⋯ button — `docs/04.components/08.tables/0.index.md#pinned-rows`.
94
147
  `setMissedDetail()`); one that reads its own data on a topic calls
95
148
  `usePageLiveRefresh(refresh, { realtimeTopic, idleRefresh })` — never a throttle of its own.
96
149
  `refreshPageBlocks()` (user actions) always reads; `refreshLivePageBlocks()` (timers, feeds) is
97
- held while paused.
150
+ held while paused. A table view's write (row/bulk action, its form saved) already
151
+ calls `refreshPageBlocks()`: KPIs and badges of the page need no wiring of their own.
152
+ - Making a block live: a built-in data block names a `realtimeTopic` (its builder registers the
153
+ topic on the page) and the backend calls `PublishMessage`; a table view follows its controller's
154
+ row events by itself. A block without a topic reads only on `refreshLivePageBlocks()`, the
155
+ polling while the stream is down and `refreshPageBlocks()` — no timer while the stream is up. A
156
+ custom component's own topic needs `RegisterPageTopic(pageId, topic)` in the backend.
157
+ - Pause (user, hold, hidden tab) freezes every block of the page at once: realtime events, row
158
+ events, page-topic events behind `useApiData`, `refreshLivePageBlocks()`, `idleRefresh`, the
159
+ stream-down polling and a component's `useApiData` `refreshInterval`. Each block that missed
160
+ something reads once on resume. User actions and inputs (period, filter, search, sort, page)
161
+ still read; notifications, presence and the menu are not the page and keep updating.
98
162
 
99
163
  ### Texts
100
164
 
@@ -103,6 +167,13 @@ row's ⋯ button — `docs/04.components/08.tables/0.index.md#pinned-rows`.
103
167
  KeyValueList / Banner / NavCardGrid / ActivityFeed / Meter / TopListCard item texts, ActivityFeed
104
168
  `params` (typed `count` for plurals), tab badges and layout banners (`RegisterLayoutBanner({ resolve })`
105
169
  → `{ text, actions }`) take it. Never format text server-side.
170
+ - A layout banner (`RegisterLayoutBanner`) shows on the application's pages only by default, never
171
+ inside `/modules` (modules page, module store, module pages). Give `scope:
172
+ LayoutBannerScope.EVERYWHERE` to a workspace-wide state (billing past due, suspended workspace,
173
+ maintenance) that must follow the user into modules; leave the default for anything about the
174
+ application's own data.
175
+ - A route that must word a text reads the request's `x-content-language` header (the language on
176
+ screen), never `users.language` (the profile's, for mails).
106
177
  - A status the backend computes (health, outage) is a `Banner({ fetchUrl })`: the route answers a
107
178
  `BannerContent` (its buttons may run `api` / modal / quick-action targets with `confirm`) or
108
179
  `null` for no banner.
@@ -110,13 +181,20 @@ row's ⋯ button — `docs/04.components/08.tables/0.index.md#pinned-rows`.
110
181
  ### Blocks
111
182
 
112
183
  - `StatGroup` details and `NavCardGrid` card titles take up to two lines before their ellipsis.
184
+ - `StatGroup({ columnsFrom: "md" })` (`DmsStatGroup columns-from`) sets all `columns` side by side from
185
+ that group width — never a class forcing the group's grid (`[&>div]:grid-cols-*`).
113
186
  - `ActivityFeed`: `wrap: true` for entries read whole (leave `fillHeight` off), `visibleItems: N`
114
187
  for a "Show N more" fold.
115
188
  - `KeyValueList` rows take `copy: true` or `copyValue` (the text to copy instead).
189
+ - A fetched list block draws `skeletonCount` placeholders until its first answer in a client
190
+ navigation (a server render waits for the data): set it to the usual number of items so the page
191
+ does not move when they land. A refresh keeps the items on screen until the new ones land.
116
192
  - `TopListCard({ actions })` puts link buttons in its head; `Tab({ fit: true })` keeps pill tabs to
117
193
  their labels' width; with `persistState` the URL names the open tab by its slot (`?tab=tester`).
118
194
  - A `ChartCard` plotting several series names them with `showSeriesLegend: true` (placed by the
119
195
  chart's `legendPosition`) — never a raw Apex `legend` in `rawOptions`.
196
+ - A chart route sends series names, categories (`x`) and point labels as `$` keys, bare chart or
197
+ `ChartCard` alike: the browser translates them, so donut slices are `{ x: "$app.plan.pro", y }`.
120
198
 
121
199
  ### Tables
122
200
 
@@ -128,13 +206,46 @@ row's ⋯ button — `docs/04.components/08.tables/0.index.md#pinned-rows`.
128
206
  `{ label, tone?, variant: "soft" | "outline" }`.
129
207
  - A `TableView` over a shared controller hides a column on one page with
130
208
  `columns: { hidden: ["workspace"] }` — no view just to hide it.
209
+ - A field shown, required or locked by another column's value goes on its `@Column`:
210
+ `visibleWhen: { field: "stage", in: ["lost"] }`, `disabledWhen: { field: "stage", in: ["won"] }`.
211
+ The generated forms and the data routes both apply them (hidden: not mandatory, value ignored,
212
+ stored value cleared on edit; disabled: sent value ignored, stored one kept) — no watch, no custom page.
213
+ - `forms: { new?, edit?, view? }` hands each generated form's builder to a callback
214
+ (`new: (form) => form.watch(FormEvents.FIELD_CHANGE, …)`) for input comfort only — a value filled
215
+ in from another, a field one table's forms leave out. No data rule there: the routes never see it.
216
+ - A table of more than a few columns that phones will read offers the cards and opens them there:
217
+ `displays: [{ id: "table" }, { id: "cards" }], mobileDisplay: "cards"`. Only a display the user
218
+ saved or the open view's own `display` overrides it: a `views.defaultView` that sets no display
219
+ still opens phones on the cards.
131
220
  - A table ordered by hand (`reorder: { field }`) moves rows on the grid and cards on the `cards`
132
221
  display alike; a `card.component` receives a `reorder` prop and `v-bind`s `reorder.handle`.
222
+ - A `cards` display whose cards need more room sets `card.minWidth` (a CSS length, `230px` by
223
+ default, the skeleton follows): cards stretch to fill the row, a short list's up to twice that.
224
+ - A `cards` display whose `card.component` is taller than the built-in card sets
225
+ `card.skeletonHeight` to its height (a CSS length): the loading placeholder takes it, so the
226
+ pagination footer does not drop when the cards land.
227
+ - A built-in card carries its row's actions top right (the grid row's buttons and … menu, same
228
+ rules and confirmations); a `card.component` opts in with `<component :is="rowActions" />`.
133
229
 
134
230
  ### Forms
135
231
 
136
- - A unit after a number field is `NumberType({ suffix: "$…days" })`; a character counter is
232
+ - A unit after a number field is `NumberType({ suffix: "$…days" })` (written in its table cells,
233
+ cards and read-only fields too); a character counter is
137
234
  `StringType({ maxLength, showCount: true })` — no custom `inputComponent` for either.
235
+ - A relation picker depending on another field of the form takes `filterBy: { field, from }`:
236
+ `RelationType({ dataApiController: SiteController, filterBy: { field: "customer", from: "customer" } })`
237
+ lists only the picked customer's sites, searches again when it changes and clears a pick made for
238
+ the previous one — no custom picker. `field` must be filterable on the related controller (it
239
+ throws at registration otherwise) — `docs/04.components/10.data-types.md`.
240
+ - A field whose value follows another one (stage → probability) takes a watch running
241
+ `FormFunctions.SET_FIELD_VALUE` with `{ targetField, valueMap: { won: 100, lost: 0 } }` (or a fixed
242
+ `value`) on `FIELD_CHANGE` keyed on the source `fieldId` — never a custom component. It writes on a
243
+ change only, never over the values a record opens with; a rule that must hold stays in the write
244
+ route — `docs/04.components/07.forms/0.index.md#setting-a-value-from-another-field`.
245
+ - A short number or text field (an estimate, a count, a code) takes `width: "compact"` on its
246
+ `NumberType` / `StringType` rather than filling the row; one bounded to 6 digits or a
247
+ `maxLength` of 16 or less is compact already, and `width: "full"` opts out. Phones keep the
248
+ full row.
138
249
  - A long sectioned `Form` groups its navigation with `FormSection.navGroup`, in the side list and
139
250
  the `sectionNav: "jump"` chips alike.
140
251
  - A module's own `inputComponent` submits its form, adds a validator and focuses a field with
@@ -145,7 +256,9 @@ row's ⋯ button — `docs/04.components/08.tables/0.index.md#pinned-rows`.
145
256
  ### Custom components
146
257
 
147
258
  - Name the record at the end of the breadcrumb with
148
- `usePageRecordLabel().setLabel(useDmsRoute().path, label)`.
259
+ `usePageRecordLabel().setLabel(useDmsRoute().path, label)`. A hidden detail page next to its
260
+ list (`project/:id` beside `projects`) declares `parent: ProjectsPage` in its menu options so
261
+ the breadcrumb shows the list before the record — `docs/02.building/04.navigation.md`.
149
262
  - Format through `useRegionalFormat()`; `useRegionalFormat({ locale: "format" })` writes in the
150
263
  locale of the DMS's texts (`en` → `en-GB`).
151
264
  - Bring a block into view with `scrollToBlock("tabs.statistics")` — never a DOM query.
@@ -63,7 +63,7 @@ export class SubmitRecipePage extends PageController("submit-recipe", { displayN
63
63
  ],
64
64
  submitUrl: "/api/recipes", // a route — often declared on this same class
65
65
  submitUrlMethod: HttpMethod.post,
66
- kind: "action", // sends something new each time; omit for a record form (save bar)
66
+ kind: "action", // sends something new each time; "create" for a form making a row; omit for a record form (save bar)
67
67
  });
68
68
  }
69
69
  ```
@@ -46,11 +46,33 @@ not survive orb updates.
46
46
  Only the project in `DMS_BACK_DIR`. The script records the pids it starts in
47
47
  `DMS_BACK_DIR/.antelope/dms-dev.pid`; without that file it matches only dev processes whose working
48
48
  directory or command line lies under `DMS_BACK_DIR`. Each process gets SIGTERM, then SIGKILL after
49
- `DMS_DEV_STOP_GRACE` seconds (default 10). Other projects' dev servers on the machine keep running,
49
+ `DMS_DEV_STOP_GRACE` seconds (default 10); on Windows, `taskkill /T /F` ([below](#windows)). Other projects' dev servers on the machine keep running,
50
50
  which is why the script replaces `pkill` by name (`pkill -9 node`, `pkill -f antelope-runner`).
51
51
 
52
+ `restart-back` and `restart-front` touch one server only: the pid the pid file records for it
53
+ (`backend` or `frontend`) and its process tree, or, when that pid is gone (the server crashed),
54
+ the processes of that server alone that the scan below finds. The other server keeps running.
55
+
52
56
  Run one `start` or `restart` at a time: a second concurrent call hits a port or lock conflict.
53
57
 
58
+ ## Windows
59
+
60
+ The script runs in Git Bash, MSYS2 or Cygwin. Their `ps` lists only their own processes and takes
61
+ no `-o`, and they have no `setsid`, while the dev servers run as native `node.exe` processes. So on
62
+ Windows the script:
63
+
64
+ - reads the Windows process table through PowerShell (`Get-CimInstance Win32_Process`: pid, parent
65
+ pid, creation time, command line), and maps the pids it recorded to Windows pids through
66
+ `/proc/<pid>/winpid`;
67
+ - follows parent pids for the tree (Windows has no process groups), counting only children created
68
+ after their parent, so that a process holding a dead parent's reused pid is left alone;
69
+ - stops each tree at once with `taskkill /T /F`: a console node process handles no SIGTERM, so
70
+ there is no grace period (`DMS_DEV_STOP_GRACE` is unused);
71
+ - without a pid file, matches only processes whose command line names `DMS_BACK_DIR`: a native
72
+ process exposes no working directory. Servers started through `pnpm` rarely do (only binaries
73
+ installed in the project's `node_modules` show its path), so start them with the script, which
74
+ records their pids.
75
+
54
76
  ## Pitfalls
55
77
 
56
78
  - **Zombie frontend processes.** The frontend CLI spawns children. `stop` signals the whole
@@ -20,5 +20,5 @@ Put secrets/per-deploy values in `envOverrides` (a framework feature); per-envir
20
20
  | --- | --- |
21
21
  | Pages, TableViews, the component builders | **dms-pages** (`docs/02.building/03.pages-and-components.md`, `docs/04.components/`) |
22
22
  | Auth on pages/routes, permissions, tenants | **dms-auth** (`docs/03.auth-and-tenancy/`) |
23
- | Hooks, notifications, realtime, replayable jobs, HTML render, export jobs | `docs/02.building/06.backend-services.md` |
23
+ | Hooks, notifications, realtime, replayable jobs, automation nodes, HTML render, export jobs | `docs/02.building/06.backend-services.md` |
24
24
  | Custom Vue in your `frontend-vue/` module | `docs/02.building/08.frontend-layer.md`, `docs/05.extending-the-dashboard/`, `docs/06.frontend-composables/` |
@@ -193,6 +193,8 @@ DMS_BACK_DIR=<resolved-path> bash "<skill-base-dir>/scripts/dms-dev.sh" restart
193
193
  | Command | Use when |
194
194
  | --- | --- |
195
195
  | `restart` | Hot reload cannot apply a change, or the state is unknown. |
196
+ | `restart-front` | The frontend crashed or hangs while the backend runs: only the frontend is stopped (if it runs) and started again. |
197
+ | `restart-back` | The backend crashed alone: only the backend is restarted, and the frontend keeps running. Run `restart-front` too if the frontend then serves stale layers. |
196
198
  | `start` | Nothing is running (fresh shell, after `stop`). |
197
199
  | `stop` | Before walking away, before destructive operations, on session cleanup. |
198
200
  | `status` | The user asks whether the DMS is running. |
@@ -202,7 +204,8 @@ The call returns once both servers print their ready line and reports the URLs t
202
204
  fails fast when a server exits early, otherwise after 180 s per server (`DMS_DEV_TIMEOUT`). The
203
205
  servers keep running detached. By default the script runs the project's `pnpm dev` and
204
206
  `pnpm frontend:dev` scripts (a project convention that expands to the two commands above);
205
- override them with `DMS_BACK_CMD` / `DMS_FRONT_CMD`.
207
+ override them with `DMS_BACK_CMD` / `DMS_FRONT_CMD`. It runs in bash on Linux and macOS, and in
208
+ Git Bash, MSYS2 or Cygwin on Windows ([DEV-SERVERS.md](DEV-SERVERS.md#windows)).
206
209
 
207
210
  When you hand off for manual testing, run `restart` yourself, wait for both ready lines, then tell
208
211
  the user what to click. Boot failures, stale frontends, a refused credential (401), stop scope and