@antelopejs/interface-dms 0.10.4 → 0.13.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 (384) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +21 -10
  3. package/dist/attachments.d.ts +15 -2
  4. package/dist/attachments.js +14 -1
  5. package/dist/attachments.js.map +1 -1
  6. package/dist/auth/db/models/sessions.model.d.ts +7 -5
  7. package/dist/auth/db/models/sessions.model.js +2 -9
  8. package/dist/auth/db/models/sessions.model.js.map +1 -1
  9. package/dist/auth/db/models/userExternalIdentities.model.d.ts +7 -5
  10. package/dist/auth/db/models/users.model.d.ts +7 -5
  11. package/dist/auth/db/tables/users.table.d.ts +2 -2
  12. package/dist/auth/db/tables/users.table.js.map +1 -1
  13. package/dist/auth/index.d.ts +4 -4
  14. package/dist/auth/internal/jwt-auth-decorator.d.ts +1 -1
  15. package/dist/auth/internal/jwt-auth-decorator.js +6 -3
  16. package/dist/auth/internal/jwt-auth-decorator.js.map +1 -1
  17. package/dist/auth/internal/request-authenticators.d.ts +12 -0
  18. package/dist/auth/internal/request-authenticators.js +53 -10
  19. package/dist/auth/internal/request-authenticators.js.map +1 -1
  20. package/dist/base/activity-feed.d.ts +34 -32
  21. package/dist/base/activity-feed.js +2 -0
  22. package/dist/base/activity-feed.js.map +1 -1
  23. package/dist/base/banner.d.ts +12 -10
  24. package/dist/base/banner.js +2 -0
  25. package/dist/base/banner.js.map +1 -1
  26. package/dist/base/block-registry/internal/describe.js +4 -12
  27. package/dist/base/block-registry/internal/describe.js.map +1 -1
  28. package/dist/base/block-registry/internal/ui.js +1 -1
  29. package/dist/base/block-registry/internal/ui.js.map +1 -1
  30. package/dist/base/card.d.ts +11 -9
  31. package/dist/base/card.js +2 -0
  32. package/dist/base/card.js.map +1 -1
  33. package/dist/base/chart-card.d.ts +4 -2
  34. package/dist/base/chart-card.js +2 -0
  35. package/dist/base/chart-card.js.map +1 -1
  36. package/dist/base/chart-schemas.d.ts +148 -148
  37. package/dist/base/chart.d.ts +65 -0
  38. package/dist/base/chart.js +65 -0
  39. package/dist/base/chart.js.map +1 -1
  40. package/dist/base/code-block.d.ts +5 -3
  41. package/dist/base/code-block.js +2 -0
  42. package/dist/base/code-block.js.map +1 -1
  43. package/dist/base/custom.d.ts +5 -0
  44. package/dist/base/custom.js +5 -0
  45. package/dist/base/custom.js.map +1 -1
  46. package/dist/base/data-types/default/address.d.ts +5 -0
  47. package/dist/base/data-types/default/address.js +5 -0
  48. package/dist/base/data-types/default/address.js.map +1 -1
  49. package/dist/base/data-types/default/choices.d.ts +20 -0
  50. package/dist/base/data-types/default/choices.js +20 -0
  51. package/dist/base/data-types/default/choices.js.map +1 -1
  52. package/dist/base/data-types/default/files.d.ts +22 -5
  53. package/dist/base/data-types/default/files.js +20 -0
  54. package/dist/base/data-types/default/files.js.map +1 -1
  55. package/dist/base/data-types/default/numbers.d.ts +15 -0
  56. package/dist/base/data-types/default/numbers.js +25 -9
  57. package/dist/base/data-types/default/numbers.js.map +1 -1
  58. package/dist/base/data-types/default/relations.d.ts +10 -2
  59. package/dist/base/data-types/default/relations.js +9 -6
  60. package/dist/base/data-types/default/relations.js.map +1 -1
  61. package/dist/base/data-types/default/strings.d.ts +25 -0
  62. package/dist/base/data-types/default/strings.js +25 -0
  63. package/dist/base/data-types/default/strings.js.map +1 -1
  64. package/dist/base/data-types/default-types.d.ts +1 -1
  65. package/dist/base/data-types/field-types.d.ts +10 -0
  66. package/dist/base/data-types/field-types.js +10 -0
  67. package/dist/base/data-types/field-types.js.map +1 -1
  68. package/dist/base/data-types/internal/relation-endpoints.js +1 -0
  69. package/dist/base/data-types/internal/relation-endpoints.js.map +1 -1
  70. package/dist/base/data-types/status-type.d.ts +5 -0
  71. package/dist/base/data-types/status-type.js +5 -0
  72. package/dist/base/data-types/status-type.js.map +1 -1
  73. package/dist/base/display.d.ts +6 -6
  74. package/dist/base/empty-state.d.ts +15 -13
  75. package/dist/base/empty-state.js +2 -0
  76. package/dist/base/empty-state.js.map +1 -1
  77. package/dist/base/form-block-schema.d.ts +50 -50
  78. package/dist/base/form-schema.d.ts +2 -0
  79. package/dist/base/form-schema.js +2 -0
  80. package/dist/base/form-schema.js.map +1 -1
  81. package/dist/base/grid.d.ts +4 -0
  82. package/dist/base/grid.js +4 -0
  83. package/dist/base/grid.js.map +1 -1
  84. package/dist/base/guard.d.ts +30 -28
  85. package/dist/base/guard.js +2 -0
  86. package/dist/base/guard.js.map +1 -1
  87. package/dist/base/helpers/archive-mode-helpers.d.ts +1 -1
  88. package/dist/base/helpers/file-refs.js +15 -15
  89. package/dist/base/helpers/file-refs.js.map +1 -1
  90. package/dist/base/internal/form-schema-validation.js +7 -1
  91. package/dist/base/internal/form-schema-validation.js.map +1 -1
  92. package/dist/base/internal/realtime-topics.js.map +1 -1
  93. package/dist/base/internal/searchable.d.ts +2 -1
  94. package/dist/base/internal/searchable.js +1 -3
  95. package/dist/base/internal/searchable.js.map +1 -1
  96. package/dist/base/key-value-list.d.ts +21 -19
  97. package/dist/base/key-value-list.js +2 -0
  98. package/dist/base/key-value-list.js.map +1 -1
  99. package/dist/base/kpi-card.d.ts +4 -2
  100. package/dist/base/kpi-card.js +2 -0
  101. package/dist/base/kpi-card.js.map +1 -1
  102. package/dist/base/live-toggle.d.ts +2 -0
  103. package/dist/base/live-toggle.js +2 -0
  104. package/dist/base/live-toggle.js.map +1 -1
  105. package/dist/base/meter.d.ts +23 -21
  106. package/dist/base/meter.js +2 -0
  107. package/dist/base/meter.js.map +1 -1
  108. package/dist/base/nav-card-grid.d.ts +24 -19
  109. package/dist/base/nav-card-grid.js +5 -0
  110. package/dist/base/nav-card-grid.js.map +1 -1
  111. package/dist/base/page-toolbar.d.ts +2 -0
  112. package/dist/base/page-toolbar.js +2 -0
  113. package/dist/base/page-toolbar.js.map +1 -1
  114. package/dist/base/period-selector.d.ts +3 -1
  115. package/dist/base/period-selector.js +2 -0
  116. package/dist/base/period-selector.js.map +1 -1
  117. package/dist/base/placeholder.d.ts +2 -0
  118. package/dist/base/placeholder.js +2 -0
  119. package/dist/base/placeholder.js.map +1 -1
  120. package/dist/base/resource-form-schema.d.ts +2 -2
  121. package/dist/base/searchable.d.ts +3 -2
  122. package/dist/base/searchable.js +2 -2
  123. package/dist/base/searchable.js.map +1 -1
  124. package/dist/base/section.d.ts +6 -2
  125. package/dist/base/section.js +4 -0
  126. package/dist/base/section.js.map +1 -1
  127. package/dist/base/stack.d.ts +6 -0
  128. package/dist/base/stack.js +6 -0
  129. package/dist/base/stack.js.map +1 -1
  130. package/dist/base/stat-group.d.ts +16 -14
  131. package/dist/base/stat-group.js +2 -0
  132. package/dist/base/stat-group.js.map +1 -1
  133. package/dist/base/tab.d.ts +10 -8
  134. package/dist/base/tab.js +2 -0
  135. package/dist/base/tab.js.map +1 -1
  136. package/dist/base/table-view/column-display.d.ts +1 -1
  137. package/dist/base/table-view/column-display.js.map +1 -1
  138. package/dist/base/table-view/data-functions.d.ts +10 -4
  139. package/dist/base/table-view/data-functions.js.map +1 -1
  140. package/dist/base/table-view/factory.d.ts +5 -0
  141. package/dist/base/table-view/factory.js +8 -4
  142. package/dist/base/table-view/factory.js.map +1 -1
  143. package/dist/base/table-view/internal/auth.d.ts +17 -3
  144. package/dist/base/table-view/internal/auth.js +26 -5
  145. package/dist/base/table-view/internal/auth.js.map +1 -1
  146. package/dist/base/table-view/internal/column-conditions.d.ts +8 -1
  147. package/dist/base/table-view/internal/column-conditions.js +25 -13
  148. package/dist/base/table-view/internal/column-conditions.js.map +1 -1
  149. package/dist/base/table-view/internal/column-display.d.ts +1 -2
  150. package/dist/base/table-view/internal/column-display.js +3 -9
  151. package/dist/base/table-view/internal/column-display.js.map +1 -1
  152. package/dist/base/table-view/internal/factory-helpers.d.ts +1 -1
  153. package/dist/base/table-view/internal/factory-helpers.js +17 -14
  154. package/dist/base/table-view/internal/factory-helpers.js.map +1 -1
  155. package/dist/base/table-view/internal/factory-lifecycle-created.d.ts +2 -3
  156. package/dist/base/table-view/internal/factory-lifecycle-created.js +5 -5
  157. package/dist/base/table-view/internal/factory-lifecycle-created.js.map +1 -1
  158. package/dist/base/table-view/internal/factory-lifecycle-filter.d.ts +2 -2
  159. package/dist/base/table-view/internal/factory-private-actions.d.ts +2 -2
  160. package/dist/base/table-view/internal/files.d.ts +2 -1
  161. package/dist/base/table-view/internal/files.js +14 -5
  162. package/dist/base/table-view/internal/files.js.map +1 -1
  163. package/dist/base/table-view/internal/footer.d.ts +3 -3
  164. package/dist/base/table-view/internal/footer.js +16 -15
  165. package/dist/base/table-view/internal/footer.js.map +1 -1
  166. package/dist/base/table-view/internal/guards.d.ts +27 -5
  167. package/dist/base/table-view/internal/guards.js +133 -49
  168. package/dist/base/table-view/internal/guards.js.map +1 -1
  169. package/dist/base/table-view/internal/meta-helpers.d.ts +1 -1
  170. package/dist/base/table-view/internal/meta-helpers.js +3 -4
  171. package/dist/base/table-view/internal/meta-helpers.js.map +1 -1
  172. package/dist/base/table-view/internal/meta.js +2 -3
  173. package/dist/base/table-view/internal/meta.js.map +1 -1
  174. package/dist/base/table-view/internal/option-contract.d.ts +9 -1
  175. package/dist/base/table-view/internal/option-footer.d.ts +2 -2
  176. package/dist/base/table-view/internal/option-row-actions.d.ts +1 -1
  177. package/dist/base/table-view/internal/realtime.d.ts +52 -11
  178. package/dist/base/table-view/internal/realtime.js +23 -16
  179. package/dist/base/table-view/internal/realtime.js.map +1 -1
  180. package/dist/base/table-view/internal/resource-form.d.ts +1 -1
  181. package/dist/base/table-view/internal/resource-form.js +1 -1
  182. package/dist/base/table-view/internal/resource-form.js.map +1 -1
  183. package/dist/base/table-view/internal/row-actions-schema.d.ts +12 -12
  184. package/dist/base/table-view/internal/row-rule-shape.d.ts +11 -5
  185. package/dist/base/table-view/internal/row-rule-shape.js +60 -30
  186. package/dist/base/table-view/internal/row-rule-shape.js.map +1 -1
  187. package/dist/base/table-view/internal/row-rules.d.ts +28 -1
  188. package/dist/base/table-view/internal/row-rules.js +8 -19
  189. package/dist/base/table-view/internal/row-rules.js.map +1 -1
  190. package/dist/base/table-view/internal/tabs.d.ts +1 -1
  191. package/dist/base/table-view/internal/tabs.js +1 -4
  192. package/dist/base/table-view/internal/tabs.js.map +1 -1
  193. package/dist/base/table-view/internal/validation.d.ts +2 -2
  194. package/dist/base/table-view/internal/validation.js +7 -7
  195. package/dist/base/table-view/internal/validation.js.map +1 -1
  196. package/dist/base/table-view/meta.d.ts +7 -6
  197. package/dist/base/table-view/meta.js +12 -7
  198. package/dist/base/table-view/meta.js.map +1 -1
  199. package/dist/base/table-view/resource-form.d.ts +3 -1
  200. package/dist/base/table-view/resource-form.js +2 -0
  201. package/dist/base/table-view/resource-form.js.map +1 -1
  202. package/dist/base/table-view/routes.d.ts +73 -21
  203. package/dist/base/table-view/routes.js +13 -10
  204. package/dist/base/table-view/routes.js.map +1 -1
  205. package/dist/base/table-view/schema.d.ts +157 -152
  206. package/dist/base/table-view/schema.js +2 -1
  207. package/dist/base/table-view/schema.js.map +1 -1
  208. package/dist/base/table-view/source.js +4 -1
  209. package/dist/base/table-view/source.js.map +1 -1
  210. package/dist/base/table-view.d.ts +1 -1
  211. package/dist/base/table-view.js.map +1 -1
  212. package/dist/base/top-list-card.d.ts +35 -33
  213. package/dist/base/top-list-card.js +2 -0
  214. package/dist/base/top-list-card.js.map +1 -1
  215. package/dist/base/types/error.js +5 -2
  216. package/dist/base/types/error.js.map +1 -1
  217. package/dist/base/types/guards.d.ts +4 -4
  218. package/dist/base/types/json.d.ts +1 -10
  219. package/dist/base/types/row-action.d.ts +7 -7
  220. package/dist/component-options/confirm-dialog.d.ts +2 -0
  221. package/dist/component-options/confirm-dialog.js.map +1 -1
  222. package/dist/component-options/data-type.d.ts +2 -2
  223. package/dist/component-options/data-type.js +7 -7
  224. package/dist/component-options/data-type.js.map +1 -1
  225. package/dist/component-options/page-layout.d.ts +3 -2
  226. package/dist/component-options/page-layout.js.map +1 -1
  227. package/dist/component-options/row-action.d.ts +14 -9
  228. package/dist/component-slots.d.ts +11 -2
  229. package/dist/component-slots.js +1 -0
  230. package/dist/component-slots.js.map +1 -1
  231. package/dist/component.d.ts +7 -8
  232. package/dist/component.js +17 -25
  233. package/dist/component.js.map +1 -1
  234. package/dist/data-controllers/members.d.ts +11 -7
  235. package/dist/data-controllers/members.js +1 -1
  236. package/dist/data-controllers/members.js.map +1 -1
  237. package/dist/data-controllers/roles.d.ts +32 -10
  238. package/dist/db/internal/exportJobs.model.d.ts +7 -5
  239. package/dist/db/internal/inviteResolutions.model.d.ts +7 -5
  240. package/dist/db/internal/tenantLifecycle.model.d.ts +15 -7
  241. package/dist/db/internal/tenantLifecycle.model.js +16 -7
  242. package/dist/db/internal/tenantLifecycle.model.js.map +1 -1
  243. package/dist/db/models/roles.model.d.ts +7 -5
  244. package/dist/db/models/tenantMembers.model.d.ts +7 -5
  245. package/dist/db/models/tenants.model.d.ts +7 -5
  246. package/dist/db/models/user_invites.model.d.ts +7 -5
  247. package/dist/guards.d.ts +1 -1
  248. package/dist/hooks.d.ts +1 -2
  249. package/dist/hooks.js +33 -26
  250. package/dist/hooks.js.map +1 -1
  251. package/dist/internal/attachments.d.ts +2 -2
  252. package/dist/internal/component-builder.js +2 -1
  253. package/dist/internal/component-builder.js.map +1 -1
  254. package/dist/internal/component-serialization.d.ts +2 -4
  255. package/dist/internal/component-serialization.js +4 -3
  256. package/dist/internal/component-serialization.js.map +1 -1
  257. package/dist/internal/component-slots.d.ts +19 -2
  258. package/dist/internal/component-slots.js +35 -12
  259. package/dist/internal/component-slots.js.map +1 -1
  260. package/dist/internal/component-watch-filter.d.ts +11 -0
  261. package/dist/internal/component-watch-filter.js +22 -0
  262. package/dist/internal/component-watch-filter.js.map +1 -0
  263. package/dist/internal/component-watches.js +0 -1
  264. package/dist/internal/component-watches.js.map +1 -1
  265. package/dist/internal/own-entry.d.ts +7 -0
  266. package/dist/internal/own-entry.js +13 -0
  267. package/dist/internal/own-entry.js.map +1 -0
  268. package/dist/internal/uploads.d.ts +30 -0
  269. package/dist/internal/uploads.js +19 -0
  270. package/dist/internal/uploads.js.map +1 -1
  271. package/dist/invite-extension-payloads.d.ts +14 -2
  272. package/dist/invite-extensions/internal/delivery.js +1 -2
  273. package/dist/invite-extensions/internal/delivery.js.map +1 -1
  274. package/dist/invite-extensions/internal/edit.d.ts +2 -1
  275. package/dist/invite-extensions/internal/edit.js +8 -9
  276. package/dist/invite-extensions/internal/edit.js.map +1 -1
  277. package/dist/invite-extensions/internal/form-slot.js +8 -15
  278. package/dist/invite-extensions/internal/form-slot.js.map +1 -1
  279. package/dist/invite-extensions/internal/payload-slices.d.ts +33 -3
  280. package/dist/invite-extensions/internal/payload-slices.js +84 -19
  281. package/dist/invite-extensions/internal/payload-slices.js.map +1 -1
  282. package/dist/invite-extensions/internal/types.d.ts +10 -1
  283. package/dist/invite-resolution.js +6 -4
  284. package/dist/invite-resolution.js.map +1 -1
  285. package/dist/json.d.ts +10 -0
  286. package/dist/json.js +3 -0
  287. package/dist/json.js.map +1 -0
  288. package/dist/layout-banners.d.ts +5 -2
  289. package/dist/layout-banners.js.map +1 -1
  290. package/dist/page/controllers.d.ts +2 -2
  291. package/dist/page/internal/extension-validation.js +3 -2
  292. package/dist/page/internal/extension-validation.js.map +1 -1
  293. package/dist/page/internal/metadata-layout.js +1 -1
  294. package/dist/page/internal/metadata-layout.js.map +1 -1
  295. package/dist/page/internal/metadata-publish.js +3 -2
  296. package/dist/page/internal/metadata-publish.js.map +1 -1
  297. package/dist/page/internal/metadata-registration.js +5 -4
  298. package/dist/page/internal/metadata-registration.js.map +1 -1
  299. package/dist/page/internal/metadata-upload-registration.d.ts +4 -2
  300. package/dist/page/internal/metadata-upload-registration.js +13 -4
  301. package/dist/page/internal/metadata-upload-registration.js.map +1 -1
  302. package/dist/page/internal/metadata-uploads.d.ts +5 -5
  303. package/dist/page/internal/metadata-uploads.js +4 -8
  304. package/dist/page/internal/metadata-uploads.js.map +1 -1
  305. package/dist/page/internal/page-record.d.ts +2 -3
  306. package/dist/page/internal/page-record.js +23 -16
  307. package/dist/page/internal/page-record.js.map +1 -1
  308. package/dist/page/layout-filter.js +17 -6
  309. package/dist/page/layout-filter.js.map +1 -1
  310. package/dist/page/metadata.js +5 -7
  311. package/dist/page/metadata.js.map +1 -1
  312. package/dist/request-tenant.d.ts +10 -4
  313. package/dist/request-tenant.js +16 -34
  314. package/dist/request-tenant.js.map +1 -1
  315. package/dist/tenant-export.d.ts +2 -1
  316. package/dist/tenant-lifecycle.d.ts +43 -4
  317. package/dist/tenant-lifecycle.js +97 -18
  318. package/dist/tenant-lifecycle.js.map +1 -1
  319. package/dist/types.d.ts +20 -0
  320. package/dist/uploads.d.ts +1 -1
  321. package/dist/uploads.js +39 -60
  322. package/dist/uploads.js.map +1 -1
  323. package/dist/utils/fire-and-forget.js.map +1 -1
  324. package/dist/utils/internal/decorated-class.d.ts +14 -0
  325. package/dist/utils/internal/decorated-class.js +37 -0
  326. package/dist/utils/internal/decorated-class.js.map +1 -0
  327. package/dist/utils/internal/type-check.d.ts +9 -0
  328. package/dist/utils/internal/type-check.js +13 -5
  329. package/dist/utils/internal/type-check.js.map +1 -1
  330. package/dist/utils/internal/value-parser.d.ts +1 -1
  331. package/dist/utils/internal/value-parser.js +22 -9
  332. package/dist/utils/internal/value-parser.js.map +1 -1
  333. package/dist/watch-actions.d.ts +1 -1
  334. package/docs/1.core/1.introduction.md +82 -77
  335. package/docs/1.core/10.layout-banners.md +57 -45
  336. package/docs/1.core/11.modules-and-dynamic-menus.md +178 -0
  337. package/docs/1.core/12.frontend-modules-and-request-helpers.md +155 -0
  338. package/docs/1.core/13.tenant-data-export.md +120 -0
  339. package/docs/1.core/2.pages-and-modules.md +140 -367
  340. package/docs/1.core/3.components.md +21 -22
  341. package/docs/1.core/4.permissions.md +92 -71
  342. package/docs/1.core/5.tenancy.md +150 -86
  343. package/docs/1.core/6.invites.md +90 -65
  344. package/docs/1.core/7.hooks.md +96 -166
  345. package/docs/1.core/8.realtime.md +44 -45
  346. package/docs/1.core/9.quick-actions.md +37 -30
  347. package/docs/2.auth/1.introduction.md +33 -35
  348. package/docs/2.auth/2.authentication.md +60 -38
  349. package/docs/2.auth/3.tokens-and-sessions.md +56 -55
  350. package/docs/2.auth/4.users.md +79 -51
  351. package/docs/2.auth/5.external-identities.md +25 -26
  352. package/docs/3.base/1.introduction.md +64 -60
  353. package/docs/3.base/10.display-blocks.md +15 -16
  354. package/docs/3.base/11.page-layouts.md +270 -0
  355. package/docs/3.base/12.table-row-actions.md +122 -0
  356. package/docs/3.base/13.table-filters-and-forms.md +104 -0
  357. package/docs/3.base/14.table-events-and-helpers.md +114 -0
  358. package/docs/3.base/15.table-sources-and-gates.md +24 -0
  359. package/docs/3.base/2.types.md +44 -41
  360. package/docs/3.base/3.forms.md +27 -28
  361. package/docs/3.base/4.tables.md +35 -368
  362. package/docs/3.base/5.charts-and-widgets.md +28 -29
  363. package/docs/3.base/6.layout.md +21 -270
  364. package/docs/3.base/8.data-types.md +39 -40
  365. package/docs/3.base/9.helpers.md +36 -38
  366. package/docs/4.notifications/1.introduction.md +22 -26
  367. package/docs/4.notifications/2.categories-and-subjects.md +58 -55
  368. package/docs/4.notifications/3.sending.md +72 -68
  369. package/docs/5.html-render/1.introduction.md +119 -81
  370. package/docs/5.html-render/2.built-in-emails.md +71 -51
  371. package/docs/index.md +18 -29
  372. package/docs/tsconfig.json +4 -0
  373. package/package.json +11 -11
  374. package/docs/images/emails-admin-invite.png +0 -0
  375. package/docs/images/emails-change-notice.png +0 -0
  376. package/docs/images/emails-change-verification.png +0 -0
  377. package/docs/images/emails-digest-logo-dark.png +0 -0
  378. package/docs/images/emails-digest-logo-light.png +0 -0
  379. package/docs/images/emails-digest.png +0 -0
  380. package/docs/images/emails-export-partial.png +0 -0
  381. package/docs/images/emails-export-ready.png +0 -0
  382. package/docs/images/emails-reset-password.png +0 -0
  383. package/docs/images/emails-two-factor.png +0 -0
  384. package/docs/images/emails-user-validation.png +0 -0
@@ -0,0 +1,114 @@
1
+ ---
2
+ title: "Table events and helpers"
3
+ description: Exports, realtime updates, the metadata, the route helpers and the events of a table view.
4
+ mode: reference
5
+ ---
6
+
7
+ These are the parts of a [table view](/docs/interfaces/base/tables) that run around its rows: exports, realtime updates, the metadata it registers, the route helpers and its events.
8
+
9
+ ## Exports
10
+
11
+ The export action is offered only when the controller registered all three `ExportRoutes`. Pressing it starts a background export job, polls its status, and downloads the result; the job machinery itself is shared with any other long export and is documented in [Helpers](/docs/interfaces/base/helpers). Which columns land in the file is decided by `@Exported`.
12
+
13
+ ## Realtime
14
+
15
+ Unless `realtime: false` is set, a table view registers two realtime topics for its page (and for each generated sub-page), and its routes publish every create, update and delete on the first and track who has a row open on the second. Both are named after the controller's location:
16
+
17
+ ```typescript
18
+ import {
19
+ tableViewPresenceTopic,
20
+ tableViewRowTopic,
21
+ } from "@antelopejs/interface-dms/base/table-view";
22
+
23
+ tableViewRowTopic("/api/orders"); // "tableview:row:/api/orders"
24
+ tableViewPresenceTopic("/api/orders"); // "tableview:presence:/api/orders"
25
+ ```
26
+
27
+ The topics are registered with `RegisterPageTopic` from the table view's `onCreated`, so they belong to the module whose page it is, as described in [Realtime](/docs/interfaces/core/realtime). A module that publishes on a table's row topic itself, such as a background job updating rows, builds the name with `tableViewRowTopic` rather than spelling out the prefix, and passes the tenant of the rows as `tenantId`.
28
+
29
+ The topics are the same for every tenant, but what is published on them is not: the routes publish each change, and each presence, for the tenant the request was made in, so the sessions of the other tenants neither refetch nor see who has a row open. The DMS decides who else receives them, with no option on the table: a table whose rows live in the schema every tenant shares (`CORE_SCHEMA_NAME`) publishes to every tenant, and a session on a platform page (a module's page) receives the changes of every tenant, as such a page lists the data of all of them. `RealtimeMutationContext` and `RealtimePresenceContext` carry the tenant as `tenantId`, absent on a table of the shared schema.
30
+
31
+ Two functions let other modules observe those mutations:
32
+
33
+ ```typescript
34
+ import {
35
+ registerRealtimeMutationListener,
36
+ unregisterRealtimeMutationListener,
37
+ type RealtimeMutationContext,
38
+ } from "@antelopejs/interface-dms/base/table-view";
39
+
40
+ const listener = (context: RealtimeMutationContext) => {
41
+ // context.controllerLocation, context.eventType, context.ids, …
42
+ };
43
+
44
+ registerRealtimeMutationListener(listener);
45
+ ```
46
+
47
+ Listeners are additive side observers: they run after the DMS has published the mutation, and a listener that throws is logged, never propagated to the mutating request. A listener is released with the module that registered it, including when that module reloads in development; `unregisterRealtimeMutationListener` is for a module that stops listening while it stays loaded.
48
+
49
+ | Type | Shape |
50
+ | --- | --- |
51
+ | `RealtimeMutationEventType` | `"created" \| "updated" \| "deleted"` |
52
+ | `RealtimeMutationContext` | `controllerLocation`, `rowIdKey`, `eventType`, `ids: string[]`, `sessionId?`, `actor?: RealtimePresenceActor` |
53
+ | `RealtimePresenceActor` | `id`, `displayName?`, `avatarUrl?` |
54
+ | `RealtimePresenceContext` | `controllerLocation`, `rowIdKey`, `sessionId`, `rowId`, `actor` |
55
+
56
+ The routes reach the DMS through two interface functions it implements, `internal.PublishMutation` and `internal.AcquirePresence`. They are internal: nothing outside the DMS implements them, and the core binds them to each generation of the DMS module, so a mutation made while the DMS reloads waits for the next generation instead of reaching the one being torn down.
57
+
58
+ ## Metadata
59
+
60
+ `TableViewMeta` is the metadata object the decorators write to and the builder reads from. Retrieve it with `GetMetadata(controller, TableViewMeta)`.
61
+
62
+ | Member | Description |
63
+ | --- | --- |
64
+ | `columns` | `Record<string, ColumnOptions>` keyed by field name. |
65
+ | `groups` | `Record<string, ColumnGroupConfig>` keyed by group id. |
66
+ | `options` | The `TableViewOptions` of the writing `TableView`, or of the last one built while none writes. |
67
+ | `archiveField` | Field name recorded by `@ArchiveField`. |
68
+ | `controllerRowActionRules` | The rules the write routes enforce: the writing table view's `rowActions`, archive-mode defaults included. |
69
+ | `controllerGuards` | Guards promoted to controller-wide guards. |
70
+ | `componentBuilders` | Every live `TableView` builder built on the controller, in build order. |
71
+ | `writingComponentBuilders` | The live builders of `componentBuilders` that write through the data routes. |
72
+ | `actionPermissionIds(actionId)` | The permission id the action carries on each mounted table view of the controller, on the writing one only for a write action. |
73
+ | `addComponentBuilder(builder, access?)` | Writer the builder calls to record itself, with its `TableViewAccess` (`"read"` or `"write"`, the default). A custom component standing in for a table view (the roles editor) records itself the same way. |
74
+ | `resourceFormBuilders` | Every live `new` / `edit` form built over the controller, in build order: the `ResourceForm` blocks and the forms each table view opens. |
75
+ | `addResourceFormBuilder` | Writer the form builder calls to record a form that submits to the controller. |
76
+ | `writingComponents` | Every live component that submits to the controller's write routes: its writing table view and its `new` / `edit` forms, including the ones a page-mode table view mounts on its form sub-pages. A native file staged by any of them is accepted on save; one staged by any other component is refused. |
77
+ | `inherit(parent)` | Called by `GetMetadata` for a derived controller: copies the parent's `columns` (each with its own copy of its data type), `groups`, `options` and `archiveField`, never its table views or forms. |
78
+ | `config` | Getter returning `{ location, columns }`, the serialized column list plus the controller's route location. |
79
+ | `getFormFields(mode)` | Builds the `FormFieldOrGroup[]` for `"view"`, `"edit"` or `"new"`. |
80
+ | `setColumn`, `setGroup`, `setOptions`, `setArchiveField`, `setControllerRowActionRules`, `setControllerGuards` | Writers used by the decorators and the builder. |
81
+
82
+ Each entry of `config.columns` carries `id`, `header`, `isVisible`, `type` (the serialized data type), `accessorKey`, `listable`, `enableSorting`, `enableColumnFilter`, `defaultValue`, `accessMode` and `readonlyBehavior`.
83
+
84
+ ## Route helpers
85
+
86
+ `table-view` also exports the interface functions the wrapped routes call. They are the seam between the interface and its implementation. A consumer wires them by declaring `TableViewRoutes`, and does not normally call them directly.
87
+
88
+ | Function | Role |
89
+ | --- | --- |
90
+ | `listWithSearch` | Runs the list query with search, filters, sorting and pagination; returns `{ results, total, offset, limit }`. |
91
+ | `countWithSearch` | Same query, count only; returns `{ total }`. |
92
+ | `startExport` | Queues an export job; returns `{ jobId, format, extension }`. |
93
+ | `getExportStatus` | Returns `{ status, progress, error? }` for a job. |
94
+ | `downloadExport` | Streams a completed job's file to the response. |
95
+ | `archiveRows` | Sets the archive field on the given ids; returns `{ success, archivedCount }`. |
96
+ | `restoreRows` | Clears it; returns `{ success, restoredCount }`. |
97
+ | `validateRowsAgainstRule` | Splits ids into `{ eligibleIds, rejectedIds }` against a `RowActionRule`. |
98
+ | `fetchRowForGuard` | Loads one row by id field, for the `edit` guard and the file-cleanup passes. |
99
+
100
+ ## Events and functions
101
+
102
+ | Namespace member | Value |
103
+ | --- | --- |
104
+ | `TableViewEvents.ROW_CLICK` | `"DmsComponent.TableView.RowClick"` |
105
+ | `TableViewEvents.ROW_SELECT` | `"DmsComponent.TableView.RowSelect"` |
106
+ | `TableViewEvents.ROW_DELETE` | `"DmsComponent.TableView.RowDelete"` |
107
+ | `TableViewEvents.ROW_ADD` | `"DmsComponent.TableView.RowAdd"` |
108
+ | `TableViewEvents.ROW_EDIT` | `"DmsComponent.TableView.RowEdit"` |
109
+ | `TableViewEvents.FILTER_CHANGE` | `"DmsComponent.TableView.FilterChange"` |
110
+ | `TableViewEvents.SORT_CHANGE` | `"DmsComponent.TableView.SortChange"` |
111
+ | `TableViewEvents.EXPORT` | `"DmsComponent.TableView.Export"` |
112
+ | `TableViewFunctions.CUSTOM_PAGE_FORM_SUCCESS` | `"DmsComponent.TableView.CustomPageFormSuccess"` |
113
+
114
+ `CUSTOM_PAGE_FORM_SUCCESS` registers `{ url: string; preserveQuery?: string[] }` in `WatchFunctionParamMap`. The builder uses it itself: the generated `new` and `edit` page forms watch `FormEvents.SUBMIT_SUCCESS` and navigate back to the table, preserving the query parameters named in `queryParamFilters`. The handler resolves `{{params.X}}` / `{{query.X}}` tokens in `url` against the route being left before navigating; the generated forms rely on it to send the user back to a page whose slug carries parameters: each placeholder of the page's slug becomes the token reading it on the form route (`/workspaces/:id` becomes `/workspaces/{{params.id:1}}` from `/workspaces/:id/invoiceTable/:id/edit`, `/workspaces/{{params.id}}` from `/workspaces/:id/invoiceTable/new`). A slug without parameters is used as is. The `view` form submits nothing and carries no such watch. All three generated pages are registered with `FormPageLayout()`, the constrained-column layout ([Layout and containers](/docs/interfaces/base/layout)).
@@ -0,0 +1,24 @@
1
+ ---
2
+ title: "Table sources and tenant gates"
3
+ description: Table views over a module's own route, and table views that stay readable behind a tenant access gate.
4
+ mode: reference
5
+ ---
6
+
7
+ A [table view](/docs/interfaces/base/tables) usually reads a data controller. These two cases differ: a table view over a module's own route, and a table view that stays readable while a tenant access gate denies the tenant.
8
+
9
+ ## Tables over a module's route
10
+
11
+ ```typescript fragment
12
+ TableView.fromSource(options: TableViewSourceOptions): ComponentBuilder<TableViewOptionsSerialized>;
13
+ ```
14
+
15
+ A read-only table view with no data controller (`tableViewFromSource`). `TableViewSourceOptions` takes `columns` (a record of `TableViewSourceColumn`, a `@Column`'s options plus `sortable`), `fetchUrl` (its `{{params.X}}` / `{{query.X}}` tokens are filled from the page URL, percent-encoded; the table and its tab counters list again when they change and request nothing while one has no value), `fetchRowUrl?` (a route answering one row by id, `{{row.id}}` its percent-encoded id, with the same tokens: a deep link to a row the table does not list opens through it; serialized on `TableViewSourceSerialized`), `rowIdKey?`, `periodScope?` (the id of a `PeriodSelector`: every request carries its `from`, `to`, `preset` and `comparison`, the table lists again when the period changes, and nothing is requested until the selector is on the page), `capabilities?` (`TableViewSourceCapabilities`: `search`, `sort`, `paginate`, `filter`), `queryParamFilters?` (URL query parameters sent to the route as hidden `filter_<field>` filters), custom row actions and buttons only, and the presentation options of a table view (`caption`, `layout`, `pagination`, `tabs`, `quickFilters`, `displays`, `card`, `emptyStates`, `footer` texts and legend…). The route answers `{ results, total }` and is sent the part of the list query its capabilities name, nothing else; the browser does the rest over the rows it answered, except that a paging route's rows are neither searched nor sorted by the browser. Registration runs the checks of `TableView()` that apply (page size, display ids, tab targets) and throws when tabs, quick filters or `queryParamFilters` lack `capabilities.filter`, or when a key they, `labelKey`, `card.fields` or `expandable` name is not a column, or when `expandable` sets `lazyLoad` (a source has no `get` route), or when `fetchRowUrl` lacks `{{row.id}}`; it warns about a quick filter on a column with no values to pick. There is no export, realtime nor footer summary.
16
+
17
+ ## Reach a table behind a tenant gate
18
+
19
+ `bypassTenantAccessGate` is the table-view mirror of the guard option of the same name. Reserve it for tables that must stay readable while a gate denies the tenant, such as the invoices on the billing page of a suspended tenant, so it can regularize its situation. Permission checks still apply.
20
+
21
+ Data routes are registered against the controller, not against a page, so the opt-out is controller-level and **latched**: once any `TableView()` call on a controller declares it, the controller's routes bypass the gate wherever they are rendered. A later registration of the same controller without the flag cannot re-gate them, and gets a warning saying so. Two consequences worth designing around:
22
+
23
+ - Declaring the flag on a controller opens its routes for every table view built on it, including one mounted on an ordinary page.
24
+ - Actions that carry no permission id, such as a plain list on a component that was never mounted, are then served to any member of a denied tenant. That is the escape hatch working as intended, so keep every action of a flagged controller stamped with a permission.
@@ -1,10 +1,9 @@
1
1
  ---
2
- title: "Shared Types"
2
+ title: "Shared types"
3
3
  description: "The `types` subpath holds the vocabulary every other part of the `base` domain is built from: the base props interface every component's props extend, the colour and size scales, the action targets a button or a row…"
4
+ mode: reference
4
5
  ---
5
6
 
6
- # Shared Types
7
-
8
7
  ## Overview
9
8
 
10
9
  The `types` subpath holds the vocabulary every other part of the `base` domain is built from: the base props interface every component's props extend, the colour and size scales, the action targets a button or a row action can point at, the rule algebra that decides whether a row action applies to a row, the guard signatures a table view runs before a mutation, and a handful of small enums and value unions.
@@ -30,7 +29,7 @@ Four modules are not re-exported by that barrel and are imported from their own
30
29
  | `FIELD_OPERATORS`, `FIELD_KEY`, `FieldOperatorKey`, `FieldRule`, `AnyFieldRule`, `LOGICAL_OPERATOR_KEYS`, `LogicalOperatorKey` | `@antelopejs/interface-dms/base/types/row-action-operators` |
31
30
  | `EditGuardArgs`, `DeleteGuardArgs`, `BulkGuardArgs`, `NewGuardArgs`, `GuardFn`, `AfterWrite`, `TableViewGuards` | `@antelopejs/interface-dms/base/types/guards` |
32
31
 
33
- ## Base Component Props
32
+ ## Base component props
34
33
 
35
34
  `BaseComponentProps` is the one field every component props interface inherits.
36
35
 
@@ -48,9 +47,9 @@ interface BaseComponentProps {
48
47
  }
49
48
  ```
50
49
 
51
- `FormProps`, `TreeProps`, `TabProps`, `KpiCardProps`, `ChartCardProps`, `TopListCardProps`, `PeriodSelectorProps` and the chart props all extend it. The `ComponentBuilder` from `@antelopejs/interface-dms/component` strips a caller-supplied `watchActions` from the options it receives and fills the field itself from `.watch()` / `.watchOn()` calls, so the property is the transport rather than something you set by hand.
50
+ `FormProps`, `TabProps`, `KpiCardProps`, `ChartCardProps`, `TopListCardProps`, `PeriodSelectorProps` and the chart props all extend it. The `ComponentBuilder` from `@antelopejs/interface-dms/component` strips a caller-supplied `watchActions` from the options it receives and fills the field itself from `.watch()` / `.watchOn()` calls, so the property is the transport rather than something you set by hand.
52
51
 
53
- ### Watch Actions
52
+ ### Watch actions
54
53
 
55
54
  A `WatchAction` binds an event emitted by a component to a function exposed by a component.
56
55
 
@@ -66,13 +65,13 @@ import type {
66
65
  | `component` | `string` | Identifier of the component that emits the event. `ComponentId.SELF` (`"$component:self"`) refers to the declaring component. |
67
66
  | `event` | `string` | Event name, e.g. `FormEvents.SUBMIT_SUCCESS`. |
68
67
  | `functionId` | `string` | Identifier of the function to invoke, e.g. `FormFunctions.SET_FIELD_HIDDEN`. |
69
- | `params` | `Record<string, unknown>` | Arguments passed to the function. |
68
+ | `params` | `object` | Arguments passed to the function. Read a member after checking it (`"targetField" in params`), or read the shape the function registers through `WatchFunctionParams`. |
70
69
  | `onParam` | `WatchActionCondition \| WatchActionCondition[]` | Only run when the event payload matches these `{ key, value }` pairs. |
71
70
  | `requirePermission` | `string` | Permission id the viewer must hold for the action to be kept. |
72
71
 
73
- `WatchFunctionParamMap` is an interface extended by declaration merging: each module that exposes a watch function adds its `functionId` and the exact parameter shape to the map. `WatchFunctionId` is `keyof WatchFunctionParamMap & string`, and `WatchFunctionParams<F>` resolves to the registered parameter shape for `F`, falling back to `Record<string, unknown> | undefined` for ids that are not in the map. `Form` and `TableView` both register their functions in this map — see [Forms](/docs/interfaces/base/forms) and [Tables](/docs/interfaces/base/tables).
72
+ `WatchFunctionParamMap` is an interface extended by declaration merging: each module that exposes a watch function adds its `functionId` and the exact parameter shape to the map. `WatchFunctionId` is `keyof WatchFunctionParamMap & string`, and `WatchFunctionParams<F>` resolves to the registered parameter shape for `F`, falling back to `Record<string, unknown> | undefined` for ids that are not in the map. `Form` and `TableView` both register their functions in this map, as [Forms](/docs/interfaces/base/forms) and [Tables](/docs/interfaces/base/tables) describe.
74
73
 
75
- ## Colors and Sizes
74
+ ## Colors and sizes
76
75
 
77
76
  ```typescript
78
77
  import {
@@ -86,7 +85,7 @@ import {
86
85
 
87
86
  `Color` is an enum of the semantic palette names: `primary`, `secondary`, `success`, `info`, `warning`, `error`, `neutral`. `ColorValue` is `Color | (string & {})`, so a component that accepts a `ColorValue` takes either an enum member or an arbitrary string while keeping the enum members in editor completion.
88
87
 
89
- `TONES` (`Tone`, from `types/tone`) is `neutral`, `primary`, `secondary`, `success`, `warning`, `error`, `info`; `ICON_TONES` (`IconTone`) adds `muted`. `color` is for what is clicked (buttons, row actions, header actions, tabs), `tone` for what shows a state (pills, icon wells, banners, meters, notifications, blocks); see [Display Blocks](/docs/interfaces/base/display-blocks).
88
+ `TONES` (`Tone`, from `types/tone`) is `neutral`, `primary`, `secondary`, `success`, `warning`, `error`, `info`; `ICON_TONES` (`IconTone`) adds `muted`. `color` is for what is clicked (buttons, row actions, header actions, tabs), `tone` for what shows a state (pills, icon wells, banners, meters, notifications, blocks); see [Display blocks](/docs/interfaces/base/display-blocks).
90
89
 
91
90
  `Size` maps readable names onto the scale tokens: `tiny` → `"xs"`, `small` → `"sm"`, `medium` → `"md"`, `large` → `"lg"`, `huge` → `"xl"`. `SizeValue` widens it the same way `ColorValue` widens `Color`.
92
91
 
@@ -94,7 +93,7 @@ import {
94
93
 
95
94
  ## Buttons
96
95
 
97
- `ButtonVariant` is an enum with `solid`, `outline`, `soft`, `ghost` and `link`. `ButtonColor` is a plain string union — `"primary" | "secondary" | "success" | "error" | "warning" | "info" | "neutral"` — used by `CustomButton` in place of the `Color` enum.
96
+ `ButtonVariant` is an enum with `solid`, `outline`, `soft`, `ghost` and `link`. `ButtonColor` is a plain string union, `"primary" | "secondary" | "success" | "error" | "warning" | "info" | "neutral"`, used by `CustomButton` in place of the `Color` enum.
98
97
 
99
98
  `CustomButton` describes a toolbar button; it is what `TableViewOptions.customButtons` takes.
100
99
 
@@ -123,7 +122,7 @@ const inviteButton: CustomButton = {
123
122
  | `permissionId` | `string` | Absolute permission id the button requires; wins over `permission`. |
124
123
  | `availability` | `CustomButtonAvailability` | Disable the button, with a reason, for a request it refuses. |
125
124
 
126
- `permission` takes either form: a string names one of the owner's actions, relative to its permission id — the table's for a toolbar button (`"add"` → `<table permission id>.add`), the page's for a header button (`DefaultLayout({ headerActions })`) — and an `Action` references any component's action — another table's `add`, for instance. `permissionId` takes an absolute permission id (`"settings.workspace.invites"`) and wins when both are set. A button the caller lacks the permission for is stripped from the serialized options rather than disabled, so it never reaches the browser. A declared permission that cannot be resolved to an id — an action on a page that never registered — fails closed and strips the button too.
125
+ `permission` takes either form: a string names one of the owner's actions, relative to its permission id: the table's for a toolbar button (`"add"` → `<table permission id>.add`), the page's for a header button (`DefaultLayout({ headerActions })`). An `Action` references any component's action, such as another table's `add`. `permissionId` takes an absolute permission id (`"settings.workspace.invites"`) and wins when both are set. A button the caller lacks the permission for is stripped from the serialized options rather than disabled, so it never reaches the browser. A declared permission that cannot be resolved to an id, such as an action on a page that never registered, fails closed and strips the button too.
127
126
 
128
127
  A button with an `id` can be exposed as a [quick action](/docs/interfaces/core/quick-actions) with a `"button"` target. The quick action opens what the button opens and inherits the button's `permission`: it is listed for exactly the callers the button is shown to.
129
128
 
@@ -135,7 +134,7 @@ A button with an `id` can be exposed as a [quick action](/docs/interfaces/core/q
135
134
 
136
135
  `PermissionGate`, imported from `@antelopejs/interface-dms/permission-gate`, names the shared optional `permission?: ButtonPermission` and `permissionId?: string` fields described above. `ButtonPermission` is `string | Action`; `permissionId` takes precedence. The shape is shared by permission-filtered buttons, row actions, table tabs and views. It does not authorize the route that a control calls: protect that route with a guard too.
137
136
 
138
- ## Action Targets
137
+ ## Action targets
139
138
 
140
139
  `ActionTarget` is a discriminated union on `type`. It is what a custom button or a custom row action points at.
141
140
 
@@ -147,7 +146,7 @@ import type { ActionTarget } from "@antelopejs/interface-dms/base/types/action-t
147
146
  | --- | --- |
148
147
  | `"drawer"` | `component: Component`, `title?`, `description?`, `direction?: DrawerDirection`, plus `DrawerTargetOptions`: `size?: ModalSize`, `rowHeader?`, `rowTitle?`, `positionLabel?`, `deepLink?`, `notFound?` |
149
148
  | `"modal"` | `component: Component`, `size?: ModalSize`, `title?`, `description?` |
150
- | `"sidePanel"` | `component: Component`, plus `SidePanelTargetOptions`: `title?`, `rowTitle?`, `positionLabel?`, `deepLink?`, `notFound?` — for global, page-independent panels; a detail panel is a `drawer` |
149
+ | `"sidePanel"` | `component: Component`, plus `SidePanelTargetOptions`: `title?`, `rowTitle?`, `positionLabel?`, `deepLink?`, `notFound?`. For global, page-independent panels. A detail panel is a `drawer`. |
151
150
  | `"page"` | `url: string`: the page URL's `{{params.X}}` / `{{query.X}}` (a query pair without a value left out), then on a row action the row's `{{row.field}}`; see [Template tokens](/docs/building/pages-and-components#template-tokens) |
152
151
  | `"external"` | `url: string`, `newTab?: boolean`; the same tokens as `page` |
153
152
  | `"download"` | `url: string`, `filename?: string` (`DownloadActionTarget`); the same tokens as `page`, the file name taking them as written. Fetched with the user's session and saved under `filename`, else the server's `Content-Disposition` name, else the URL's last segment; a failure is toasted |
@@ -155,15 +154,17 @@ import type { ActionTarget } from "@antelopejs/interface-dms/base/types/action-t
155
154
  | `"api"` | `url: string`, `method?: "GET" \| "POST" \| "PUT" \| "DELETE" \| "PATCH"`, `body?`, `copy?`, `successMessage: string`; the same tokens as `page` |
156
155
  | `"exportJob"` | `url: string`, `method?: "GET" \| "POST"`, `statusUrl?`, `downloadUrl?`, `labels?`; the same tokens as `page`, plus `{{job.id}}` in `statusUrl` and `downloadUrl` |
157
156
 
158
- `SidePanelTargetOptions` sets the header the DMS draws above a `sidePanel` target's component: `title` (the action's label by default; `$`: an i18n key), `rowTitle`, the title while a row is open, an i18n key or a literal receiving the row's fields (`"{method} {path}"`), `positionLabel`, an i18n key receiving `{ index }` (from 1) and `{ total }` for the row's position among all the rows the table lists, its count rather than the page loaded (the DMS's "{index} of {total}" by default), and `deepLink`, which keeps the open row in the URL like the action's own `deepLink` — on by default for a side panel, `false` opting out (the action's own `deepLink` wins when set), and `notFound` (`SidePanelNotFoundTexts`: `title?`, `description?`), the state the panel draws with a close button when the row a link names answers 404. The panel is non-modal and docked on the right, one at a time with a module's side panels. It is meant for global, page-independent panels (an assistant dock): a detail or record panel opens in a `drawer`.
157
+ `SidePanelTargetOptions` sets the header the DMS draws above a `sidePanel` target's component: `title` (the action's label by default; `$`: an i18n key), `rowTitle`, the title while a row is open, an i18n key or a literal receiving the row's fields (`"{method} {path}"`), `positionLabel`, an i18n key receiving `{ index }` (from 1) and `{ total }` for the row's position among all the rows the table lists, its count rather than the page loaded (the DMS's "{index} of {total}" by default), and `deepLink`, which keeps the open row in the URL like the action's own `deepLink`. It is on by default for a side panel, `false` opting out (the action's own `deepLink` wins when set), and `notFound` (`SidePanelNotFoundTexts`: `title?`, `description?`), the state the panel draws with a close button when the row a link names answers 404. The panel is non-modal and docked on the right, one at a time with a module's side panels. It is meant for global, page-independent panels (an assistant dock): a detail or record panel opens in a `drawer`.
159
158
 
160
- `DrawerTargetOptions` gives a `drawer` target opened on a row the same options, so a detail panel moves from `sidePanel` to `drawer` without losing any: `rowTitle`, `positionLabel` and `notFound` as above; `rowHeader`, the DMS drawing the row header (the title naming the row, its position, previous and next buttons next to the close button) — on when `rowTitle` or `positionLabel` is set, `false` leaving the drawer's own title, `true` drawing it with the defaults; `deepLink`, off by default for a drawer (the action's own `deepLink` wins when set); and `size` (`ModalSize`), the width a `left` / `right` drawer opens at from `lg`, a modal's width at that size. J and K step through the rows in place whatever the header. A drawer shows its not-found state only once its target sets `notFound`; otherwise a deep link to a missing row is a toast, as before.
159
+ `DrawerTargetOptions` gives a `drawer` target opened on a row the same options, so a detail panel moves from `sidePanel` to `drawer` without losing any: `rowTitle`, `positionLabel` and `notFound` as above; `rowHeader`, the DMS drawing the row header (the title naming the row, its position, previous and next buttons next to the close button), on when `rowTitle` or `positionLabel` is set, `false` leaving the drawer's own title, `true` drawing it with the defaults; `deepLink`, off by default for a drawer (the action's own `deepLink` wins when set); and `size` (`ModalSize`), the width a `left` / `right` drawer opens at from `lg`, a modal's width at that size. J and K step through the rows in place whatever the header. A drawer shows its not-found state only once its target sets `notFound`; otherwise a deep link to a missing row is a toast, as before.
161
160
 
162
161
  `DrawerDirection` is `"top" | "right" | "bottom" | "left"`, the edge the drawer slides in from: `bottom` by default, while `left` and `right` open a side sheet spanning the window's height, 600px wide from `lg` without a `size` (capped to the window) and 440px below it. From `lg` the user resizes every drawer by its inner edge (width or height), and the drawer opens again at the size it was left at.
163
162
 
164
163
  A target carries no confirmation: the action does (`CustomButton.confirm`, `CustomRowAction.confirm`, `RowActionConfig.confirm`), with one type, `ActionConfirm = ConfirmDialog | ConfirmDialogFrom` (see below). The `labels` object on `exportJob` accepts `title`, `exporting`, `downloading`, `successTitle`, `successMessage`, `errorTitle` and `retry`, all optional strings.
165
164
 
166
165
  ```typescript
166
+ import { ActionTarget } from "@antelopejs/interface-dms/base/types/action-target";
167
+
167
168
  const validateEmail: ActionTarget = {
168
169
  type: "api",
169
170
  url: "/settings/workspace/members/{{row._id}}/validate-email",
@@ -181,15 +182,15 @@ import type {
181
182
  } from "@antelopejs/interface-dms/base/types/confirm-dialog";
182
183
  ```
183
184
 
184
- `ConfirmDialog` is the one confirmation every action asks in: `title`, `description?`, `params?` (interpolated into the texts, besides a row action's row fields; a numeric `count` pluralizes them), `icon?`, `color?` (`ButtonColor`), `confirmLabel?`, `cancelLabel?`, `impact?: ConfirmDialogImpact[]` (`{ icon, label, count? }`), `secondaryAction?: ConfirmDialogSecondaryAction` (`{ label, icon?, target }`, a button next to cancel and confirm that leaves the dialog open; its `target` is an `external` link or `{ type: "download", url, filename? }`, fetched with the user's session), `blocked?` (the dialog only explains why the action cannot run), `confirmText?` (type-to-confirm), `confirmTextCaseInsensitive?` (the typed text compared ignoring case), `fields?: FormField[]` and `component?: Component`. The values of `fields` are sent with the action's request — merged into an `api` target's `body`, the input winning — and a field error the server answers shows under its field. `ConfirmDialogFrom` is `{ from: string }`: a URL (on a row action, built-in or custom, the row's fields filled in, such as `{{row._id}}`, plus `{{row.id}}`, the row's id) answering a `ConfirmDialogSerialized`, which `serializeConfirmDialog(dialog)` builds. `ActionConfirm` is either.
185
+ `ConfirmDialog` is the one confirmation every action asks in: `title`, `description?`, `params?` (interpolated into the texts, besides a row action's row fields; a numeric `count` pluralizes them), `icon?`, `color?` (`ButtonColor`), `confirmLabel?`, `cancelLabel?`, `impact?: ConfirmDialogImpact[]` (`{ icon, label, count? }`), `secondaryAction?: ConfirmDialogSecondaryAction` (`{ label, icon?, target }`, a button next to cancel and confirm that leaves the dialog open; its `target` is an `external` link or `{ type: "download", url, filename? }`, fetched with the user's session), `blocked?` (the dialog only explains why the action cannot run), `confirmText?` (type-to-confirm), `confirmTextCaseInsensitive?` (the typed text compared ignoring case), `fields?: FormField[]` and `component?: Component`. The values of `fields` are sent with the action's request, merged into an `api` target's `body` with the input winning. A field error the server answers shows under its field. `ConfirmDialogFrom` is `{ from: string }`: a URL (on a row action, built-in or custom, the row's fields filled in, such as `{{row._id}}`, plus `{{row.id}}`, the row's id) answering a `ConfirmDialogSerialized`, which `serializeConfirmDialog(dialog)` builds. `ActionConfirm` is either.
185
186
 
186
187
  `ActionTargetSerialized` mirrors the union exactly, with `component` on the `drawer`, `modal` and `sidePanel` variants replaced by `ComponentInfoSerialized`.
187
188
 
188
- ## Row Action Rules
189
+ ## Row action rules
189
190
 
190
191
  A row action rule decides, per row, whether an action applies. The same rule value is sent to the frontend so the row's menu matches what the backend will accept, and evaluated on the backend before an `edit`, `delete`, `archive` or `restore` runs.
191
192
 
192
- ### Field Operators
193
+ ### Field operators
193
194
 
194
195
  `FIELD_OPERATORS` is the catalogue of leaf comparisons. Each entry declares whether the rule value is an array and carries the comparison itself.
195
196
 
@@ -210,9 +211,9 @@ import {
210
211
 
211
212
  `FieldOperatorKey` is `keyof typeof FIELD_OPERATORS`. `FIELD_KEY` is the literal `"field"`, the property name that carries the field name inside a leaf rule. `LOGICAL_OPERATOR_KEYS` is the tuple `["and", "or", "not"]` and `LogicalOperatorKey` is its element type.
212
213
 
213
- ### Rule Shapes
214
+ ### Rule shapes
214
215
 
215
- A leaf rule is `{ field: K }` plus the operator key. `FieldRule<T, Op>` builds that shape for one operator over the keys of `T`, choosing `T[K][]` for the array operators and `T[K]` for the others. `AnyFieldRule<T>` is the union over all four operators.
216
+ A leaf rule is `{ field: K }` plus the operator key. `FieldRule<T, Op>` builds that shape for one operator over the keys of `T`, choosing `Awaited<T[K]>[]` for the array operators and `Awaited<T[K]>` for the others: a getter answering a promise is compared by the value it resolves to, as the served row holds it. `AnyFieldRule<T>` is the union over all four operators.
216
217
 
217
218
  ```typescript
218
219
  import type {
@@ -235,7 +236,7 @@ const editable: AndRule<Invoice> = {
235
236
 
236
237
  The four named leaf aliases are `FieldEqualsRule<T>`, `FieldNotEqualsRule<T>`, `FieldInRule<T>` and `FieldNotInRule<T>`, each an alias of `FieldRule<T, Op>` for the matching operator. The three combinators are `AndRule<T>` (`{ and: RowActionRule<T>[] }`), `OrRule<T>` (`{ or: RowActionRule<T>[] }`) and `NotRule<T>` (`{ not: RowActionRule<T> }`); `LogicalRule<T>` is their union. `RowActionRule<T>` is `AnyFieldRule<T> | LogicalRule<T>`, so rules nest to any depth.
237
238
 
238
- ### Attaching a Rule
239
+ ### Attach a rule
239
240
 
240
241
  `RowActionConfig<T>` is the object form of a built-in row action.
241
242
 
@@ -258,7 +259,7 @@ The four named leaf aliases are `FieldEqualsRule<T>`, `FieldNotEqualsRule<T>`, `
258
259
 
259
260
  `CustomRowActionSerialized` is the same shape with `target: ActionTargetSerialized` and an untyped `RowActionRule`.
260
261
 
261
- Where these are consumed — `TableViewOptions.rowActions`, and the archive-mode defaults — is covered in [Tables](/docs/interfaces/base/tables).
262
+ [Tables](/docs/interfaces/base/tables) covers where these are consumed: `TableViewOptions.rowActions` and the archive-mode defaults.
262
263
 
263
264
  ## Guards
264
265
 
@@ -309,13 +310,13 @@ A mutating guard may return an `AfterWrite`: the table view runs it once the wri
309
310
 
310
311
  `T` is the data controller instance `TableView()` infers from its controller; it defaults to `Record<string, unknown>` on every one of them. How guards are attached and when each one fires is documented in [Tables](/docs/interfaces/base/tables).
311
312
 
312
- ## Form and Field Types
313
+ ## Form and field types
313
314
 
314
- ### FormMode
315
+ ### `FormMode`
315
316
 
316
317
  `FormMode` is the enum `new`, `edit`, `view`. It selects which variant of a form the table view generates and which readonly behaviour applies.
317
318
 
318
- ### ReadonlyBehavior
319
+ ### `ReadonlyBehavior`
319
320
 
320
321
  `ReadonlyBehaviorType` is an enum with `disabled`, `hidden` and `default`. `ReadonlyBehaviorConfig` gives one value per mode:
321
322
 
@@ -331,7 +332,7 @@ const createdAtBehavior = {
331
332
 
332
333
  `ReadonlyBehavior` is `ReadonlyBehaviorType | ReadonlyBehaviorConfig`, so a column may pass a single value that applies to every mode or a per-mode object. It is read by `ColumnOptions.readonlyBehavior`.
333
334
 
334
- ### ListableConfig and FieldMetadata
335
+ ### `ListableConfig` and `FieldMetadata`
335
336
 
336
337
  `FieldMetadata` is the slice of a field's data-api metadata the table view reads when it builds a column or a form field.
337
338
 
@@ -342,35 +343,37 @@ const createdAtBehavior = {
342
343
  | `listable` | `ListableConfig` | Which pluck modes include the field. |
343
344
  | `sortable` | `boolean` | Whether the field can be sorted on. |
344
345
 
345
- `ListableConfig` is `{ list?: boolean; select?: boolean; export?: boolean }` — one flag per pluck mode.
346
+ `ListableConfig` is `{ list?: boolean; select?: boolean; export?: boolean }`, one flag per pluck mode.
346
347
 
347
- ### Field Values
348
+ ### Field values
348
349
 
349
350
  `DefaultValue` and `FormFieldValue` are the same recursive union: `string | number | boolean | Date | null` and arrays of themselves. `DefaultValue` types `FormField.defaultValue` and `ColumnOptions.defaultValue`; `FormFieldValue` types a value held by a form field.
350
351
 
351
- ### ComponentOrNoInput
352
+ ### `ComponentOrNoInput`
352
353
 
353
354
  ```typescript
355
+ import { Component } from "vue";
356
+
354
357
  type ComponentOrNoInput<T = undefined> = Component<T> | "noInput";
355
358
  ```
356
359
 
357
- The literal `"noInput"` stands for a compare mode that takes no value — `is_empty` and `is_not_empty` are registered that way, and `serializeType` substitutes the literal for their filter component. The serialized counterpart used by data types is `FilterComponent`, documented in [Data Types](/docs/interfaces/base/data-types).
360
+ The literal `"noInput"` stands for a compare mode that takes no value. `is_empty` and `is_not_empty` are registered that way, and `serializeType` substitutes the literal for their filter component. The serialized counterpart used by data types is `FilterComponent`, documented in [Data types](/docs/interfaces/base/data-types).
358
361
 
359
- ## Transport and Miscellaneous
362
+ ## Transport and other types
360
363
 
361
- ### HttpMethod
364
+ ### `HttpMethod`
362
365
 
363
366
  `HttpMethod` is an enum of `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, keyed by the lowercase name (`HttpMethod.get`, `HttpMethod.post`, …). Every component with a `fetchUrl` also accepts a `fetchUrlMethod` of this type.
364
367
 
365
- ### AxeOrientation
368
+ ### `AxeOrientation`
366
369
 
367
370
  `AxeOrientation` is the enum `horizontal` / `vertical`. `TabProps.orientation`, `BarChartProps.orientation` and `FormComponents.RadioGroupOptions.orientation` take it.
368
371
 
369
- ### ExportStatus
372
+ ### `ExportStatus`
370
373
 
371
- `ExportStatus` is the enum `pending`, `completed`, `failed`. It is the status stored on an export job and returned by the export-status route — see [Helpers](/docs/interfaces/base/helpers).
374
+ `ExportStatus` is the enum `pending`, `completed`, `failed`. It is the status stored on an export job and returned by the export-status route, as [Helpers](/docs/interfaces/base/helpers) describes.
372
375
 
373
- ### Json Values
376
+ ### JSON values
374
377
 
375
378
  ```typescript
376
379
  type JsonPrimitive = string | number | boolean | null;
@@ -379,9 +382,9 @@ type JsonValue = JsonPrimitive | JsonValue[] | { [key: string]: JsonValue };
379
382
 
380
383
  `JsonValue` describes anything that survives a JSON round trip.
381
384
 
382
- ### Error Helpers
385
+ ### Error helpers
383
386
 
384
- ```typescript
387
+ ```typescript fragment
385
388
  import {
386
389
  getErrorMessage,
387
390
  isErrorWithMessage,
@@ -399,6 +402,6 @@ try {
399
402
 
400
403
  `ErrorWithMessage` is `{ message: string }`. `isErrorWithMessage` is a type guard that accepts any object carrying a `message` property. `getErrorMessage` returns that message, or the string `"Unknown error"` for anything else, including an object whose `message` is not a string.
401
404
 
402
- ## Next Steps
405
+ ## Next steps
403
406
 
404
- - [Forms](/docs/interfaces/base/forms) - Build a form, its fields, and its validation schema.
407
+ - [Forms](/docs/interfaces/base/forms): Build a form, its fields, and its validation schema.
@@ -1,13 +1,12 @@
1
1
  ---
2
2
  title: "Forms"
3
3
  description: "The Form builder, its fields and field groups, sections, validation and the save modes."
4
+ mode: reference
4
5
  ---
5
6
 
6
- # Forms
7
-
8
7
  ## Overview
9
8
 
10
- `Form` builds a form component from a list of fields. Each field names a [data type](/docs/interfaces/base/data-types), and the data type supplies both the input component the frontend renders and the Zod schema the value is validated against. The builder does three things when you call it: it serializes every field, it compiles the field list into a single Zod object schema, and it attaches the JSON Schema form of that schema to the component options — so the description shipped to the frontend already carries its own validation contract.
9
+ `Form` builds a form component from a list of fields. Each field names a [data type](/docs/interfaces/base/data-types), and the data type supplies both the input component the frontend renders and the Zod schema the value is validated against. The builder does three things when you call it: it serializes every field, it compiles the field list into a single Zod object schema, and it attaches the JSON Schema form of that schema to the component options. The description shipped to the frontend already carries its own validation contract.
11
10
 
12
11
  Everything on this page is exported from the `form` module, reachable either from the package root or from its own subpath:
13
12
 
@@ -23,7 +22,7 @@ import { Form, FormComponents } from "@antelopejs/interface-dms/base/form";
23
22
 
24
23
  `Form` returns a `FormBuilder`, which is a `ComponentBuilder<FormPropsSerialized>` with one extra readonly property, `fields`, carrying the original unserialized `FormFieldOrGroup[]`. That property is what lets `formSchema` derive a schema straight from a builder.
25
24
 
26
- ## Declare a Form
25
+ ## Declare a form
27
26
 
28
27
  Assign the builder to a static field of a page class. The form fetches its initial values from `fetchUrl` and posts back to `submitUrl`.
29
28
 
@@ -67,7 +66,7 @@ export class NotesPage extends PageController(
67
66
  }
68
67
  ```
69
68
 
70
- ### FormProps
69
+ ### `FormProps`
71
70
 
72
71
  `FormProps` extends [`BaseComponentProps`](/docs/interfaces/base/types).
73
72
 
@@ -98,7 +97,7 @@ A form on a page that sets neither `saveMode` nor `kind` saves with the save bar
98
97
 
99
98
  An `"action"` form resets after a successful submit, a `"record"` keeps its values; `labelKey` names the field labelling the record.
100
99
 
101
- `FormPropsSerialized` is `FormProps` with `fields` replaced by `FormFieldOrGroupSerialized[]` — every entry of the form, its own then each section's (`formEntries`) — `sections` by `FormSectionSerialized[]` (each section with the `fieldIds` of the entries it holds), and one added property, `schema`, holding the JSON Schema produced from the compiled Zod object. A required boolean field whose input is a checkbox validates as `z.literal(true)` (`isAcceptanceField`).
100
+ `FormPropsSerialized` is `FormProps` with `fields` replaced by `FormFieldOrGroupSerialized[]` (every entry of the form, its own then each section's, `formEntries`), `sections` by `FormSectionSerialized[]` (each section with the `fieldIds` of the entries it holds), and one added property, `schema`, holding the JSON Schema produced from the compiled Zod object. A required boolean field whose input is a checkbox validates as `z.literal(true)` (`isAcceptanceField`).
102
101
 
103
102
  ## Fields
104
103
 
@@ -123,9 +122,9 @@ A `FormField` describes one input.
123
122
 
124
123
  A module's own form applies `visibleWhen` and `disabledWhen` in the browser; its submit handler enforces what it needs. A table view's columns carry them to its forms and its data routes enforce them as well (see [Tables](/docs/interfaces/base/tables)).
125
124
 
126
- `FormFieldSerialized` replaces `type` with the data type's registered id string and `inputComponent` with a mandatory `component: ComponentInfoSerialized` — the resolved input component, taken from `inputComponent` when set and from `type.inputComponent()` otherwise.
125
+ `FormFieldSerialized` replaces `type` with the data type's registered id string and `inputComponent` with a mandatory `component: ComponentInfoSerialized`: the resolved input component, taken from `inputComponent` when set and from `type.inputComponent()` otherwise.
127
126
 
128
- ## Group Fields
127
+ ## Group fields
129
128
 
130
129
  A `FieldGroup` nests fields under a common heading. It is an alternative member of the `fields` array, not a wrapper around it.
131
130
 
@@ -158,7 +157,7 @@ const contact: FieldGroup = {
158
157
 
159
158
  `FormFieldOrGroup` is `FormField | FieldGroup`, and `FormFieldOrGroupSerialized` is `FormFieldSerialized | FieldGroupSerialized`. Two guards discriminate them, both by checking for an array-valued `fields` property:
160
159
 
161
- ```typescript
160
+ ```typescript fragment
162
161
  import {
163
162
  isFieldGroup,
164
163
  isFieldGroupSerialized,
@@ -171,11 +170,11 @@ for (const item of formProps.fields) {
171
170
  }
172
171
  ```
173
172
 
174
- ## Validate a Submission
173
+ ## Validate a submission
175
174
 
176
175
  The schema the form ships to the frontend is also available on the backend, so the route that receives the submission validates against exactly the same rules.
177
176
 
178
- ```typescript
177
+ ```typescript fragment
179
178
  import { Controller, HTTPResult, JSONBody, Post } from "@antelopejs/interface-api";
180
179
  import { formSchema } from "@antelopejs/interface-dms/base";
181
180
 
@@ -193,9 +192,9 @@ export class NotesController extends Controller("/playground/notes") {
193
192
  }
194
193
  ```
195
194
 
196
- ### formSchema
195
+ ### `formSchema`
197
196
 
198
- ```typescript
197
+ ```typescript fragment
199
198
  function formSchema(
200
199
  source: FormSchemaSource,
201
200
  ): z.ZodObject<Record<string, z.ZodTypeAny>>;
@@ -203,9 +202,9 @@ function formSchema(
203
202
 
204
203
  `FormSchemaSource` is `FormFieldOrGroup[] | FormProps | FormBuilder`. `formSchema` accepts any of the three: an array is compiled directly, a `FormBuilder` and a `FormProps` object are compiled from their `fields`. Anything else throws `Error("formSchema: unsupported source")`.
205
204
 
206
- ### buildFormSchema
205
+ ### `buildFormSchema`
207
206
 
208
- ```typescript
207
+ ```typescript fragment
209
208
  function buildFormSchema(
210
209
  fields: FormFieldOrGroup[],
211
210
  ): z.ZodObject<Record<string, z.ZodTypeAny>>;
@@ -213,9 +212,9 @@ function buildFormSchema(
213
212
 
214
213
  `buildFormSchema` is the field-list form of the same operation and is what `Form` itself calls. It walks the list, flattens groups so a grouped field lands in the object under its own `id`, and adapts every field's base schema. The resulting object is flat: grouping affects layout, not the payload shape.
215
214
 
216
- ### adaptFieldValidationSchema
215
+ ### `adaptFieldValidationSchema`
217
216
 
218
- ```typescript
217
+ ```typescript fragment
219
218
  function adaptFieldValidationSchema(
220
219
  baseSchema: z.ZodTypeAny,
221
220
  options: FieldValidationOptions, // { localized?, required?, fallbackLocale? }
@@ -228,11 +227,11 @@ function adaptFieldValidationSchema(
228
227
  - When `required` is falsy the schema becomes `.nullable().optional()`.
229
228
  - When `required` is true and the schema is a `ZodString` or a `ZodArray`, a `.min(1)` is added so an empty string or empty array does not satisfy the requirement.
230
229
 
231
- It is exported because the same adaptation is applied outside forms — the `Column` decorator uses it to register a field validator on a data controller.
230
+ It is exported because the same adaptation is applied outside forms. The `Column` decorator uses it to register a field validator on a data controller.
232
231
 
233
- ### serializeFormFields
232
+ ### `serializeFormFields`
234
233
 
235
- ```typescript
234
+ ```typescript fragment
236
235
  function serializeFormFields(
237
236
  fields: FormFieldOrGroup[],
238
237
  ): FormFieldOrGroupSerialized[];
@@ -240,7 +239,7 @@ function serializeFormFields(
240
239
 
241
240
  `serializeFormFields` produces the serialized field list: for each field it resolves the input component (`inputComponent` if given, otherwise `type.inputComponent()`) and replaces the data type instance with its registered id, falling back to the string `"unknown"` when the type is not registered. Groups keep their metadata and have their `fields` serialized in place.
242
241
 
243
- ## Input Components
242
+ ## Input components
244
243
 
245
244
  `FormComponents` is a namespace of factory functions, each returning a `ComponentInfoSerialized` for one input widget. Data types call them to produce their default input; you call them directly when a field needs a widget other than its type's default, via `FormField.inputComponent` or `ColumnOptions.inputComponent`.
246
245
 
@@ -258,7 +257,7 @@ const priority = FormComponents.InputSelect({
258
257
 
259
258
  | Function | Options interface |
260
259
  | --- | --- |
261
- | `InputCheckbox()` | — |
260
+ | `InputCheckbox()` | None |
262
261
  | `InputText(options?)` | `InputTextOptions` |
263
262
  | `InputTextarea(options?)` | `TextareaOptions` |
264
263
  | `InputEmail(options?)` | `InputEmailOptions` |
@@ -269,7 +268,7 @@ const priority = FormComponents.InputSelect({
269
268
  | `InputTime(options?)` | `InputTimeOptions` |
270
269
  | `InputPhone(options?)` | `InputPhoneOptions` |
271
270
  | `InputSlider(options?)` | `SliderOptions` |
272
- | `InputSwitch()` | — |
271
+ | `InputSwitch()` | None |
273
272
  | `InputRadioGroup(options)` | `RadioGroupOptions` |
274
273
  | `InputSelect(options)` | `SelectOptions` |
275
274
  | `InputRelation(options)` | `RelationOptions` |
@@ -309,9 +308,9 @@ The option interfaces live in the same namespace. The ones with more than a plac
309
308
  | `ImageResizeOptions` | `maxWidth: number`, `maxHeight: number`, `fit?: "cover" \| "contain"` |
310
309
  | `InputEmailOptions`, `InputColorOptions`, `RichTextOptions` | `placeholder?` |
311
310
 
312
- `ImageResizeOptions` downscales client-side before upload. `contain` (the default) scales down while preserving the source ratio; `cover` crops the image centred to the `maxWidth`/`maxHeight` ratio first, then scales down. An image already within bounds is uploaded untouched. This is a UX-level bound, not a server-enforced guarantee — keep `constraints.maxSize` for the latter.
311
+ `ImageResizeOptions` downscales client-side before upload. `contain` (the default) scales down while preserving the source ratio; `cover` crops the image centred to the `maxWidth`/`maxHeight` ratio first, then scales down. An image already within bounds is uploaded untouched. This is a UX-level bound, not a server-enforced guarantee. Keep `constraints.maxSize` for that.
313
312
 
314
- ## Events and Functions
313
+ ## Events and functions
315
314
 
316
315
  `FormEvents` names the events a form emits, `FormFunctions` the functions it exposes to watch actions.
317
316
 
@@ -355,7 +354,7 @@ const form = Form({
355
354
 
356
355
  `SET_FIELD_VALUE` writes a field from another one's change: `value` writes a fixed value, `valueMap` the entry named by the value of the field the event names, and a value the map has no entry for writes nothing. It skips the `initial` events, so a record opens with what it stored and a field nobody edited is never submitted as changed; a field it writes on a change counts as changed, like one typed in. A field it writes fires `FIELD_CHANGE` in turn, so two watches writing each other loop.
357
356
 
358
- ```typescript
357
+ ```typescript fragment
359
358
  form.watch(FormEvents.FIELD_CHANGE, FormFunctions.SET_FIELD_VALUE, {
360
359
  params: { targetField: "probability", valueMap: { won: 100, lost: 0 } },
361
360
  onParam: { key: "fieldId", value: "stage" },
@@ -364,6 +363,6 @@ form.watch(FormEvents.FIELD_CHANGE, FormFunctions.SET_FIELD_VALUE, {
364
363
 
365
364
  `.watch()` records the watch on the component itself; `.watchOn(childId, …)` records it on a child declared with `.child()`. Both come from `ComponentBuilder` in `@antelopejs/interface-dms/component`.
366
365
 
367
- ## Next Steps
366
+ ## Next steps
368
367
 
369
- - [Tables](/docs/interfaces/base/tables) - Turn a data controller into a table view with columns, row actions and guards.
368
+ - [Tables](/docs/interfaces/base/tables): Turn a data controller into a table view with columns, row actions and guards.