@antelopejs/dms 0.9.7 → 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 (414) hide show
  1. package/CHANGELOG.md +114 -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 -45
  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/realtime.d.ts +13 -1
  117. package/dist/routes/realtime.js +114 -29
  118. package/dist/routes/realtime.js.map +1 -1
  119. package/dist/startup-config.d.ts +2 -0
  120. package/dist/startup-config.js +62 -0
  121. package/dist/startup-config.js.map +1 -0
  122. package/dist/store/interfaces.d.ts +3 -2
  123. package/dist/store/interfaces.js +16 -6
  124. package/dist/store/interfaces.js.map +1 -1
  125. package/dist/store/listing.js +24 -13
  126. package/dist/store/listing.js.map +1 -1
  127. package/dist/store/operations.js +4 -0
  128. package/dist/store/operations.js.map +1 -1
  129. package/dist/store/requirements.js +3 -2
  130. package/dist/store/requirements.js.map +1 -1
  131. package/dist/store/runtime.d.ts +10 -1
  132. package/dist/store/runtime.js +33 -6
  133. package/dist/store/runtime.js.map +1 -1
  134. package/dist/store/types.d.ts +10 -0
  135. package/dist/validation/auth.schema.d.ts +2 -2
  136. package/dist/validation/member-invite.schema.d.ts +2 -10
  137. package/dist/validation/member-invite.schema.js +2 -15
  138. package/dist/validation/member-invite.schema.js.map +1 -1
  139. package/frontend-vue/dms.frontend.ts +24 -5
  140. package/frontend-vue/dms.server.ts +17 -0
  141. package/frontend-vue/layers/dms-auth/server/accounts.ts +3 -4
  142. package/frontend-vue/layers/dms-core/app/build/composables/renderNow.ts +34 -0
  143. package/frontend-vue/layers/dms-core/app/build/composables/user/tablePreferences.ts +5 -1
  144. package/frontend-vue/layers/dms-core/app/build/utils/crossTab.ts +199 -0
  145. package/frontend-vue/layers/dms-core/app/build/utils/sharedRealtimeConnection.ts +410 -0
  146. package/frontend-vue/layers/dms-core/app/composables/auth/useApiData.ts +77 -12
  147. package/frontend-vue/layers/dms-core/app/composables/data-types/useDataType.ts +26 -0
  148. package/frontend-vue/layers/dms-core/app/composables/hydration/isHydratingComponent.ts +29 -0
  149. package/frontend-vue/layers/dms-core/app/composables/live/livePauseSource.ts +29 -0
  150. package/frontend-vue/layers/dms-core/app/composables/period/compareResolvers.ts +150 -9
  151. package/frontend-vue/layers/dms-core/app/composables/period/usePeriod.ts +6 -4
  152. package/frontend-vue/layers/dms-core/app/composables/period/usePeriodScope.ts +27 -1
  153. package/frontend-vue/layers/dms-core/app/composables/realtime/useUserRealtime.ts +256 -119
  154. package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +21 -8
  155. package/frontend-vue/layers/dms-core/app/composables/translation/useTranslation.ts +22 -5
  156. package/frontend-vue/layers/dms-core/app/plugins/dev-error-log.ts +16 -0
  157. package/frontend-vue/layers/dms-core/app/types/user.ts +6 -0
  158. package/frontend-vue/layers/dms-core/app/utils/composedText.ts +7 -2
  159. package/frontend-vue/layers/dms-core/app/utils/formatter.ts +166 -35
  160. package/frontend-vue/layers/dms-core/app/utils/url-interpolation.ts +18 -1
  161. package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +134 -2
  162. package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +134 -2
  163. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +3 -2
  164. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +41 -21
  165. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardPageBody.vue +9 -0
  166. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidebar.vue +4 -19
  167. package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +11 -3
  168. package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +18 -7
  169. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionBar.vue +8 -0
  170. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionsOutlet.vue +14 -0
  171. package/frontend-vue/layers/dms-layout/app/build/components/layout/RowSidePanel.vue +43 -82
  172. package/frontend-vue/layers/dms-layout/app/build/components/layout/SidebarUserMenu.vue +44 -3
  173. package/frontend-vue/layers/dms-layout/app/build/components/layout/UserIdentity.vue +11 -3
  174. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleCatalogTile.vue +132 -35
  175. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleManageMenu.vue +59 -0
  176. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleSourceLabel.vue +25 -0
  177. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreBanners.vue +73 -0
  178. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreOperation.vue +116 -0
  179. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreRequirements.vue +8 -3
  180. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreTile.vue +85 -207
  181. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTile.vue +10 -3
  182. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTileSkeleton.vue +68 -0
  183. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxDisplay.vue +24 -8
  184. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxItem.vue +8 -5
  185. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionTimeZoneInput.vue +1 -0
  186. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +19 -0
  187. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRoleEditor.ts +2 -1
  188. package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +31 -70
  189. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +11 -1
  190. package/frontend-vue/layers/dms-layout/app/build/utils/dev-reload-stream.ts +81 -0
  191. package/frontend-vue/layers/dms-layout/app/build/utils/module-store-catalog.ts +232 -36
  192. package/frontend-vue/layers/dms-layout/app/build/utils/modules-catalog.ts +122 -14
  193. package/frontend-vue/layers/dms-layout/app/composables/layout/useLayoutBanners.ts +32 -3
  194. package/frontend-vue/layers/dms-layout/app/composables/layout/usePageRecord.ts +50 -0
  195. package/frontend-vue/layers/dms-layout/app/composables/layout/useServedHeaderActions.ts +25 -7
  196. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleHistory.ts +3 -2
  197. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStore.ts +51 -4
  198. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStoreActions.ts +194 -0
  199. package/frontend-vue/layers/dms-layout/app/composables/page/usePageComponentPreload.ts +23 -3
  200. package/frontend-vue/layers/dms-layout/app/composables/page/usePageLayout.ts +4 -2
  201. package/frontend-vue/layers/dms-layout/app/composables/page/useSiteLayout.ts +6 -1
  202. package/frontend-vue/layers/dms-layout/app/custom-layouts/DefaultLayout.vue +9 -0
  203. package/frontend-vue/layers/dms-layout/app/custom-layouts/SettingsLayout.vue +9 -0
  204. package/frontend-vue/layers/dms-layout/app/custom-pages/modules-store.vue +291 -0
  205. package/frontend-vue/layers/dms-layout/app/custom-pages/modules.vue +87 -474
  206. package/frontend-vue/layers/dms-layout/app/middleware/module-routing.global.ts +3 -0
  207. package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +6 -22
  208. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-navigation.client.ts +2 -1
  209. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-personal-pages.client.ts +14 -44
  210. package/frontend-vue/layers/dms-layout/app/plugins/dms-dev-reload.client.ts +14 -9
  211. package/frontend-vue/layers/dms-layout/app/theme/form-controls.ts +9 -4
  212. package/frontend-vue/layers/dms-layout/app/theme/surfaces.ts +22 -6
  213. package/frontend-vue/layers/dms-layout/app/types/module-store.ts +9 -0
  214. package/frontend-vue/layers/dms-layout/app/types/page.ts +15 -1
  215. package/frontend-vue/layers/dms-layout/app/utils/account-menu.ts +11 -0
  216. package/frontend-vue/layers/dms-layout/app/utils/breadcrumb.ts +57 -0
  217. package/frontend-vue/layers/dms-layout/app/utils/pageQuery.ts +26 -0
  218. package/frontend-vue/layers/dms-layout/app/utils/pageRecord.ts +71 -0
  219. package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +39 -14
  220. package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +38 -13
  221. package/frontend-vue/layers/dms-ui/app/build/components/containers/TargetComponentTree.vue +31 -0
  222. package/frontend-vue/layers/dms-ui/app/build/components/containers/constants.ts +25 -0
  223. package/frontend-vue/layers/dms-ui/app/build/components/containers/drawer/DynamicDrawer.vue +244 -15
  224. package/frontend-vue/layers/dms-ui/app/build/components/containers/modal/DynamicModal.vue +42 -25
  225. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowHeader.vue +153 -0
  226. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowNotFound.vue +44 -0
  227. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/drawerRowHeader.ts +35 -0
  228. package/frontend-vue/layers/dms-ui/app/build/components/form/FormEntries.vue +44 -9
  229. package/frontend-vue/layers/dms-ui/app/build/components/form/FormErrorSummary.vue +11 -4
  230. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldControl.vue +38 -5
  231. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldNotes.vue +29 -5
  232. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSectionNav.vue +3 -1
  233. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSections.vue +106 -27
  234. package/frontend-vue/layers/dms-ui/app/build/components/table/Actions.vue +12 -4
  235. package/frontend-vue/layers/dms-ui/app/build/components/table/Empty.vue +4 -2
  236. package/frontend-vue/layers/dms-ui/app/build/components/table/FiltersRow.vue +38 -1
  237. package/frontend-vue/layers/dms-ui/app/build/components/table/Pagination.vue +55 -54
  238. package/frontend-vue/layers/dms-ui/app/build/components/table/RowSelection.vue +2 -1
  239. package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +396 -288
  240. package/frontend-vue/layers/dms-ui/app/build/components/table/Tabs.vue +2 -1
  241. package/frontend-vue/layers/dms-ui/app/build/components/table/Views.vue +2 -1
  242. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardAvatar.vue +59 -0
  243. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardGridSkeleton.vue +19 -2
  244. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardRowActions.vue +38 -0
  245. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +148 -104
  246. package/frontend-vue/layers/dms-ui/app/build/components/table-view/LiveHoldBanner.vue +17 -2
  247. package/frontend-vue/layers/dms-ui/app/build/composables/actions/bulkSelection.ts +43 -9
  248. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowComponentOptions.ts +76 -0
  249. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +172 -27
  250. package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +270 -46
  251. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/confirmDialogTexts.ts +2 -0
  252. package/frontend-vue/layers/dms-ui/app/build/composables/containers/closingLayers.ts +186 -0
  253. package/frontend-vue/layers/dms-ui/app/build/composables/containers/context.ts +14 -0
  254. package/frontend-vue/layers/dms-ui/app/build/composables/containers/drawerSize.ts +229 -0
  255. package/frontend-vue/layers/dms-ui/app/build/composables/containers/useResizableSize.ts +175 -0
  256. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +18 -35
  257. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/numberSuffix.ts +47 -0
  258. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +99 -24
  259. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerFieldTypes.ts +2 -1
  260. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationFilter.ts +75 -0
  261. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationRows.ts +71 -0
  262. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationValue.ts +39 -0
  263. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +3 -3
  264. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +6 -2
  265. package/frontend-vue/layers/dms-ui/app/build/composables/form/createFormFields.ts +15 -0
  266. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldSaved.ts +40 -0
  267. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldValueRule.ts +62 -0
  268. package/frontend-vue/layers/dms-ui/app/build/composables/form/formEntryContext.ts +5 -0
  269. package/frontend-vue/layers/dms-ui/app/build/composables/form/formFooter.ts +42 -7
  270. package/frontend-vue/layers/dms-ui/app/build/composables/form/formLayout.ts +106 -4
  271. package/frontend-vue/layers/dms-ui/app/build/composables/form/formSections.ts +32 -0
  272. package/frontend-vue/layers/dms-ui/app/build/composables/form/readonlyValue.ts +19 -0
  273. package/frontend-vue/layers/dms-ui/app/build/composables/form/registerFormFunctions.ts +27 -0
  274. package/frontend-vue/layers/dms-ui/app/build/composables/form/repeaterTable.ts +65 -0
  275. package/frontend-vue/layers/dms-ui/app/build/composables/form/serverFieldErrors.ts +49 -0
  276. package/frontend-vue/layers/dms-ui/app/build/composables/form/toasterClearance.ts +118 -0
  277. package/frontend-vue/layers/dms-ui/app/build/composables/form/useInstantForm.ts +12 -1
  278. package/frontend-vue/layers/dms-ui/app/build/composables/live/currentPageLive.ts +41 -3
  279. package/frontend-vue/layers/dms-ui/app/build/composables/live/livePoller.ts +10 -2
  280. package/frontend-vue/layers/dms-ui/app/build/composables/live/pageReadClock.ts +28 -0
  281. package/frontend-vue/layers/dms-ui/app/build/composables/live/shortcuts.ts +1 -1
  282. package/frontend-vue/layers/dms-ui/app/build/composables/live/usePageLiveHost.ts +17 -3
  283. package/frontend-vue/layers/dms-ui/app/build/composables/live/useUpdatedLabel.ts +38 -0
  284. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/pageToolbarContext.ts +75 -0
  285. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/toolbarControlHeight.ts +29 -0
  286. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodComparison.ts +52 -0
  287. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodDisplay.ts +21 -0
  288. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodShortLabels.ts +28 -0
  289. package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodDraft.ts +1 -0
  290. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRelationFilterLabels.ts +73 -0
  291. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRowScrollAnchor.ts +106 -0
  292. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +9 -0
  293. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableColumns.ts +1 -2
  294. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/archivedCount.ts +31 -0
  295. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/filterEditorValue.ts +38 -0
  296. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/formatFilterValue.ts +33 -2
  297. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/scrollEdges.ts +31 -0
  298. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useCardFields.ts +33 -0
  299. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useMobileDisplay.ts +48 -0
  300. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useScrolledPastTop.ts +41 -18
  301. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableFooter.ts +3 -2
  302. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLinkedVisit.ts +78 -0
  303. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLiveHold.ts +135 -22
  304. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +56 -25
  305. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +77 -32
  306. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViews.ts +86 -10
  307. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/bulkActions.ts +14 -4
  308. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/card.ts +127 -2
  309. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/compareValues.ts +13 -0
  310. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/expandedRows.ts +28 -0
  311. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/groupedRows.ts +114 -1
  312. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/linkedArrival.ts +308 -0
  313. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/locateRow.ts +106 -0
  314. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pageArrival.ts +34 -0
  315. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pinnedRows.ts +17 -0
  316. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/quickFilters.ts +41 -33
  317. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +24 -8
  318. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableCounts.ts +113 -0
  319. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableQuery.ts +27 -4
  320. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +22 -6
  321. package/frontend-vue/layers/dms-ui/app/build/utils/addressSuggestions.ts +49 -0
  322. package/frontend-vue/layers/dms-ui/app/build/utils/eyebrow.ts +12 -0
  323. package/frontend-vue/layers/dms-ui/app/build/utils/fieldOptionsI18n.ts +51 -11
  324. package/frontend-vue/layers/dms-ui/app/build/utils/inputWidth.ts +53 -0
  325. package/frontend-vue/layers/dms-ui/app/build/utils/numberAdjustment.ts +6 -3
  326. package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +19 -5
  327. package/frontend-vue/layers/dms-ui/app/build/utils/scrollWithin.ts +99 -0
  328. package/frontend-vue/layers/dms-ui/app/build/utils/urlVariables.ts +36 -14
  329. package/frontend-vue/layers/dms-ui/app/components/PasswordStrength.vue +1 -1
  330. package/frontend-vue/layers/dms-ui/app/components/RecursiveComponent.vue +9 -1
  331. package/frontend-vue/layers/dms-ui/app/components/blocks/LiveToggleBlock.vue +80 -32
  332. package/frontend-vue/layers/dms-ui/app/components/blocks/PageToolbarBlock.vue +137 -0
  333. package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +5 -0
  334. package/frontend-vue/layers/dms-ui/app/components/chart/ApexChartHost.vue +16 -2
  335. package/frontend-vue/layers/dms-ui/app/components/chart/Chart.vue +24 -5
  336. package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +41 -23
  337. package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +1 -1
  338. package/frontend-vue/layers/dms-ui/app/components/container-footer/ContainerFooter.vue +34 -0
  339. package/frontend-vue/layers/dms-ui/app/components/field-row/FieldRow.vue +25 -2
  340. package/frontend-vue/layers/dms-ui/app/components/flow-canvas/FlowCanvas.vue +2 -2
  341. package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +118 -36
  342. package/frontend-vue/layers/dms-ui/app/components/form/components/DatePicker.vue +20 -1
  343. package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +13 -1
  344. package/frontend-vue/layers/dms-ui/app/components/form/components/Image.vue +8 -3
  345. package/frontend-vue/layers/dms-ui/app/components/form/components/InputAddress.vue +53 -5
  346. package/frontend-vue/layers/dms-ui/app/components/form/components/InputCode.vue +29 -5
  347. package/frontend-vue/layers/dms-ui/app/components/form/components/InputNumber.vue +45 -8
  348. package/frontend-vue/layers/dms-ui/app/components/form/components/InputPercentage.vue +28 -5
  349. package/frontend-vue/layers/dms-ui/app/components/form/components/InputSecret.vue +5 -0
  350. package/frontend-vue/layers/dms-ui/app/components/form/components/InputText.vue +19 -2
  351. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTime.vue +2 -1
  352. package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +205 -65
  353. package/frontend-vue/layers/dms-ui/app/components/form/components/Repeater.vue +80 -30
  354. package/frontend-vue/layers/dms-ui/app/components/form/components/RepeaterTable.vue +203 -0
  355. package/frontend-vue/layers/dms-ui/app/components/form/components/Select.vue +4 -2
  356. package/frontend-vue/layers/dms-ui/app/components/grid/GridRow.vue +11 -2
  357. package/frontend-vue/layers/dms-ui/app/components/key-value-list/KeyValueList.vue +79 -70
  358. package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +117 -21
  359. package/frontend-vue/layers/dms-ui/app/components/meter/Meter.vue +2 -1
  360. package/frontend-vue/layers/dms-ui/app/components/period/PeriodSelector.vue +113 -34
  361. package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +14 -2
  362. package/frontend-vue/layers/dms-ui/app/components/section-header/Eyebrow.vue +6 -1
  363. package/frontend-vue/layers/dms-ui/app/components/segmented/Segmented.vue +13 -0
  364. package/frontend-vue/layers/dms-ui/app/components/stat-group/StatGroup.vue +52 -3
  365. package/frontend-vue/layers/dms-ui/app/components/tab/Tab.vue +2 -1
  366. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanBoard.vue +45 -35
  367. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanDisplay.vue +4 -1
  368. package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +410 -96
  369. package/frontend-vue/layers/dms-ui/app/components/top-list/TopListCard.vue +33 -5
  370. package/frontend-vue/layers/dms-ui/app/composables/chart/apexCategoryLabels.ts +68 -0
  371. package/frontend-vue/layers/dms-ui/app/composables/chart/apexDatetimeBuckets.ts +306 -0
  372. package/frontend-vue/layers/dms-ui/app/composables/chart/formatValue.ts +4 -3
  373. package/frontend-vue/layers/dms-ui/app/composables/chart/heatmapColors.ts +93 -0
  374. package/frontend-vue/layers/dms-ui/app/composables/chart/localizeSeries.ts +62 -0
  375. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.ts +116 -8
  376. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.types.ts +7 -0
  377. package/frontend-vue/layers/dms-ui/app/composables/containers/types.ts +84 -1
  378. package/frontend-vue/layers/dms-ui/app/composables/containers/useDrawer.ts +69 -8
  379. package/frontend-vue/layers/dms-ui/app/composables/form/types/field-saved.ts +11 -0
  380. package/frontend-vue/layers/dms-ui/app/composables/form/types/field.ts +4 -0
  381. package/frontend-vue/layers/dms-ui/app/composables/form/types/functions.ts +1 -0
  382. package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +142 -21
  383. package/frontend-vue/layers/dms-ui/app/composables/live/usePageLive.ts +11 -4
  384. package/frontend-vue/layers/dms-ui/app/composables/page-toolbar/usePageToolbarSize.ts +30 -0
  385. package/frontend-vue/layers/dms-ui/app/composables/table-view/kanban.ts +4 -2
  386. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +22 -3
  387. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +4 -0
  388. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +24 -1
  389. package/frontend-vue/layers/dms-ui/app/plugins/closing-layers.client.ts +10 -0
  390. package/frontend-vue/layers/dms-ui/app/plugins/live-pause-source.ts +15 -0
  391. package/frontend-vue/layers/dms-ui/app/plugins/register.ts +2 -0
  392. package/frontend-vue/layers/dms-ui/app/types/input-number.ts +3 -2
  393. package/frontend-vue/layers/dms-ui/app/types/page-toolbar.ts +7 -0
  394. package/frontend-vue/layers/dms-ui/app/types/row-action.ts +0 -2
  395. package/frontend-vue/layers/dms-ui/app/types/row-navigation.ts +17 -0
  396. package/frontend-vue/layers/dms-ui/app/types/table/query.ts +2 -1
  397. package/frontend-vue/layers/dms-ui/app/utils/blockRefresh.ts +3 -1
  398. package/frontend-vue/layers/dms-ui/app/utils/componentTree.ts +24 -0
  399. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +16 -4
  400. package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +16 -4
  401. package/frontend-vue/package.json +2 -2
  402. package/package.json +7 -6
  403. package/skills/dms/SKILL.md +1 -1
  404. package/skills/dms-auth/SKILL.md +5 -3
  405. package/skills/dms-best-practices/REFERENCE.md +2 -0
  406. package/skills/dms-best-practices/SKILL.md +4 -0
  407. package/skills/dms-module/SKILL.md +3 -2
  408. package/skills/dms-pages/REFERENCE.md +125 -16
  409. package/skills/dms-pages/SKILL.md +1 -1
  410. package/skills/dms-project/DEV-SERVERS.md +23 -1
  411. package/skills/dms-project/REFERENCE.md +1 -1
  412. package/skills/dms-project/SKILL.md +4 -1
  413. package/skills/dms-project/scripts/dms-dev.sh +205 -17
  414. package/frontend-vue/layers/dms-core/app/composables/period/periodRenderNow.ts +0 -42
@@ -3,6 +3,15 @@ import { APEX_TYPE_CONFIGS } from "./apexTypeConfigs";
3
3
  import { buildAnnotations } from "./apexAnnotations";
4
4
  import { buildPlotOptions, ringFitsSliceLabels } from "./apexPlotOptions";
5
5
  import { buildAutoYRange, formatPlainAxisValue } from "./apexYRange";
6
+ import { heatmapRangeColors, isDarkSurface } from "./heatmapColors";
7
+ import { thinnedCategoryFormatter } from "./apexCategoryLabels";
8
+ import {
9
+ bucketAxisFormatter,
10
+ bucketTooltipFormatter,
11
+ detectDatetimeBuckets,
12
+ toBucketSeries,
13
+ type DatetimeBuckets,
14
+ } from "./apexDatetimeBuckets";
6
15
  import { isReducedMotionActive } from "../../build/utils/accessibilityPreferences";
7
16
  import {
8
17
  axisLabelStyle,
@@ -21,6 +30,7 @@ import {
21
30
  readThemeBorderAccented,
22
31
  readThemeHighlighted,
23
32
  readThemeMuted,
33
+ readThemeSurface,
24
34
  } from "./useChartTheme";
25
35
  import type {
26
36
  ChartSeries,
@@ -287,6 +297,12 @@ function applySeriesStroke(
287
297
  }
288
298
 
289
299
  const HIGH_CONTRAST_YAXIS_TYPES: ChartType[] = ["radar"];
300
+ /**
301
+ * Charts whose Y axis lists categories (a heatmap's rows: its series names)
302
+ * rather than values: a card's value format would write each name as NaN.
303
+ * Their values are still formatted, in the tooltip.
304
+ */
305
+ const CATEGORY_YAXIS_TYPES: ChartType[] = ["heatmap"];
290
306
 
291
307
  function buildYAxis(
292
308
  input: UseApexChartInput,
@@ -303,16 +319,43 @@ function buildYAxis(
303
319
  yaxis.min = input.yRange.min;
304
320
  yaxis.max = input.yRange.max;
305
321
  }
322
+ const valueFormatter = CATEGORY_YAXIS_TYPES.includes(input.type)
323
+ ? undefined
324
+ : input.yAxisFormatter;
306
325
  (yaxis.labels as Record<string, unknown>).formatter =
307
- input.yAxisFormatter ?? formatPlainAxisValue;
326
+ valueFormatter ?? formatPlainAxisValue;
308
327
  return yaxis;
309
328
  }
310
329
 
330
+ /**
331
+ * Charts whose category labels ApexCharts never thins, whatever
332
+ * `hideOverlappingLabels` says: the chart thins them itself.
333
+ */
334
+ const SELF_THINNED_XAXIS_TYPES: ChartType[] = ["heatmap"];
335
+
336
+ function thinsOwnXLabels(input: UseApexChartInput): boolean {
337
+ const settings = input.xAxis;
338
+ return (
339
+ SELF_THINNED_XAXIS_TYPES.includes(input.type) &&
340
+ (input.xaxisType ?? "category") === "category" &&
341
+ settings?.hideOverlappingLabels !== false &&
342
+ settings?.tickAmount === undefined &&
343
+ !settings?.rotate
344
+ );
345
+ }
346
+
347
+ function xLabelFormatter(input: UseApexChartInput): unknown {
348
+ if (thinsOwnXLabels(input))
349
+ return thinnedCategoryFormatter(input.xAxisFormatter);
350
+ return input.xAxisFormatter;
351
+ }
352
+
311
353
  function buildXAxis(
312
354
  input: UseApexChartInput,
313
355
  theme: ApexThemeColors,
314
356
  ): Record<string, unknown> {
315
357
  const settings = input.xAxis;
358
+ const formatter = xLabelFormatter(input);
316
359
  const xaxis: Record<string, unknown> = {
317
360
  type: input.xaxisType ?? "category",
318
361
  axisBorder: { show: false },
@@ -330,7 +373,7 @@ function buildXAxis(
330
373
  settings?.datetimeFormat !== undefined
331
374
  ? { format: settings.datetimeFormat }
332
375
  : {}),
333
- ...(input.xAxisFormatter ? { formatter: input.xAxisFormatter } : {}),
376
+ ...(formatter ? { formatter } : {}),
334
377
  },
335
378
  crosshairs: {
336
379
  stroke: { color: readThemeBorderAccented(), dashArray: CROSSHAIR_DASH },
@@ -568,6 +611,12 @@ function buildValueBasedRanges(
568
611
  });
569
612
  }
570
613
 
614
+ /**
615
+ * Several colours split a heatmap's values into ranges, one colour each,
616
+ * laid over the card surface from faint to full: low values fade into the
617
+ * card in either theme. Apex's own shading is off there, as it would lighten
618
+ * each range towards white again.
619
+ */
571
620
  function applyValueBasedColorScale(
572
621
  plotOptions: Record<string, unknown>,
573
622
  input: UseApexChartInput,
@@ -577,15 +626,37 @@ function applyValueBasedColorScale(
577
626
  if (!VALUE_SCALED_TYPES.includes(input.type)) return;
578
627
  if (input.distributed) return;
579
628
  if (palette.length < 2) return;
580
- const ranges = buildValueBasedRanges(extractNumericValues(series), palette);
581
- if (ranges.length === 0) return;
582
629
  const subKey = VALUE_SCALED_PLOT_KEY[input.type]!;
583
630
  const subOptions =
584
631
  (plotOptions[subKey] as Record<string, unknown> | undefined) ?? {};
632
+ const colors = heatmapRangeColors(
633
+ palette,
634
+ readThemeSurface(),
635
+ Number(subOptions.shadeIntensity ?? 1),
636
+ );
637
+ const ranges = buildValueBasedRanges(extractNumericValues(series), colors);
638
+ if (ranges.length === 0) return;
585
639
  subOptions.colorScale = { ranges };
640
+ subOptions.enableShades = false;
586
641
  plotOptions[subKey] = subOptions;
587
642
  }
588
643
 
644
+ /**
645
+ * A heatmap with one colour, or one per row (`distributed`), is shaded by
646
+ * Apex: towards white unless told the theme is dark, where it shades towards
647
+ * black, the side of a dark card. Only the shading reads this mode: every
648
+ * colour Apex would take from it is set explicitly.
649
+ */
650
+ function applyHeatmapThemeMode(
651
+ baseOptions: Record<string, unknown>,
652
+ input: UseApexChartInput,
653
+ ): void {
654
+ if (!VALUE_SCALED_TYPES.includes(input.type)) return;
655
+ baseOptions.theme = {
656
+ mode: isDarkSurface(readThemeSurface()) ? "dark" : "light",
657
+ };
658
+ }
659
+
589
660
  function applyOptionalSections(
590
661
  baseOptions: Record<string, unknown>,
591
662
  input: UseApexChartInput,
@@ -595,6 +666,7 @@ function applyOptionalSections(
595
666
  ): void {
596
667
  const plotOptions = buildPlotOptions(input);
597
668
  applyValueBasedColorScale(plotOptions, input, series, palette);
669
+ applyHeatmapThemeMode(baseOptions, input);
598
670
  if (Object.keys(plotOptions).length > 0)
599
671
  baseOptions.plotOptions = plotOptions;
600
672
 
@@ -609,18 +681,48 @@ function applyOptionalSections(
609
681
  function projectSeries(
610
682
  input: UseApexChartInput,
611
683
  isCircular: boolean,
684
+ buckets: DatetimeBuckets | null,
612
685
  ): ChartSeries[] {
613
686
  if (isCircular) return [];
614
687
  void input.themeRevision;
615
- const series =
688
+ const mixed =
616
689
  input.type === "mixed"
617
690
  ? applyMixedSeriesDefs(input.series, input.seriesDefs)
618
691
  : input.series;
692
+ const series = buckets ? toBucketSeries(mixed, buckets) : mixed;
619
693
  return asComparisonLines(series, input).map((entry) =>
620
694
  entry.color ? { ...entry, color: resolveChartColor(entry.color) } : entry,
621
695
  );
622
696
  }
623
697
 
698
+ /**
699
+ * Calendar buckets on a datetime axis become one category each: a column
700
+ * per month (or day), evenly spaced, under one label, the tooltip naming the
701
+ * whole bucket.
702
+ */
703
+ function applyDatetimeBuckets(
704
+ options: Record<string, unknown>,
705
+ input: UseApexChartInput,
706
+ buckets: DatetimeBuckets | null,
707
+ ): void {
708
+ if (!buckets) return;
709
+ const xaxis = options.xaxis as Record<string, unknown>;
710
+ const { format: _datetimeFormat, ...labels } = xaxis.labels as Record<
711
+ string,
712
+ unknown
713
+ >;
714
+ options.xaxis = {
715
+ ...xaxis,
716
+ type: "category",
717
+ labels: { ...labels, formatter: bucketAxisFormatter(buckets, input) },
718
+ };
719
+ const tooltip = options.tooltip as Record<string, unknown>;
720
+ options.tooltip = {
721
+ ...tooltip,
722
+ x: { formatter: bucketTooltipFormatter(buckets, input) },
723
+ };
724
+ }
725
+
624
726
  /**
625
727
  * On an area chart the comparison is drawn as a bare line (v2): Apex takes a
626
728
  * fill's opacity from an rgba colour over any fill setting, so an unfilled
@@ -700,6 +802,7 @@ function buildChartOptions(
700
802
  value: UseApexChartInput,
701
803
  cfg: (typeof APEX_TYPE_CONFIGS)[ChartType],
702
804
  finalSeries: ChartSeries[],
805
+ buckets: DatetimeBuckets | null,
703
806
  ): Record<string, unknown> {
704
807
  void value.themeRevision;
705
808
  const ctx = buildChartOptionsContext(value, cfg, finalSeries);
@@ -725,6 +828,7 @@ function buildChartOptions(
725
828
  finalSeries,
726
829
  ctx.baseColors,
727
830
  );
831
+ applyDatetimeBuckets(baseOptions, value, buckets);
728
832
  return injectRawOptions(baseOptions, value.rawOptions);
729
833
  }
730
834
 
@@ -732,8 +836,9 @@ export function useApexChart(
732
836
  input: () => UseApexChartInput,
733
837
  ): UseApexChartOutput {
734
838
  const config = computed(() => APEX_TYPE_CONFIGS[input().type]);
839
+ const buckets = computed(() => detectDatetimeBuckets(input()));
735
840
  const finalSeries = computed<ChartSeries[]>(() =>
736
- projectSeries(input(), config.value.isCircular),
841
+ projectSeries(input(), config.value.isCircular, buckets.value),
737
842
  );
738
843
 
739
844
  const series = computed<unknown>(() => {
@@ -745,9 +850,12 @@ export function useApexChart(
745
850
  });
746
851
 
747
852
  const options = computed<Record<string, unknown>>(() =>
748
- buildChartOptions(input(), config.value, finalSeries.value),
853
+ buildChartOptions(input(), config.value, finalSeries.value, buckets.value),
749
854
  );
750
855
 
751
856
  const apexType = computed(() => resolveApexType(input()));
752
- return { apexType, options, series };
857
+ const sourcePointIndex = (seriesIndex: number, dataPointIndex: number) =>
858
+ buckets.value?.sourceIndexes[seriesIndex]?.[dataPointIndex] ??
859
+ dataPointIndex;
860
+ return { apexType, options, series, sourcePointIndex };
753
861
  }
@@ -72,6 +72,8 @@ export interface UseApexChartInput {
72
72
  xAxis?: ChartXAxis;
73
73
  xAxisFormatter?: ChartXAxisFormatter;
74
74
  yAxisFormatter?: (value: number) => string;
75
+ /** The reader's locale, for the dates the chart writes itself. */
76
+ locale?: string;
75
77
  onDataPointClick?: ApexClickHandler;
76
78
  }
77
79
 
@@ -79,4 +81,9 @@ export interface UseApexChartOutput {
79
81
  apexType: ComputedRef<string>;
80
82
  options: ComputedRef<Record<string, unknown>>;
81
83
  series: ComputedRef<unknown>;
84
+ /**
85
+ * The index, in the series as given, of the point Apex drew at
86
+ * `dataPointIndex` (they differ when the chart lays dates out in buckets).
87
+ */
88
+ sourcePointIndex: (seriesIndex: number, dataPointIndex: number) => number;
82
89
  }
@@ -1,5 +1,6 @@
1
1
  import type { Component } from "vue";
2
2
  import type { ModalSize } from "../../types/modal";
3
+ import type { RowNavigation } from "../../types/row-navigation";
3
4
 
4
5
  /**
5
6
  * Side from which a {@link DrawerOptions} drawer slides in.
@@ -43,6 +44,71 @@ export interface ContainerOptions {
43
44
  /** Options accepted by {@link useDrawer}'s `open`. */
44
45
  export interface DrawerOptions extends ContainerOptions {
45
46
  direction?: DrawerDirection;
47
+ /**
48
+ * Width a `left` / `right` drawer opens at from `lg`: a modal's width at
49
+ * that size (`sm` 384px ... `5xl` 1024px), `full` the whole window; 600px
50
+ * without one, capped to the window. Below `lg` an unsized side drawer is
51
+ * 440px wide, and on a phone every side drawer, sized or not, leaves a 2rem
52
+ * strip of backdrop (only `full` fills the screen). A `top` / `bottom`
53
+ * drawer ignores it.
54
+ */
55
+ size?: ModalSize;
56
+ /**
57
+ * The key the size the user drags the drawer to is remembered under, on
58
+ * this device (a cookie): the same drawer opens again at that size. Sizes
59
+ * are kept per axis, so a side and a bottom drawer may share a key.
60
+ * Defaults to `containerId`, else to the body component's name (its
61
+ * `name`, or the file name of a `<script setup>` component): a drawer keeps
62
+ * its size without one. Set it when one component opens drawers that
63
+ * should not share a size, or when an anonymous component (a render
64
+ * function, an async wrapper) or a per-opening `containerId` would forget.
65
+ */
66
+ sizeKey?: string;
67
+ /**
68
+ * Draws the DMS's row header in place of the drawer's own title, as on a
69
+ * row action's drawer: the row's title, its position ("4 of 50") and
70
+ * previous / next, next to the close button; J and K step while the
71
+ * drawer is open. For a drawer a module opens on a row of its own list.
72
+ */
73
+ rowHeader?: DrawerRowHeader;
74
+ }
75
+
76
+ /**
77
+ * The DMS's row header over a drawer opened with {@link useDrawer}. Patch it
78
+ * (`patch({ rowHeader })`) as the drawer steps to another row.
79
+ */
80
+ export interface DrawerRowHeader {
81
+ /** The row's title; the drawer's `title` without one. */
82
+ title?: string;
83
+ /**
84
+ * i18n key (`$`-prefixed) of the position, receiving `{ index, total }`
85
+ * (1-based, grouped as the locale does); "{index} of {total}" without one.
86
+ */
87
+ positionLabel?: string;
88
+ /**
89
+ * The row's place among the rows it steps through: the position, the
90
+ * previous / next buttons and J / K call its `prev()` and `next()`. No
91
+ * position nor buttons without one.
92
+ */
93
+ navigation?: RowNavigation;
94
+ /** Classes added to the title's (`font-mono` for a key); its size stays. */
95
+ titleClass?: string;
96
+ /**
97
+ * Wraps the title only after this separator (`"."` for a dotted key): each
98
+ * segment keeps the separator that follows it, a `<wbr>` between them.
99
+ */
100
+ titleBreakAfter?: string;
101
+ /**
102
+ * Text after the position, on its line after a "·", cut at its end (the
103
+ * whole text in its tooltip): "12 of 1,338 · helio › catalog".
104
+ */
105
+ subtitle?: string;
106
+ /** Classes added to the subtitle's (`font-mono`). */
107
+ subtitleClass?: string;
108
+ /** Drawn under the position line, in the title's column (pills, hints). */
109
+ component?: Component;
110
+ /** Props passed to `component`. */
111
+ componentOptions?: Record<string, unknown>;
46
112
  }
47
113
 
48
114
  /** Options accepted by {@link useModal}'s `open`. */
@@ -67,6 +133,23 @@ export interface ContainerInstance<Result = unknown> {
67
133
  export type ContainerPatch = Partial<
68
134
  Pick<
69
135
  ContainerOptions,
70
- "title" | "description" | "componentOptions" | "componentKey"
136
+ | "title"
137
+ | "description"
138
+ | "componentOptions"
139
+ | "componentKey"
140
+ | "headerComponentOptions"
71
141
  >
72
142
  >;
143
+
144
+ /**
145
+ * What an open drawer can change in place: a container's, and the row
146
+ * header it was opened with (`rowHeader`), replaced as a whole.
147
+ */
148
+ export type DrawerPatch = ContainerPatch & Pick<DrawerOptions, "rowHeader">;
149
+
150
+ /** The handle of a drawer opened with {@link useDrawer}. */
151
+ export interface DrawerInstance<Result = unknown>
152
+ extends Omit<ContainerInstance<Result>, "patch"> {
153
+ /** Updates the open drawer: its texts, its body, its row header. */
154
+ patch: (options: DrawerPatch) => void;
155
+ }
@@ -1,9 +1,31 @@
1
+ import { getCurrentInstance } from "vue";
1
2
  import DynamicDrawer from "../../build/components/containers/drawer/DynamicDrawer.vue";
3
+ import DmsRowHeader from "../../build/components/containers/row/RowHeader.vue";
4
+ import { drawerRowHeaderProps } from "../../build/components/containers/row/drawerRowHeader";
5
+ import { listenRowSteps } from "../../build/composables/actions/rowNavigation";
6
+ import { DMS_OWN_DRAWER } from "../../build/composables/containers/context";
7
+ import { componentSizeKey } from "../../build/composables/containers/drawerSize";
2
8
  import { openDynamicContainer } from "./openDynamicContainer";
3
- import type { ContainerInstance, DrawerOptions } from "./types";
9
+ import type {
10
+ DrawerInstance,
11
+ DrawerOptions,
12
+ DrawerPatch,
13
+ DrawerRowHeader,
14
+ } from "./types";
4
15
 
5
16
  const DRAWER_ID_PREFIX = "drawer";
6
17
 
18
+ /** What `useDrawer` hands the drawer besides its options. */
19
+ interface DrawerCallerContext {
20
+ /** The provides of the component that called `useDrawer` (see DynamicDrawer). */
21
+ callerProvides?: object;
22
+ }
23
+
24
+ /** The part of a component instance holding what it and its ancestors provide. */
25
+ interface InstanceProvides {
26
+ provides?: object;
27
+ }
28
+
7
29
  /**
8
30
  * Public composable to open a DMS-themed drawer from any module that extends the
9
31
  * layer. Wraps the internal DynamicDrawer container; `open` returns a handle
@@ -11,16 +33,55 @@ const DRAWER_ID_PREFIX = "drawer";
11
33
  */
12
34
  export function useDrawer() {
13
35
  const overlay = useOverlay();
36
+ // The drawer mounts under the app's overlay provider, outside the caller's
37
+ // tree: it inherits what the caller provides, as a drawer written in the
38
+ // caller's template does. Read at each opening, as the caller may provide
39
+ // after calling `useDrawer`. Vue keeps them in the instance's `provides`,
40
+ // which its public types do not list.
41
+ const caller = getCurrentInstance() as InstanceProvides | null;
14
42
 
15
43
  function open<Result = unknown>(
16
44
  options: DrawerOptions,
17
- ): ContainerInstance<Result> {
18
- return openDynamicContainer<Result, DrawerOptions>(
19
- overlay,
20
- DynamicDrawer,
21
- DRAWER_ID_PREFIX,
22
- options,
23
- );
45
+ ): DrawerInstance<Result> {
46
+ const { rowHeader, ...containerOptions } = options;
47
+ // The row header follows the title and the row it was last patched with.
48
+ let title = options.title;
49
+ let header: DrawerRowHeader | undefined = rowHeader;
50
+ const headerProps = () => header && drawerRowHeaderProps(header, title);
51
+ const instance = openDynamicContainer<
52
+ Result,
53
+ DrawerOptions & DrawerCallerContext
54
+ >(overlay, DynamicDrawer, DRAWER_ID_PREFIX, {
55
+ ...containerOptions,
56
+ // The DMS's own drawers keep the app's provides only.
57
+ callerProvides: DMS_OWN_DRAWER in options ? undefined : caller?.provides,
58
+ ...(rowHeader && {
59
+ headerComponent: DmsRowHeader,
60
+ headerComponentOptions: headerProps(),
61
+ }),
62
+ sizeKey:
63
+ options.sizeKey ??
64
+ options.containerId ??
65
+ componentSizeKey(options.component),
66
+ });
67
+ if (!rowHeader) {
68
+ // Without a row header to update, a patch is a container's.
69
+ return {
70
+ ...instance,
71
+ patch: ({ rowHeader: _rowHeader, ...patch }: DrawerPatch) =>
72
+ instance.patch(patch),
73
+ };
74
+ }
75
+ const stopSteps = listenRowSteps(() => header?.navigation);
76
+ instance.result.then(stopSteps, stopSteps);
77
+ return {
78
+ ...instance,
79
+ patch: ({ rowHeader: nextHeader, ...patch }: DrawerPatch) => {
80
+ title = patch.title ?? title;
81
+ header = nextHeader ?? header;
82
+ instance.patch({ ...patch, headerComponentOptions: headerProps() });
83
+ },
84
+ };
24
85
  }
25
86
 
26
87
  return { open };
@@ -0,0 +1,11 @@
1
+ import type { InjectionKey } from "vue";
2
+
3
+ /**
4
+ * Makes `value` the saved value of the field `id`: a control whose value the
5
+ * server already stored on its own (a rotated secret) is not a change left to
6
+ * save, and "Discard" keeps it.
7
+ */
8
+ export type MarkFieldSaved = (id: string, value: unknown) => void;
9
+
10
+ export const FORM_FIELD_SAVED_KEY: InjectionKey<MarkFieldSaved> =
11
+ Symbol("form-field-saved");
@@ -28,9 +28,13 @@ export interface FormField {
28
28
  disabled?: boolean;
29
29
  /** Shown, not edited: `true`, or with a pill and a link. */
30
30
  readonly?: boolean | FormFieldReadonly;
31
+ /** A create form shows it read-only and empty, rather than leaving it out. */
32
+ showEmptyOnCreate?: boolean;
31
33
  required?: boolean;
32
34
  type?: string;
33
35
  defaultValue?: FormFieldValue;
36
+ /** "Module default · Use default" while it holds something else. */
37
+ offersDefault?: boolean;
34
38
  localized?: boolean;
35
39
  }
36
40
 
@@ -2,4 +2,5 @@ export const FormFunctions = {
2
2
  SET_FIELD_DISABLED: "DmsComponent.Form.SetFieldDisabled",
3
3
  SET_FIELD_HIDDEN: "DmsComponent.Form.SetFieldHidden",
4
4
  SET_FIELD_REQUIRED: "DmsComponent.Form.SetFieldRequired",
5
+ SET_FIELD_VALUE: "DmsComponent.Form.SetFieldValue",
5
6
  } as const;