@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.
- package/CHANGELOG.md +126 -0
- package/README.md +21 -10
- package/dist/attachments.d.ts +15 -2
- package/dist/attachments.js +14 -1
- package/dist/attachments.js.map +1 -1
- package/dist/auth/db/models/sessions.model.d.ts +7 -5
- package/dist/auth/db/models/sessions.model.js +2 -9
- package/dist/auth/db/models/sessions.model.js.map +1 -1
- package/dist/auth/db/models/userExternalIdentities.model.d.ts +7 -5
- package/dist/auth/db/models/users.model.d.ts +7 -5
- package/dist/auth/db/tables/users.table.d.ts +2 -2
- package/dist/auth/db/tables/users.table.js.map +1 -1
- package/dist/auth/index.d.ts +4 -4
- package/dist/auth/internal/jwt-auth-decorator.d.ts +1 -1
- package/dist/auth/internal/jwt-auth-decorator.js +6 -3
- package/dist/auth/internal/jwt-auth-decorator.js.map +1 -1
- package/dist/auth/internal/request-authenticators.d.ts +12 -0
- package/dist/auth/internal/request-authenticators.js +53 -10
- package/dist/auth/internal/request-authenticators.js.map +1 -1
- package/dist/base/activity-feed.d.ts +34 -32
- package/dist/base/activity-feed.js +2 -0
- package/dist/base/activity-feed.js.map +1 -1
- package/dist/base/banner.d.ts +12 -10
- package/dist/base/banner.js +2 -0
- package/dist/base/banner.js.map +1 -1
- package/dist/base/block-registry/internal/describe.js +4 -12
- package/dist/base/block-registry/internal/describe.js.map +1 -1
- package/dist/base/block-registry/internal/ui.js +1 -1
- package/dist/base/block-registry/internal/ui.js.map +1 -1
- package/dist/base/card.d.ts +11 -9
- package/dist/base/card.js +2 -0
- package/dist/base/card.js.map +1 -1
- package/dist/base/chart-card.d.ts +4 -2
- package/dist/base/chart-card.js +2 -0
- package/dist/base/chart-card.js.map +1 -1
- package/dist/base/chart-schemas.d.ts +148 -148
- package/dist/base/chart.d.ts +65 -0
- package/dist/base/chart.js +65 -0
- package/dist/base/chart.js.map +1 -1
- package/dist/base/code-block.d.ts +5 -3
- package/dist/base/code-block.js +2 -0
- package/dist/base/code-block.js.map +1 -1
- package/dist/base/custom.d.ts +5 -0
- package/dist/base/custom.js +5 -0
- package/dist/base/custom.js.map +1 -1
- package/dist/base/data-types/default/address.d.ts +5 -0
- package/dist/base/data-types/default/address.js +5 -0
- package/dist/base/data-types/default/address.js.map +1 -1
- package/dist/base/data-types/default/choices.d.ts +20 -0
- package/dist/base/data-types/default/choices.js +20 -0
- package/dist/base/data-types/default/choices.js.map +1 -1
- package/dist/base/data-types/default/files.d.ts +22 -5
- package/dist/base/data-types/default/files.js +20 -0
- package/dist/base/data-types/default/files.js.map +1 -1
- package/dist/base/data-types/default/numbers.d.ts +15 -0
- package/dist/base/data-types/default/numbers.js +25 -9
- package/dist/base/data-types/default/numbers.js.map +1 -1
- package/dist/base/data-types/default/relations.d.ts +10 -2
- package/dist/base/data-types/default/relations.js +9 -6
- package/dist/base/data-types/default/relations.js.map +1 -1
- package/dist/base/data-types/default/strings.d.ts +25 -0
- package/dist/base/data-types/default/strings.js +25 -0
- package/dist/base/data-types/default/strings.js.map +1 -1
- package/dist/base/data-types/default-types.d.ts +1 -1
- package/dist/base/data-types/field-types.d.ts +10 -0
- package/dist/base/data-types/field-types.js +10 -0
- package/dist/base/data-types/field-types.js.map +1 -1
- package/dist/base/data-types/internal/relation-endpoints.js +1 -0
- package/dist/base/data-types/internal/relation-endpoints.js.map +1 -1
- package/dist/base/data-types/status-type.d.ts +5 -0
- package/dist/base/data-types/status-type.js +5 -0
- package/dist/base/data-types/status-type.js.map +1 -1
- package/dist/base/display.d.ts +6 -6
- package/dist/base/empty-state.d.ts +15 -13
- package/dist/base/empty-state.js +2 -0
- package/dist/base/empty-state.js.map +1 -1
- package/dist/base/form-block-schema.d.ts +50 -50
- package/dist/base/form-schema.d.ts +2 -0
- package/dist/base/form-schema.js +2 -0
- package/dist/base/form-schema.js.map +1 -1
- package/dist/base/grid.d.ts +4 -0
- package/dist/base/grid.js +4 -0
- package/dist/base/grid.js.map +1 -1
- package/dist/base/guard.d.ts +30 -28
- package/dist/base/guard.js +2 -0
- package/dist/base/guard.js.map +1 -1
- package/dist/base/helpers/archive-mode-helpers.d.ts +1 -1
- package/dist/base/helpers/file-refs.js +15 -15
- package/dist/base/helpers/file-refs.js.map +1 -1
- package/dist/base/internal/form-schema-validation.js +7 -1
- package/dist/base/internal/form-schema-validation.js.map +1 -1
- package/dist/base/internal/realtime-topics.js.map +1 -1
- package/dist/base/internal/searchable.d.ts +2 -1
- package/dist/base/internal/searchable.js +1 -3
- package/dist/base/internal/searchable.js.map +1 -1
- package/dist/base/key-value-list.d.ts +21 -19
- package/dist/base/key-value-list.js +2 -0
- package/dist/base/key-value-list.js.map +1 -1
- package/dist/base/kpi-card.d.ts +4 -2
- package/dist/base/kpi-card.js +2 -0
- package/dist/base/kpi-card.js.map +1 -1
- package/dist/base/live-toggle.d.ts +2 -0
- package/dist/base/live-toggle.js +2 -0
- package/dist/base/live-toggle.js.map +1 -1
- package/dist/base/meter.d.ts +23 -21
- package/dist/base/meter.js +2 -0
- package/dist/base/meter.js.map +1 -1
- package/dist/base/nav-card-grid.d.ts +24 -19
- package/dist/base/nav-card-grid.js +5 -0
- package/dist/base/nav-card-grid.js.map +1 -1
- package/dist/base/page-toolbar.d.ts +2 -0
- package/dist/base/page-toolbar.js +2 -0
- package/dist/base/page-toolbar.js.map +1 -1
- package/dist/base/period-selector.d.ts +3 -1
- package/dist/base/period-selector.js +2 -0
- package/dist/base/period-selector.js.map +1 -1
- package/dist/base/placeholder.d.ts +2 -0
- package/dist/base/placeholder.js +2 -0
- package/dist/base/placeholder.js.map +1 -1
- package/dist/base/resource-form-schema.d.ts +2 -2
- package/dist/base/searchable.d.ts +3 -2
- package/dist/base/searchable.js +2 -2
- package/dist/base/searchable.js.map +1 -1
- package/dist/base/section.d.ts +6 -2
- package/dist/base/section.js +4 -0
- package/dist/base/section.js.map +1 -1
- package/dist/base/stack.d.ts +6 -0
- package/dist/base/stack.js +6 -0
- package/dist/base/stack.js.map +1 -1
- package/dist/base/stat-group.d.ts +16 -14
- package/dist/base/stat-group.js +2 -0
- package/dist/base/stat-group.js.map +1 -1
- package/dist/base/tab.d.ts +10 -8
- package/dist/base/tab.js +2 -0
- package/dist/base/tab.js.map +1 -1
- package/dist/base/table-view/column-display.d.ts +1 -1
- package/dist/base/table-view/column-display.js.map +1 -1
- package/dist/base/table-view/data-functions.d.ts +10 -4
- package/dist/base/table-view/data-functions.js.map +1 -1
- package/dist/base/table-view/factory.d.ts +5 -0
- package/dist/base/table-view/factory.js +8 -4
- package/dist/base/table-view/factory.js.map +1 -1
- package/dist/base/table-view/internal/auth.d.ts +17 -3
- package/dist/base/table-view/internal/auth.js +26 -5
- package/dist/base/table-view/internal/auth.js.map +1 -1
- package/dist/base/table-view/internal/column-conditions.d.ts +8 -1
- package/dist/base/table-view/internal/column-conditions.js +25 -13
- package/dist/base/table-view/internal/column-conditions.js.map +1 -1
- package/dist/base/table-view/internal/column-display.d.ts +1 -2
- package/dist/base/table-view/internal/column-display.js +3 -9
- package/dist/base/table-view/internal/column-display.js.map +1 -1
- package/dist/base/table-view/internal/factory-helpers.d.ts +1 -1
- package/dist/base/table-view/internal/factory-helpers.js +17 -14
- package/dist/base/table-view/internal/factory-helpers.js.map +1 -1
- package/dist/base/table-view/internal/factory-lifecycle-created.d.ts +2 -3
- package/dist/base/table-view/internal/factory-lifecycle-created.js +5 -5
- package/dist/base/table-view/internal/factory-lifecycle-created.js.map +1 -1
- package/dist/base/table-view/internal/factory-lifecycle-filter.d.ts +2 -2
- package/dist/base/table-view/internal/factory-private-actions.d.ts +2 -2
- package/dist/base/table-view/internal/files.d.ts +2 -1
- package/dist/base/table-view/internal/files.js +14 -5
- package/dist/base/table-view/internal/files.js.map +1 -1
- package/dist/base/table-view/internal/footer.d.ts +3 -3
- package/dist/base/table-view/internal/footer.js +16 -15
- package/dist/base/table-view/internal/footer.js.map +1 -1
- package/dist/base/table-view/internal/guards.d.ts +27 -5
- package/dist/base/table-view/internal/guards.js +133 -49
- package/dist/base/table-view/internal/guards.js.map +1 -1
- package/dist/base/table-view/internal/meta-helpers.d.ts +1 -1
- package/dist/base/table-view/internal/meta-helpers.js +3 -4
- package/dist/base/table-view/internal/meta-helpers.js.map +1 -1
- package/dist/base/table-view/internal/meta.js +2 -3
- package/dist/base/table-view/internal/meta.js.map +1 -1
- package/dist/base/table-view/internal/option-contract.d.ts +9 -1
- package/dist/base/table-view/internal/option-footer.d.ts +2 -2
- package/dist/base/table-view/internal/option-row-actions.d.ts +1 -1
- package/dist/base/table-view/internal/realtime.d.ts +52 -11
- package/dist/base/table-view/internal/realtime.js +23 -16
- package/dist/base/table-view/internal/realtime.js.map +1 -1
- package/dist/base/table-view/internal/resource-form.d.ts +1 -1
- package/dist/base/table-view/internal/resource-form.js +1 -1
- package/dist/base/table-view/internal/resource-form.js.map +1 -1
- package/dist/base/table-view/internal/row-actions-schema.d.ts +12 -12
- package/dist/base/table-view/internal/row-rule-shape.d.ts +11 -5
- package/dist/base/table-view/internal/row-rule-shape.js +60 -30
- package/dist/base/table-view/internal/row-rule-shape.js.map +1 -1
- package/dist/base/table-view/internal/row-rules.d.ts +28 -1
- package/dist/base/table-view/internal/row-rules.js +8 -19
- package/dist/base/table-view/internal/row-rules.js.map +1 -1
- package/dist/base/table-view/internal/tabs.d.ts +1 -1
- package/dist/base/table-view/internal/tabs.js +1 -4
- package/dist/base/table-view/internal/tabs.js.map +1 -1
- package/dist/base/table-view/internal/validation.d.ts +2 -2
- package/dist/base/table-view/internal/validation.js +7 -7
- package/dist/base/table-view/internal/validation.js.map +1 -1
- package/dist/base/table-view/meta.d.ts +7 -6
- package/dist/base/table-view/meta.js +12 -7
- package/dist/base/table-view/meta.js.map +1 -1
- package/dist/base/table-view/resource-form.d.ts +3 -1
- package/dist/base/table-view/resource-form.js +2 -0
- package/dist/base/table-view/resource-form.js.map +1 -1
- package/dist/base/table-view/routes.d.ts +73 -21
- package/dist/base/table-view/routes.js +13 -10
- package/dist/base/table-view/routes.js.map +1 -1
- package/dist/base/table-view/schema.d.ts +157 -152
- package/dist/base/table-view/schema.js +2 -1
- package/dist/base/table-view/schema.js.map +1 -1
- package/dist/base/table-view/source.js +4 -1
- package/dist/base/table-view/source.js.map +1 -1
- package/dist/base/table-view.d.ts +1 -1
- package/dist/base/table-view.js.map +1 -1
- package/dist/base/top-list-card.d.ts +35 -33
- package/dist/base/top-list-card.js +2 -0
- package/dist/base/top-list-card.js.map +1 -1
- package/dist/base/types/error.js +5 -2
- package/dist/base/types/error.js.map +1 -1
- package/dist/base/types/guards.d.ts +4 -4
- package/dist/base/types/json.d.ts +1 -10
- package/dist/base/types/row-action.d.ts +7 -7
- package/dist/component-options/confirm-dialog.d.ts +2 -0
- package/dist/component-options/confirm-dialog.js.map +1 -1
- package/dist/component-options/data-type.d.ts +2 -2
- package/dist/component-options/data-type.js +7 -7
- package/dist/component-options/data-type.js.map +1 -1
- package/dist/component-options/page-layout.d.ts +3 -2
- package/dist/component-options/page-layout.js.map +1 -1
- package/dist/component-options/row-action.d.ts +14 -9
- package/dist/component-slots.d.ts +11 -2
- package/dist/component-slots.js +1 -0
- package/dist/component-slots.js.map +1 -1
- package/dist/component.d.ts +7 -8
- package/dist/component.js +17 -25
- package/dist/component.js.map +1 -1
- package/dist/data-controllers/members.d.ts +11 -7
- package/dist/data-controllers/members.js +1 -1
- package/dist/data-controllers/members.js.map +1 -1
- package/dist/data-controllers/roles.d.ts +32 -10
- package/dist/db/internal/exportJobs.model.d.ts +7 -5
- package/dist/db/internal/inviteResolutions.model.d.ts +7 -5
- package/dist/db/internal/tenantLifecycle.model.d.ts +15 -7
- package/dist/db/internal/tenantLifecycle.model.js +16 -7
- package/dist/db/internal/tenantLifecycle.model.js.map +1 -1
- package/dist/db/models/roles.model.d.ts +7 -5
- package/dist/db/models/tenantMembers.model.d.ts +7 -5
- package/dist/db/models/tenants.model.d.ts +7 -5
- package/dist/db/models/user_invites.model.d.ts +7 -5
- package/dist/guards.d.ts +1 -1
- package/dist/hooks.d.ts +1 -2
- package/dist/hooks.js +33 -26
- package/dist/hooks.js.map +1 -1
- package/dist/internal/attachments.d.ts +2 -2
- package/dist/internal/component-builder.js +2 -1
- package/dist/internal/component-builder.js.map +1 -1
- package/dist/internal/component-serialization.d.ts +2 -4
- package/dist/internal/component-serialization.js +4 -3
- package/dist/internal/component-serialization.js.map +1 -1
- package/dist/internal/component-slots.d.ts +19 -2
- package/dist/internal/component-slots.js +35 -12
- package/dist/internal/component-slots.js.map +1 -1
- package/dist/internal/component-watch-filter.d.ts +11 -0
- package/dist/internal/component-watch-filter.js +22 -0
- package/dist/internal/component-watch-filter.js.map +1 -0
- package/dist/internal/component-watches.js +0 -1
- package/dist/internal/component-watches.js.map +1 -1
- package/dist/internal/own-entry.d.ts +7 -0
- package/dist/internal/own-entry.js +13 -0
- package/dist/internal/own-entry.js.map +1 -0
- package/dist/internal/uploads.d.ts +30 -0
- package/dist/internal/uploads.js +19 -0
- package/dist/internal/uploads.js.map +1 -1
- package/dist/invite-extension-payloads.d.ts +14 -2
- package/dist/invite-extensions/internal/delivery.js +1 -2
- package/dist/invite-extensions/internal/delivery.js.map +1 -1
- package/dist/invite-extensions/internal/edit.d.ts +2 -1
- package/dist/invite-extensions/internal/edit.js +8 -9
- package/dist/invite-extensions/internal/edit.js.map +1 -1
- package/dist/invite-extensions/internal/form-slot.js +8 -15
- package/dist/invite-extensions/internal/form-slot.js.map +1 -1
- package/dist/invite-extensions/internal/payload-slices.d.ts +33 -3
- package/dist/invite-extensions/internal/payload-slices.js +84 -19
- package/dist/invite-extensions/internal/payload-slices.js.map +1 -1
- package/dist/invite-extensions/internal/types.d.ts +10 -1
- package/dist/invite-resolution.js +6 -4
- package/dist/invite-resolution.js.map +1 -1
- package/dist/json.d.ts +10 -0
- package/dist/json.js +3 -0
- package/dist/json.js.map +1 -0
- package/dist/layout-banners.d.ts +5 -2
- package/dist/layout-banners.js.map +1 -1
- package/dist/page/controllers.d.ts +2 -2
- package/dist/page/internal/extension-validation.js +3 -2
- package/dist/page/internal/extension-validation.js.map +1 -1
- package/dist/page/internal/metadata-layout.js +1 -1
- package/dist/page/internal/metadata-layout.js.map +1 -1
- package/dist/page/internal/metadata-publish.js +3 -2
- package/dist/page/internal/metadata-publish.js.map +1 -1
- package/dist/page/internal/metadata-registration.js +5 -4
- package/dist/page/internal/metadata-registration.js.map +1 -1
- package/dist/page/internal/metadata-upload-registration.d.ts +4 -2
- package/dist/page/internal/metadata-upload-registration.js +13 -4
- package/dist/page/internal/metadata-upload-registration.js.map +1 -1
- package/dist/page/internal/metadata-uploads.d.ts +5 -5
- package/dist/page/internal/metadata-uploads.js +4 -8
- package/dist/page/internal/metadata-uploads.js.map +1 -1
- package/dist/page/internal/page-record.d.ts +2 -3
- package/dist/page/internal/page-record.js +23 -16
- package/dist/page/internal/page-record.js.map +1 -1
- package/dist/page/layout-filter.js +17 -6
- package/dist/page/layout-filter.js.map +1 -1
- package/dist/page/metadata.js +5 -7
- package/dist/page/metadata.js.map +1 -1
- package/dist/request-tenant.d.ts +10 -4
- package/dist/request-tenant.js +16 -34
- package/dist/request-tenant.js.map +1 -1
- package/dist/tenant-export.d.ts +2 -1
- package/dist/tenant-lifecycle.d.ts +43 -4
- package/dist/tenant-lifecycle.js +97 -18
- package/dist/tenant-lifecycle.js.map +1 -1
- package/dist/types.d.ts +20 -0
- package/dist/uploads.d.ts +1 -1
- package/dist/uploads.js +39 -60
- package/dist/uploads.js.map +1 -1
- package/dist/utils/fire-and-forget.js.map +1 -1
- package/dist/utils/internal/decorated-class.d.ts +14 -0
- package/dist/utils/internal/decorated-class.js +37 -0
- package/dist/utils/internal/decorated-class.js.map +1 -0
- package/dist/utils/internal/type-check.d.ts +9 -0
- package/dist/utils/internal/type-check.js +13 -5
- package/dist/utils/internal/type-check.js.map +1 -1
- package/dist/utils/internal/value-parser.d.ts +1 -1
- package/dist/utils/internal/value-parser.js +22 -9
- package/dist/utils/internal/value-parser.js.map +1 -1
- package/dist/watch-actions.d.ts +1 -1
- package/docs/1.core/1.introduction.md +82 -77
- package/docs/1.core/10.layout-banners.md +57 -45
- package/docs/1.core/11.modules-and-dynamic-menus.md +178 -0
- package/docs/1.core/12.frontend-modules-and-request-helpers.md +155 -0
- package/docs/1.core/13.tenant-data-export.md +120 -0
- package/docs/1.core/2.pages-and-modules.md +140 -367
- package/docs/1.core/3.components.md +21 -22
- package/docs/1.core/4.permissions.md +92 -71
- package/docs/1.core/5.tenancy.md +150 -86
- package/docs/1.core/6.invites.md +90 -65
- package/docs/1.core/7.hooks.md +96 -166
- package/docs/1.core/8.realtime.md +44 -45
- package/docs/1.core/9.quick-actions.md +37 -30
- package/docs/2.auth/1.introduction.md +33 -35
- package/docs/2.auth/2.authentication.md +60 -38
- package/docs/2.auth/3.tokens-and-sessions.md +56 -55
- package/docs/2.auth/4.users.md +79 -51
- package/docs/2.auth/5.external-identities.md +25 -26
- package/docs/3.base/1.introduction.md +64 -60
- package/docs/3.base/10.display-blocks.md +15 -16
- package/docs/3.base/11.page-layouts.md +270 -0
- package/docs/3.base/12.table-row-actions.md +122 -0
- package/docs/3.base/13.table-filters-and-forms.md +104 -0
- package/docs/3.base/14.table-events-and-helpers.md +114 -0
- package/docs/3.base/15.table-sources-and-gates.md +24 -0
- package/docs/3.base/2.types.md +44 -41
- package/docs/3.base/3.forms.md +27 -28
- package/docs/3.base/4.tables.md +35 -368
- package/docs/3.base/5.charts-and-widgets.md +28 -29
- package/docs/3.base/6.layout.md +21 -270
- package/docs/3.base/8.data-types.md +39 -40
- package/docs/3.base/9.helpers.md +36 -38
- package/docs/4.notifications/1.introduction.md +22 -26
- package/docs/4.notifications/2.categories-and-subjects.md +58 -55
- package/docs/4.notifications/3.sending.md +72 -68
- package/docs/5.html-render/1.introduction.md +119 -81
- package/docs/5.html-render/2.built-in-emails.md +71 -51
- package/docs/index.md +18 -29
- package/docs/tsconfig.json +4 -0
- package/package.json +11 -11
- package/docs/images/emails-admin-invite.png +0 -0
- package/docs/images/emails-change-notice.png +0 -0
- package/docs/images/emails-change-verification.png +0 -0
- package/docs/images/emails-digest-logo-dark.png +0 -0
- package/docs/images/emails-digest-logo-light.png +0 -0
- package/docs/images/emails-digest.png +0 -0
- package/docs/images/emails-export-partial.png +0 -0
- package/docs/images/emails-export-ready.png +0 -0
- package/docs/images/emails-reset-password.png +0 -0
- package/docs/images/emails-two-factor.png +0 -0
- package/docs/images/emails-user-validation.png +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Charts and
|
|
2
|
+
title: "Charts and widgets"
|
|
3
3
|
description: "The chart module and the three card modules cover dashboard surfaces: a chart of a series, a single figure with a delta, a ranked list, and the period selector the others read their date range from."
|
|
4
|
+
mode: reference
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
# Charts and Widgets
|
|
7
|
-
|
|
8
7
|
## Overview
|
|
9
8
|
|
|
10
9
|
The chart module and the three card modules cover dashboard surfaces: a chart of a series, a single figure with a delta, a ranked list, and the period selector the others read their date range from. Each one is a builder that produces a component description; each one either carries its data inline (`staticDataset`, `staticItems`, `staticValue`) or names a `fetchUrl` the frontend calls.
|
|
@@ -23,9 +22,9 @@ import {
|
|
|
23
22
|
import { ChartLine, ChartType } from "@antelopejs/interface-dms/base/chart";
|
|
24
23
|
```
|
|
25
24
|
|
|
26
|
-
## A
|
|
25
|
+
## A dashboard in one page
|
|
27
26
|
|
|
28
|
-
The widgets compose through the layout builders from [Layout and
|
|
27
|
+
The widgets compose through the layout builders from [Layout and containers](/docs/interfaces/base/layout). One `PeriodSelector` declares a scope id; every widget that names the same `periodScope` follows its range.
|
|
29
28
|
|
|
30
29
|
```typescript
|
|
31
30
|
import {
|
|
@@ -102,9 +101,9 @@ export class OverviewPage extends PageController(
|
|
|
102
101
|
}
|
|
103
102
|
```
|
|
104
103
|
|
|
105
|
-
## Chart
|
|
104
|
+
## Chart builders
|
|
106
105
|
|
|
107
|
-
There is one builder per chart type. Each takes its own props with the `type` discriminant optional
|
|
106
|
+
There is one builder per chart type. Each takes its own props with the `type` discriminant optional, since the builder fills it in, and returns a `ComponentBuilder` for that props type.
|
|
108
107
|
|
|
109
108
|
| Builder | `ChartType` | Props interface |
|
|
110
109
|
| --- | --- | --- |
|
|
@@ -126,7 +125,7 @@ There is one builder per chart type. Each takes its own props with the `type` di
|
|
|
126
125
|
|
|
127
126
|
Every builder gives the component a display name from `title`, falling back to the chart's own name (`"Line Chart"`, `"Donut Chart"`, …), and a matching icon.
|
|
128
127
|
|
|
129
|
-
### Common
|
|
128
|
+
### Common options
|
|
130
129
|
|
|
131
130
|
Every chart props interface extends [`BaseComponentProps`](/docs/interfaces/base/types) and adds:
|
|
132
131
|
|
|
@@ -151,7 +150,7 @@ Every chart props interface extends [`BaseComponentProps`](/docs/interfaces/base
|
|
|
151
150
|
|
|
152
151
|
When `realtimeTopic` is set, the builder registers each topic against the page it is declared on, using `RegisterPageTopic` from `@antelopejs/interface-dms/realtime`.
|
|
153
152
|
|
|
154
|
-
### Cartesian
|
|
153
|
+
### Cartesian charts
|
|
155
154
|
|
|
156
155
|
`LineChartProps`, `AreaChartProps`, `RangeAreaChartProps`, `BarChartProps`, `ColumnChartProps`, `ScatterChartProps`, `MixedChartProps`, `RadarChartProps` and `CandlestickChartProps` share a second layer of options on top of the common ones:
|
|
157
156
|
|
|
@@ -189,13 +188,13 @@ And each adds its own:
|
|
|
189
188
|
| `ScatterChartProps` | `pointSize?: number`, `showLabels?: boolean` |
|
|
190
189
|
| `MixedChartProps` | `seriesDefs?: MixedChartSeriesDef[]` |
|
|
191
190
|
| `RadarChartProps` | `fillOpacity?: number` |
|
|
192
|
-
| `CandlestickChartProps` |
|
|
191
|
+
| `CandlestickChartProps` | None |
|
|
193
192
|
|
|
194
193
|
`MixedChartSeriesDef` declares how one series of a mixed chart is drawn: `{ name: string; type: ChartType.LINE | ChartType.AREA | ChartType.COLUMN | ChartType.RANGE_AREA; color?: ChartColorValue }`.
|
|
195
194
|
|
|
196
195
|
`ChartCurve` is `"smooth" | "straight" | "stepline"`. Prefer it to `smooth`, which only chooses between the first two.
|
|
197
196
|
|
|
198
|
-
`ChartAnnotation` draws a horizontal reference on the Y axis
|
|
197
|
+
`ChartAnnotation` draws a horizontal reference on the Y axis, such as a spend cap, a max bound or a volume capacity:
|
|
199
198
|
|
|
200
199
|
| Field | Type | Description |
|
|
201
200
|
| --- | --- | --- |
|
|
@@ -207,21 +206,21 @@ And each adds its own:
|
|
|
207
206
|
|
|
208
207
|
`syncGroup` is what turns a grid of separate metrics into one readable timeline: give every chart on the page the same group name and hovering one moves the crosshair on all of them.
|
|
209
208
|
|
|
210
|
-
### Circular
|
|
209
|
+
### Circular charts
|
|
211
210
|
|
|
212
|
-
`CircularChartProps` extends the common options with `staticDataset?: DonutRecord[]
|
|
211
|
+
`CircularChartProps` extends the common options with `staticDataset?: DonutRecord[]`: a flat list of `{ label: string; value: number }` rather than series.
|
|
213
212
|
|
|
214
213
|
| Props | Extra options |
|
|
215
214
|
| --- | --- |
|
|
216
215
|
| `DonutChartProps` | `centralLabel?: string`, `centralSubLabel?: string`, `arcWidth?: number` |
|
|
217
|
-
| `PieChartProps` |
|
|
216
|
+
| `PieChartProps` | None |
|
|
218
217
|
| `RadialBarChartProps` | `hollowSize?: string`, `showTotal?: boolean` |
|
|
219
218
|
|
|
220
219
|
### Heatmap
|
|
221
220
|
|
|
222
|
-
`HeatmapChartProps` extends the common options directly
|
|
221
|
+
`HeatmapChartProps` extends the common options directly, not the cartesian layer, with `staticDataset?: ChartSeries[]`, `shadeIntensity?: number` and `distributed?: boolean`.
|
|
223
222
|
|
|
224
|
-
## Series and
|
|
223
|
+
## Series and points
|
|
225
224
|
|
|
226
225
|
```typescript
|
|
227
226
|
import type {
|
|
@@ -247,7 +246,7 @@ const series: ChartSeries[] = [
|
|
|
247
246
|
| `ChartSeries` | `name: string`, `data: Array<ChartSeriesPoint \| ChartCandlePoint \| ChartRangePoint \| number>`, `type?: ChartType`, `color?: ChartColorValue`, `strokeWidth?: number`, `strokeDashArray?: number` |
|
|
248
247
|
| `ChartSeriesPoint` | `x: string \| number \| Date`, `y: number \| null`, `label?: string` |
|
|
249
248
|
| `ChartCandlePoint` | `x: string \| number \| Date`, `y: [number, number, number, number]` |
|
|
250
|
-
| `ChartRangePoint` | `x: string \| number \| Date`, `y: [number, number]
|
|
249
|
+
| `ChartRangePoint` | `x: string \| number \| Date`, `y: [number, number]`: the low and high bound a range area fills between |
|
|
251
250
|
| `DonutRecord` | `label: string`, `value: number` |
|
|
252
251
|
|
|
253
252
|
A `null` `y` marks a gap. `ChartSeries.type` overrides the chart's own type for that series, which is what a mixed chart uses.
|
|
@@ -258,7 +257,7 @@ Each property falls back independently to the existing chart configuration when
|
|
|
258
257
|
|
|
259
258
|
These properties also survive mixed-series definition projection. Set them on the data series, not on the positional `seriesDefs`. Rendering follows the chart type's stroke support; circular records do not expose series strokes. This API does not change fills, interpolation, markers, axes or legends.
|
|
260
259
|
|
|
261
|
-
##
|
|
260
|
+
## Colors and formats
|
|
262
261
|
|
|
263
262
|
| Type | Values |
|
|
264
263
|
| --- | --- |
|
|
@@ -268,16 +267,16 @@ These properties also survive mixed-series definition projection. Set them on th
|
|
|
268
267
|
| `ComparisonStyle` | `"dashed"`, `"solid"`, `"dimmed"` |
|
|
269
268
|
| `ValueFormat` | `"number"`, `"currency"`, `"percent"`, `"compact"` |
|
|
270
269
|
|
|
271
|
-
`ColorName` is the chart palette and is distinct from the `Color` enum in [Shared
|
|
270
|
+
`ColorName` is the chart palette and is distinct from the `Color` enum in [Shared types](/docs/interfaces/base/types): it adds `accent` and it is a string union rather than an enum. `ValueFormat` is used by the three card components rather than by the charts themselves.
|
|
272
271
|
|
|
273
|
-
## Chart
|
|
272
|
+
## Chart events
|
|
274
273
|
|
|
275
274
|
| Namespace member | Value |
|
|
276
275
|
| --- | --- |
|
|
277
276
|
| `ChartEvents.SEGMENT_CLICK` | `"DmsComponent.Chart.SegmentClick"` |
|
|
278
277
|
| `ChartEvents.POINT_CLICK` | `"DmsComponent.Chart.PointClick"` |
|
|
279
278
|
|
|
280
|
-
## ChartCard
|
|
279
|
+
## `ChartCard`
|
|
281
280
|
|
|
282
281
|
`ChartCard` wraps a chart in a card that owns the title, the fetch URL and the delta display, and holds the chart as a child under the id `"chart"`.
|
|
283
282
|
|
|
@@ -313,13 +312,13 @@ const card = ChartCard({
|
|
|
313
312
|
| `currencyCode` | `string` | Currency for `valueFormat: "currency"`. |
|
|
314
313
|
| `valuePrecision` | `ValuePrecision` | Fixed fraction digits or `"native"` Intl defaults; omitted keeps legacy formatting. Also applies to the previous value and nested chart's value axis and tooltip. |
|
|
315
314
|
| `showDelta` | `boolean` | Show the change against the comparison period. |
|
|
316
|
-
| `invert` | `boolean` | Treat an increase as bad
|
|
315
|
+
| `invert` | `boolean` | Treat an increase as bad, for metrics where lower is better. |
|
|
317
316
|
| `showLegend` | `boolean` | Show the primary / comparison legend. Defaults to `true`. |
|
|
318
317
|
| `showSeriesLegend` | `boolean` | Show the nested chart's legend, naming each series. Defaults to `false`. |
|
|
319
318
|
| `primaryLabel` | `string` | Label of the primary series. |
|
|
320
319
|
| `comparisonLabel` | `string` | Label of the comparison series. Without it, a card with a `periodScope` names the selected comparison ("Previous year"). |
|
|
321
320
|
|
|
322
|
-
## KpiCard
|
|
321
|
+
## `KpiCard`
|
|
323
322
|
|
|
324
323
|
`KpiCard` shows a single figure with an optional delta and sparkline.
|
|
325
324
|
|
|
@@ -355,14 +354,14 @@ const denied = KpiCard({
|
|
|
355
354
|
| `showPreviousValue` | `boolean` | Show the route's `previousValue` next to the change ("vs €42,900"), formatted as the value. Defaults to `true`. |
|
|
356
355
|
| `showSparkline` | `boolean` | Show the sparkline. |
|
|
357
356
|
| `sparklineAccent` | `ChartColorValue \| "auto"` | Sparkline colour. |
|
|
358
|
-
| `invert` | `boolean` | Treat an increase as bad
|
|
357
|
+
| `invert` | `boolean` | Treat an increase as bad, for metrics where lower is better. |
|
|
359
358
|
| `compareLabel` | `string` | Label next to the delta. Without it (and without `description`), a card with a `periodScope` names the selected comparison ("vs previous year"). Shown with the delta only: with no comparison, the `description` shows instead. |
|
|
360
359
|
| `staticValue` | `number` | Inline value, as an alternative to `fetchUrl`. |
|
|
361
360
|
| `staticDelta` | `number` | Inline delta, in percent (`12.5` reads +12.5 %). |
|
|
362
361
|
| `staticPreviousValue` | `number` | Inline value compared against, as a fetched `previousValue`. |
|
|
363
362
|
| `staticSparkline` | `number[]` | Inline sparkline points. |
|
|
364
363
|
|
|
365
|
-
## TopListCard
|
|
364
|
+
## `TopListCard`
|
|
366
365
|
|
|
367
366
|
`TopListCard` shows a ranked list of items, each with a value and optionally a delta, a sparkline and an avatar.
|
|
368
367
|
|
|
@@ -421,7 +420,7 @@ const topSkills = TopListCard({
|
|
|
421
420
|
| `avatar` | `TopListItemAvatar` | Leading avatar, `{ src: string; alt?: string }`. |
|
|
422
421
|
| `to` | `string` | Link target for the item. `{{params.X}}` / `{{query.X}}` name the page URL; a query pair whose token has no value is left out. |
|
|
423
422
|
|
|
424
|
-
## PeriodSelector
|
|
423
|
+
## `PeriodSelector`
|
|
425
424
|
|
|
426
425
|
`PeriodSelector` owns a date range and a comparison mode, and publishes them under its `id`. Every widget carrying the same value in `periodScope` uses that range.
|
|
427
426
|
|
|
@@ -454,7 +453,7 @@ const selector = PeriodSelector({
|
|
|
454
453
|
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | Control size. |
|
|
455
454
|
| `showRangeLabel` | `boolean` | Show the resolved date range as text. |
|
|
456
455
|
| `rangeLabel` | `PeriodRangeLabel` | `"absolute"` (default): both bounds. `"relative"`: the start of a window reaching now, "since yesterday 11:52". |
|
|
457
|
-
| `comparisonControl` | `PeriodComparisonControl` | `"menu"`, `"toggle"` (one inline button switching a comparison on and off) or `"hidden"` (nothing drawn, the comparison kept on). Defaults to `"toggle"` when `comparisons` offers a single comparison besides `"none"`, `"menu"` otherwise. The menu's trigger names the compared window (
|
|
456
|
+
| `comparisonControl` | `PeriodComparisonControl` | `"menu"`, `"toggle"` (one inline button switching a comparison on and off) or `"hidden"` (nothing drawn, the comparison kept on). Defaults to `"toggle"` when `comparisons` offers a single comparison besides `"none"`, `"menu"` otherwise. The menu's trigger names the compared window (`vs 16 – 17 Oct`, the option's name in its tooltip and its list), so the range label beside it keeps the current window only. |
|
|
458
457
|
| `rememberKey` | `string` | Selectors carrying the same key share the remembered last choice, on any page. |
|
|
459
458
|
| `variant` | `PeriodSelectorVariant` | `"default"` or `"segmented"`. |
|
|
460
459
|
| `maxDays` | `number` | The longest custom range, in days (both ends included), the user can pick in the calendar or the date fields. Presets and a range given by the URL are not limited. |
|
|
@@ -465,6 +464,6 @@ The selector keeps its period in the page URL, under keys prefixed with its `id`
|
|
|
465
464
|
|
|
466
465
|
`PeriodSelectorVariant` is `"default" | "segmented"`. `segmented` renders the presets as inline pills for one-click range switching; the custom range stays in its popover calendar either way.
|
|
467
466
|
|
|
468
|
-
## Next
|
|
467
|
+
## Next steps
|
|
469
468
|
|
|
470
|
-
- [Layout and
|
|
469
|
+
- [Layout and containers](/docs/interfaces/base/layout): Grids, stacks, tabs, layouts and the custom-component escape hatch.
|
package/docs/3.base/6.layout.md
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Layout and
|
|
2
|
+
title: "Layout and containers"
|
|
3
3
|
description: "Grid, stacks, tabs, guard, placeholder and the page layouts that hold every other component."
|
|
4
|
+
mode: reference
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
# Layout and Containers
|
|
7
|
-
|
|
8
7
|
## Overview
|
|
9
8
|
|
|
10
9
|
Layout components hold other components. They come in two kinds.
|
|
@@ -18,7 +17,7 @@ See the [settings-page screenshot](/docs/building/settings-pages) for the frame
|
|
|
18
17
|
|
|
19
18
|
**Containers** are builders: `Grid`, `GridRow`, `HStack`, `VStack`, `Spacer`, `Tab`, `Guard` and `Placeholder` return a `ComponentBuilder`, and you nest components inside them with `.child(id, component)`. They are assigned to a static field of a page class like any other component.
|
|
20
19
|
|
|
21
|
-
**Page layouts** are not builders: `DefaultLayout`, `FormPageLayout`, `SettingsLayout` and `EmptyLayout` return a plain `ComponentInfo` and are passed as the third argument of `PageController
|
|
20
|
+
**Page layouts** are not builders: `DefaultLayout`, `FormPageLayout`, `SettingsLayout` and `EmptyLayout` return a plain `ComponentInfo` and are passed as the third argument of `PageController`, or as the `layout` option of a page or category (the default of everything declared under it), to say how the page's chrome is drawn.
|
|
22
21
|
|
|
23
22
|
`CustomComponent` sits outside both: it names a Vue component from the frontend registry and gives you a builder for it, which is the escape hatch when the vocabulary on this page is not enough.
|
|
24
23
|
|
|
@@ -38,7 +37,7 @@ import { CustomComponent } from "@antelopejs/interface-dms/base/custom";
|
|
|
38
37
|
|
|
39
38
|
`Grid` is a container whose direct children are `GridRow`s. The number of columns follows the widest row.
|
|
40
39
|
|
|
41
|
-
```typescript
|
|
40
|
+
```typescript fragment
|
|
42
41
|
import { Grid, GridRow } from "@antelopejs/interface-dms/base/grid";
|
|
43
42
|
import { KpiCard } from "@antelopejs/interface-dms/base";
|
|
44
43
|
|
|
@@ -60,9 +59,9 @@ static kpis = Grid({ gap: "1rem" }).child(
|
|
|
60
59
|
|
|
61
60
|
`GridRow()` takes no options. Its children are laid out horizontally within the row.
|
|
62
61
|
|
|
63
|
-
`.child()` accepts a third argument of extra metadata, which is carried verbatim onto the serialized child alongside its `id
|
|
62
|
+
`.child()` accepts a third argument of extra metadata, which is carried verbatim onto the serialized child alongside its `id`. That is how a child declares that it spans more than one column:
|
|
64
63
|
|
|
65
|
-
```typescript
|
|
64
|
+
```typescript fragment
|
|
66
65
|
GridRow().child("chart", chartCard, { colSpan: 2 }).child("list", topListCard);
|
|
67
66
|
```
|
|
68
67
|
|
|
@@ -70,7 +69,7 @@ GridRow().child("chart", chartCard, { colSpan: 2 }).child("list", topListCard);
|
|
|
70
69
|
|
|
71
70
|
`HStack` and `VStack` arrange their children along one axis; `Spacer` fills the leftover space between them.
|
|
72
71
|
|
|
73
|
-
```typescript
|
|
72
|
+
```typescript fragment
|
|
74
73
|
import { HStack, Spacer } from "@antelopejs/interface-dms/base/stack";
|
|
75
74
|
|
|
76
75
|
static toolbar = HStack({ alignment: "center", distribution: "space-between", spacing: "16px" })
|
|
@@ -81,7 +80,7 @@ static toolbar = HStack({ alignment: "center", distribution: "space-between", sp
|
|
|
81
80
|
|
|
82
81
|
`StackAlignment` is `"start" | "center" | "end" | "stretch"` and `StackDistribution` is `"start" | "center" | "end" | "space-between" | "space-around" | "space-evenly"`.
|
|
83
82
|
|
|
84
|
-
### HStackOptions
|
|
83
|
+
### `HStackOptions`
|
|
85
84
|
|
|
86
85
|
| Option | Type | Description |
|
|
87
86
|
| --- | --- | --- |
|
|
@@ -91,7 +90,7 @@ static toolbar = HStack({ alignment: "center", distribution: "space-between", sp
|
|
|
91
90
|
| `wrap` | `boolean` | Wrap children onto the next line when the row runs out of space. Defaults to `false`. |
|
|
92
91
|
| `grow` | `number` | Share of the parent stack's free space this stack takes, against its siblings. Unset, a stack nested in an `HStack` shares the row equally with its sibling stacks, or keeps its content width when the row has a `Spacer`. |
|
|
93
92
|
|
|
94
|
-
### VStackOptions
|
|
93
|
+
### `VStackOptions`
|
|
95
94
|
|
|
96
95
|
| Option | Type | Description |
|
|
97
96
|
| --- | --- | --- |
|
|
@@ -100,7 +99,7 @@ static toolbar = HStack({ alignment: "center", distribution: "space-between", sp
|
|
|
100
99
|
| `spacing` | `string` | Space between children, as a CSS length. Defaults to `"8px"`. |
|
|
101
100
|
| `grow` | `number` | Share of the parent stack's free space this stack takes, against its siblings. Unset, a stack nested in an `HStack` shares the row equally with its sibling stacks, or keeps its content width when the row has a `Spacer`. |
|
|
102
101
|
|
|
103
|
-
### SpacerOptions
|
|
102
|
+
### `SpacerOptions`
|
|
104
103
|
|
|
105
104
|
| Option | Type | Description |
|
|
106
105
|
| --- | --- | --- |
|
|
@@ -114,7 +113,7 @@ The three builders apply their defaults into the options they carry, so a `Space
|
|
|
114
113
|
|
|
115
114
|
`Tab` declares a tab bar. Each `TabItem` names a `slot`, and the component that belongs in a tab is attached as a child with that slot.
|
|
116
115
|
|
|
117
|
-
```typescript
|
|
116
|
+
```typescript fragment
|
|
118
117
|
import { Tab, TabVariant } from "@antelopejs/interface-dms/base/tab";
|
|
119
118
|
import { Color, Size } from "@antelopejs/interface-dms/base/types";
|
|
120
119
|
|
|
@@ -133,7 +132,7 @@ static tabs = Tab({
|
|
|
133
132
|
.child("members", membersTable, { slot: "members" });
|
|
134
133
|
```
|
|
135
134
|
|
|
136
|
-
### TabProps
|
|
135
|
+
### `TabProps`
|
|
137
136
|
|
|
138
137
|
`TabProps` extends [`BaseComponentProps`](/docs/interfaces/base/types).
|
|
139
138
|
|
|
@@ -149,7 +148,7 @@ static tabs = Tab({
|
|
|
149
148
|
| `persistState` | `boolean` | Keep the active tab in the URL by its slot (`?<stateKey>=<slot>`); an index (`?tab=2`) is still read. |
|
|
150
149
|
| `stateKey` | `string` | Key the state is stored under. |
|
|
151
150
|
|
|
152
|
-
### TabItem
|
|
151
|
+
### `TabItem`
|
|
153
152
|
|
|
154
153
|
| Field | Type | Description |
|
|
155
154
|
| --- | --- | --- |
|
|
@@ -165,261 +164,11 @@ static tabs = Tab({
|
|
|
165
164
|
|
|
166
165
|
`TabEvents.TAB_CHANGE` is `"DmsComponent.Tab.Change"`.
|
|
167
166
|
|
|
168
|
-
## Page Layouts
|
|
169
|
-
|
|
170
|
-
A page layout is the third argument of `PageController`. It is optional: a page that omits it is registered with `DefaultLayout()` and its default options.
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
import {
|
|
174
|
-
PageController,
|
|
175
|
-
pagesCategory,
|
|
176
|
-
RegisterPage,
|
|
177
|
-
} from "@antelopejs/interface-dms/page";
|
|
178
|
-
import { DefaultLayout } from "@antelopejs/interface-dms/base/layouts";
|
|
179
|
-
|
|
180
|
-
@RegisterPage()
|
|
181
|
-
export class OverviewPage extends PageController(
|
|
182
|
-
"overview",
|
|
183
|
-
{ displayName: "Overview", icon: "i-ph-gauge", category: pagesCategory },
|
|
184
|
-
DefaultLayout({ hideHeader: true }),
|
|
185
|
-
) {
|
|
186
|
-
static content = overviewGrid;
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
`DefaultLayout(options?)` returns the `ComponentInfo` for `dms-default-layout`.
|
|
191
|
-
|
|
192
|
-
| Option | Type | Description |
|
|
193
|
-
| --- | --- | --- |
|
|
194
|
-
| `fullWidth` | `boolean` | Let the content span the whole panel instead of a constrained column. Defaults to `true`. |
|
|
195
|
-
| `hideHeader` | `boolean` | Omit the page header. |
|
|
196
|
-
| `fillHeight` | `boolean` | Let the page fill the height of the panel instead of growing with its content, for a tool that scrolls inside itself — see [Pages that fill the panel](#pages-that-fill-the-panel). Defaults to `false`. |
|
|
197
|
-
| `headerActions` | `CustomButton[]` | Buttons right of the page title, in order — see [Header actions](#header-actions). |
|
|
198
|
-
| `record` | `PageRecordLoader` | Reads the record the page shows, with the layout, for the header buttons acting on it and every `availability` of the page — see [Buttons acting on the page's record](#buttons-acting-on-the-pages-record). |
|
|
199
|
-
|
|
200
|
-
Dashboard pages are full-width unless they opt out, which is what a table, a grid of cards or a chart wants. Set `fullWidth: false` for a page that only holds a form, where a constrained column stays readable — or use `FormPageLayout`, which is exactly that:
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
import { FormPageLayout } from "@antelopejs/interface-dms/base/layouts";
|
|
204
|
-
|
|
205
|
-
const layout = FormPageLayout({ hideHeader: true });
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
Its optional argument accepts `DefaultLayoutOptions` without `fullWidth`; the return value is a `ComponentInfo`.
|
|
209
|
-
|
|
210
|
-
The generated `new` and `edit` pages of a table view use it, unless their page's category chain declares a layout, so a form page you write by hand matches them without your having to remember the flag.
|
|
211
|
-
|
|
212
|
-
`SettingsLayout(options?)` returns the `ComponentInfo` for `dms-settings-layout`: the dashboard frame with the settings navigation next to the page, in the column width every settings page shares. Its options are `DefaultLayoutOptions` without `fullWidth`. `settingsCategory` declares it as its `layout`, so the pages under the settings root get it without naming it ([Settings pages](/docs/building/settings-pages)).
|
|
213
|
-
|
|
214
|
-
`EmptyLayout()` takes no options and returns the `ComponentInfo` for `dms-empty-layout`, with an empty options object. Use it for pages that draw their own chrome — sign-in and onboarding screens, for instance.
|
|
215
|
-
|
|
216
|
-
Because they return a plain `ComponentInfo` rather than a `ComponentBuilder`, the page layouts have no `.child()`, `.meta()` or `.watch()`.
|
|
217
|
-
|
|
218
|
-
### Header actions
|
|
219
|
-
|
|
220
|
-
A page puts its main actions next to its title — a primary "New invoice", an "Export", a link to the docs — with `headerActions`: the same `CustomButton`s as a table's toolbar (see [Tables](/docs/components/tables)), plus an `order` (`PageHeaderButton`), so a header button opens a link, runs a [quick action](/docs/interfaces/core/quick-actions), opens a drawer or a modal, calls an API or runs an export, with a confirmation and an availability of its own:
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
import { DefaultLayout } from "@antelopejs/interface-dms/base/layouts";
|
|
224
|
-
|
|
225
|
-
DefaultLayout({
|
|
226
|
-
headerActions: [
|
|
227
|
-
{
|
|
228
|
-
id: "docs",
|
|
229
|
-
label: "Documentation",
|
|
230
|
-
icon: "i-ph-book-open",
|
|
231
|
-
target: { type: "external", url: "https://antelopejs.com/docs", newTab: true },
|
|
232
|
-
},
|
|
233
|
-
// An empty label lends the quick action's name (and its icon).
|
|
234
|
-
{ id: "new", label: "", color: "primary", target: { type: "quickAction", id: "billing:new-invoice" } },
|
|
235
|
-
{
|
|
236
|
-
id: "audit",
|
|
237
|
-
label: "Audit log",
|
|
238
|
-
icon: "i-ph-scroll",
|
|
239
|
-
target: { type: "page", url: "/audit" },
|
|
240
|
-
permission: "audit", // pages.billing.audit on the page pages.billing
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
});
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
| Field | Type | Description |
|
|
247
|
-
| --- | --- | --- |
|
|
248
|
-
| `id` | `string` | Key of the button, unique in the header. Defaults to its place (`header-0`, …). |
|
|
249
|
-
| `label` | `string` | Button text (i18n key with `$` or literal). A quick action lends its own name to an empty label. |
|
|
250
|
-
| `icon` | `string` | Icon name. A quick action lends its own icon. |
|
|
251
|
-
| `target` | `ActionTarget` | What the button does: `page` or `external` (drawn as a link), `quickAction` (`{ id }`: `category:id`, or the bare id), `drawer`, `modal`, `api`, `exportJob`, `download` (`{ url, filename? }`: fetched with the user's session and saved). |
|
|
252
|
-
| `confirm` | `ConfirmDialog \| { from }` | Asked before the target runs. |
|
|
253
|
-
| `color` | `"primary" \| "neutral" \| …` | Defaults to `neutral`, an outline button; any other color is solid. |
|
|
254
|
-
| `variant` | `ButtonVariant` | Overrides the fill derived from the color. |
|
|
255
|
-
| `permission` | `string \| Action` | Action of the page, relative to its permission id (`"export"` on `pages.sales` → `pages.sales.export`), or an `Action` of any component, the user must hold to see the button. |
|
|
256
|
-
| `permissionId` | `string` | Absolute permission id the user must hold to see the button; wins over `permission`. |
|
|
257
|
-
| `availability` | `CustomButtonAvailability` | Disables the button for a request it answers `{ reason }` with, the reason shown in a tooltip; leaves it out of the header for one it answers `{ hidden: true }`. Receives the page URL's query as `context.query`. |
|
|
258
|
-
| `order` | `number` | Place among the header's buttons, smallest first; defaults to `0`. See [Ordering the header](#ordering-the-header). |
|
|
259
|
-
|
|
260
|
-
#### Buttons that follow the page URL
|
|
261
|
-
|
|
262
|
-
A page scoped by its URL — `?workspace=web`, a record id in the path — declares its buttons once and lets them follow the URL. A target's URL (`page`, `external`, `download`, `api`, `exportJob`) takes the tokens of a block's `fetchUrl`: `{{params.X}}` is filled with the route parameter `X` of the page, `{{query.X}}` with its query parameter `X`, percent-encoded, again whenever the URL changes. A query pair whose value is a token the page has no value for is left out (`?workspace={{query.workspace}}` on a page without `?workspace=` leads to the target's default), and any other token without a value is left empty. A `download` target's `filename` takes the same tokens, written as they are; while one has no value, the file is saved under the server's name:
|
|
263
|
-
|
|
264
|
-
```ts
|
|
265
|
-
{
|
|
266
|
-
id: "download-language",
|
|
267
|
-
label: "$lang.queue.download", // "Download {locale}.json"
|
|
268
|
-
icon: "i-ph-download-simple",
|
|
269
|
-
target: {
|
|
270
|
-
type: "download",
|
|
271
|
-
url: "/api/lang/translations/export?workspace={{query.workspace}}&locale={{query.locale}}",
|
|
272
|
-
filename: "{{query.locale}}.json",
|
|
273
|
-
},
|
|
274
|
-
}
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
A label's translation takes the page's route and query parameters as its own (a query parameter wins over a route parameter of the same name), so `"Download {locale}.json"` names the language of `?locale=fr` and follows it as the URL changes.
|
|
278
|
-
|
|
279
|
-
An `availability` receives the page URL's query as `context.query` (one value per name; caller-supplied, so check it like any input), its route parameters as `context.params` (`/projects/project/p1` on a page registered at `/projects/project/:id` is `{ id: "p1" }`), and the record the layout read as `context.record` ([Buttons acting on the page's record](#buttons-acting-on-the-pages-record)). The header asks again whenever the query or the route parameters change, and once a write refreshed the page — only when one of its buttons declares an `availability` or the layout reads a `record` — and keeps the buttons it has until the answer lands. The keys the DMS writes for the view itself never cause a request: `record` (the row open in a side panel), `live` (the paused live mode) and a period selector's `<id>.period`, `<id>.compare`, `<id>.from`, `<id>.to`, `<id>.compareFrom` and `<id>.compareTo`. A query key may carry dots, so `{{query.api.period}}` reads a period selector's choice.
|
|
280
|
-
|
|
281
|
-
```typescript
|
|
282
|
-
DefaultLayout({
|
|
283
|
-
headerActions: [
|
|
284
|
-
{
|
|
285
|
-
id: "matrix",
|
|
286
|
-
label: "$lang.queue.open_matrix",
|
|
287
|
-
icon: "i-ph-table",
|
|
288
|
-
target: { type: "page", url: "/modules/lang/translations?workspace={{query.workspace}}&missingIn={{params.locale}}" },
|
|
289
|
-
},
|
|
290
|
-
{
|
|
291
|
-
id: "download",
|
|
292
|
-
label: "$lang.queue.download",
|
|
293
|
-
target: { type: "api", url: "/api/lang/export?workspace={{query.workspace}}", successMessage: "$lang.exported" },
|
|
294
|
-
availability: async ({ query }) =>
|
|
295
|
-
(await workspaceExists(query?.workspace)) ? undefined : { reason: "$lang.workspace.unknown" },
|
|
296
|
-
},
|
|
297
|
-
],
|
|
298
|
-
});
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
A table view of the page places its own buttons in the header with `placement: "header"` — a custom button, or its built-in add (`rowActions: { add: { placement: "header" } }`): the server adds them after the layout's own buttons, served as the table view was (left out without its permission or when its `availability` hides it, disabled with the reason its `availability` gives), and the table view runs them, in place. They take the order `0`.
|
|
302
|
-
|
|
303
|
-
Who sees a button is settled on the server when the layout is served: a button whose `permission` or `permissionId` the user lacks is left out of the layout, and a quick-action button only shows to the users the quick action is served to — that is, the users its page admits. A page drawn by a Vue page component can add its own buttons next to these with `usePageHeaderActions`; call it before the first `await` of the component's setup, so the server renders the buttons with the page and they never pop in. A page whose changes save as soon as they are made shows the shared **Saved instantly** pill there with `useInstantSaveHeader` ([Instant save or a save bar](/docs/components/lists-and-settings/section#instant-save-or-a-save-bar)).
|
|
304
|
-
|
|
305
|
-
#### Buttons acting on the page's record
|
|
306
|
-
|
|
307
|
-
A page about one record (a site, an invoice) reads it with its layout: `record` is a function the server calls each time it serves the layout, with the request's context — the page URL's `params` and `query`, the `user` and the `tenantId` — and answers the record, or `undefined` when there is none to show. A button's target names its fields as `{{record.X}}`, filled in by the server and percent-encoded: a maps link to the site's address, an API call on its own id. A button acting on the record — one whose target names `{{record.X}}`, or declaring `requiresRecord: true` (an "Edit" link that only needs `{{params.id}}`) — is left out of a page whose record was not found, or whose `record` threw (logged). Every `availability` of the page reads the record as `context.record`, so a button can be disabled on the record's state without reading it again:
|
|
308
|
-
|
|
309
|
-
```typescript
|
|
310
|
-
DefaultLayout({
|
|
311
|
-
record: ({ params }) => GetModel(SiteModel).get(params?.id ?? ""),
|
|
312
|
-
headerActions: [
|
|
313
|
-
{
|
|
314
|
-
label: "$sites.directions",
|
|
315
|
-
icon: "i-ph-map-pin",
|
|
316
|
-
target: { type: "external", url: "https://www.google.com/maps/search/?api=1&query={{record.address}}", newTab: true },
|
|
317
|
-
},
|
|
318
|
-
{ label: "$sites.edit", requiresRecord: true, target: { type: "page", url: "/sites/{{params.id}}/edit" } },
|
|
319
|
-
{
|
|
320
|
-
label: "$sites.close",
|
|
321
|
-
target: { type: "api", url: "/api/sites/close?id={{params.id}}" },
|
|
322
|
-
availability: ({ record }) => (record?.closed ? { reason: "$sites.already_closed" } : undefined),
|
|
323
|
-
},
|
|
324
|
-
],
|
|
325
|
-
});
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
The record travels with the layout, so the header is drawn with it, on the server too, and never waits for it. Like an `availability`, it follows the page URL: the header asks for its buttons again when the route parameters or the query change, and once a write refreshed the page (`refreshPageBlocks()`, which a header button calls after a change, and a form once it saved). Its fields only shape the buttons; the route behind each one still checks the record on its own.
|
|
329
|
-
|
|
330
|
-
#### A record deleted under the page
|
|
331
|
-
|
|
332
|
-
A page reading a `record` leaves it once it is deleted, in every tab and for every member on it, with no code of the module. On each event of one of the page's realtime topics (its table views' rows, a `realtimeTopic`, a topic bound with `RegisterPageTopic`), the page asks its layout again: a record the server found before and now finds none of (its `record` answers `undefined`) was deleted. A toast says so, and the page opens the list it is a detail of (`MenuOptions.parent`); without one, it stays, on the "not found" state of its blocks. A `record` that throws counts as unknown, never as deleted, and a page opened on a record that never existed shows its blocks' "not found" state without a toast. Publish on one of the page's topics when the record is deleted: a table view's delete does it on its own.
|
|
333
|
-
|
|
334
|
-
#### Hidden or disabled
|
|
335
|
-
|
|
336
|
-
An `availability` has three answers. `undefined` leaves the button as declared, `{ reason }` disables it with the reason in a tooltip — for something the user can change ("No seat left: upgrade the plan") — and `{ hidden: true }` leaves it out of the header, as a missing permission does — for a button that makes no sense in the scope the page shows. Like a disabled one, a hidden button follows the page URL: the header asks again when the query changes, so a button can disappear on one `?workspace=` and come back on another, and the server-rendered header already carries the answer for the URL it was rendered for.
|
|
337
|
-
|
|
338
|
-
```typescript
|
|
339
|
-
DefaultLayout({
|
|
340
|
-
headerActions: [
|
|
341
|
-
{
|
|
342
|
-
id: "add-key",
|
|
343
|
-
label: "$lang.keys.add",
|
|
344
|
-
color: "primary",
|
|
345
|
-
target: { type: "drawer", component: AddKeyForm() },
|
|
346
|
-
availability: async ({ query }) =>
|
|
347
|
-
(await workspaceOf(query?.workspace))?.readOnly ? { hidden: true } : undefined,
|
|
348
|
-
},
|
|
349
|
-
],
|
|
350
|
-
});
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
A detail page reads its record from `context.params`, and hides the buttons that act on it when the record does not exist — the page then shows its "not found" state with no "Edit" or "Delete" beside the title:
|
|
354
|
-
|
|
355
|
-
```typescript
|
|
356
|
-
DefaultLayout({
|
|
357
|
-
headerActions: [
|
|
358
|
-
{
|
|
359
|
-
id: "edit",
|
|
360
|
-
label: "$projects.edit",
|
|
361
|
-
target: { type: "page", url: "/projects/project/{{params.id}}/edit" },
|
|
362
|
-
availability: async ({ params }) =>
|
|
363
|
-
(await projectExists(params?.id)) ? undefined : { hidden: true },
|
|
364
|
-
},
|
|
365
|
-
],
|
|
366
|
-
});
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
Hiding only shapes the UI: the route behind the button must still refuse the operation on its own.
|
|
370
|
-
|
|
371
|
-
#### Ordering the header
|
|
372
|
-
|
|
373
|
-
The header shows, left to right, the buttons the layout declares, the buttons a table view places there (`placement: "header"`), then the actions a Vue component of the page adds with `usePageHeaderActions` ([UI toolkit](/docs/frontend-composables/ui-toolkit#page-header-actions-usepageheaderactions)). To interleave them, give a button an `order` and the component's actions one too (`usePageHeaderActions(render, { order })`): the header sorts everything by `order`, smallest first, `0` when none is given, and at an equal order keeps the served buttons first, in the order above. So `{ order: -1 }` on a component's actions puts them before every served button left at the default:
|
|
374
|
-
|
|
375
|
-
```typescript
|
|
376
|
-
// The served "Add key" stays at the default order, 0.
|
|
377
|
-
DefaultLayout({ headerActions: [{ id: "add-key", label: "$lang.keys.add", color: "primary", target }] });
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
```vue [app/components/TranslationMatrix.vue]
|
|
381
|
-
<script setup lang="ts">
|
|
382
|
-
import { usePageHeaderActions } from "#dms-layout/app/composables/layout/usePageHeaderActions";
|
|
383
|
-
|
|
384
|
-
// Export, built in the browser, goes before the served "Add key".
|
|
385
|
-
usePageHeaderActions(() => h(UButton, { label: t("lang.export"), icon: "i-ph-download-simple", onClick: exportCsv }), { order: -1 });
|
|
386
|
-
</script>
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
### Pages that fill the panel
|
|
390
|
-
|
|
391
|
-
A page built around one tool — a file explorer, a data grid, a graph canvas — usually wants that tool to take the height of the panel and scroll inside itself, rather than make the whole page scroll. Set `fillHeight` on its layout:
|
|
392
|
-
|
|
393
|
-
```typescript
|
|
394
|
-
DefaultLayout({ fillHeight: true })
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
The layout then lays the page out as a flex column the height of the panel. The page header keeps its own height and the height left under it goes to the **last component** of the page; the components above it keep theirs. Give the root of that component `flex-1 min-h-0`, and let an element inside it scroll:
|
|
398
|
-
|
|
399
|
-
```vue [app/components/MyExplorer.vue]
|
|
400
|
-
<template>
|
|
401
|
-
<div class="flex min-h-0 flex-1 flex-col gap-4">
|
|
402
|
-
<MyToolbar />
|
|
403
|
-
<div class="min-h-0 flex-1 overflow-y-auto">
|
|
404
|
-
<!-- the rows -->
|
|
405
|
-
</div>
|
|
406
|
-
</div>
|
|
407
|
-
</template>
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
A custom page — a page component your frontend layer registers under the page's slug — sits straight in the layout, so its own root takes `flex-1 min-h-0` the same way.
|
|
411
|
-
|
|
412
|
-
Do not size the tool from the viewport, with `h-[calc(100vh-…)]` or an offset measured in the browser. The dashboard header, the [layout banners](/docs/interfaces/core/layout-banners), the page header and the panel padding all take height above the page, and that height changes: a banner shows up or is dismissed, a description wraps. The layout accounts for all of it.
|
|
413
|
-
|
|
414
|
-
- **Minimum height.** The page area, header included, never gets shorter than 30rem: on a shorter panel it stops shrinking and the panel scrolls again. The floor sits on the page area rather than on the tool, because a `min-h-*` set inside the page overflows the column, and the panel then scrolls past its own bottom padding. A tool that needs more room than what is left to it at that floor — one that shares its component with a card of figures, say — can still set its own `min-h-*`, at that cost.
|
|
415
|
-
- **Every width.** The page fills the panel on a phone too: the panel is the part of the dashboard that scrolls at every width. A page whose panes stack on a narrow screen (`grid-cols-1 lg:grid-cols-[…]`) decides how they share the height there, or lets its own root scroll below that breakpoint (`max-lg:overflow-y-auto`).
|
|
416
|
-
- **Several components.** Only the last one fills. Put the tool last, under whatever summarizes it, or keep both in one component that lays them out itself.
|
|
417
|
-
|
|
418
167
|
## Guard
|
|
419
168
|
|
|
420
169
|
`Guard` is a container that renders its children unchanged unless a route says there is nothing for them; then it renders one `EmptyState`, its `fallback`, in their place. Several children stack with the spacing the page puts between its blocks.
|
|
421
170
|
|
|
422
|
-
```typescript
|
|
171
|
+
```typescript fragment
|
|
423
172
|
import { Guard } from "@antelopejs/interface-dms/base/guard";
|
|
424
173
|
|
|
425
174
|
static statistics = Guard({
|
|
@@ -451,7 +200,7 @@ An `emptyState` object in the answer, or in the body of the 404, is laid over `f
|
|
|
451
200
|
|
|
452
201
|
`Placeholder` renders a labelled box. It exists so a layout can be assembled and reviewed before the real components are written. It takes `PlaceholderOptions`:
|
|
453
202
|
|
|
454
|
-
```typescript
|
|
203
|
+
```typescript fragment
|
|
455
204
|
import { Placeholder } from "@antelopejs/interface-dms/base/placeholder";
|
|
456
205
|
|
|
457
206
|
static preview = Placeholder({ label: "Chart goes here", height: "200px" });
|
|
@@ -463,11 +212,11 @@ static preview = Placeholder({ label: "Chart goes here", height: "200px" });
|
|
|
463
212
|
| `height` | `string` | CSS height. Defaults to `"120px"`. |
|
|
464
213
|
| `width` | `string` | CSS width. Auto by default. |
|
|
465
214
|
|
|
466
|
-
## CustomComponent
|
|
215
|
+
## `CustomComponent`
|
|
467
216
|
|
|
468
217
|
`CustomComponent(componentName)` returns a bare `ComponentBuilder` for a frontend component resolved by name. Nothing else in the `base` domain is involved: the options you pass with `.options()` are handed to that component as-is, and the component itself comes from a frontend module registered with `AddFrontendModule`.
|
|
469
218
|
|
|
470
|
-
```typescript
|
|
219
|
+
```typescript fragment
|
|
471
220
|
import { CustomComponent } from "@antelopejs/interface-dms/base/custom";
|
|
472
221
|
|
|
473
222
|
static activity = CustomComponent("DmsAiActivityView").meta({
|
|
@@ -478,6 +227,8 @@ static activity = CustomComponent("DmsAiActivityView").meta({
|
|
|
478
227
|
|
|
479
228
|
Since the return value is an ordinary builder, `.options()`, `.child()`, `.meta()`, `.watch()`, `.onCreated()` and `.onFilter()` all apply, and the component can hold `base` components as children.
|
|
480
229
|
|
|
481
|
-
`CustomComponent` is also how a table view's `formContainer.pages.*.customPage` option is used: you register your own page carrying a custom component at the slug the table view would otherwise generate
|
|
230
|
+
`CustomComponent` is also how a table view's `formContainer.pages.*.customPage` option is used: you register your own page carrying a custom component at the slug the table view would otherwise generate. Declare that slug as the entry's `urlSlug`, which is taken relative to the page as it stands. See [Tables](/docs/interfaces/base/tables).
|
|
231
|
+
|
|
232
|
+
## Next steps
|
|
482
233
|
|
|
483
|
-
|
|
234
|
+
- [Page layouts](/docs/interfaces/base/page-layouts): The layouts a page renders in, its header actions, and pages that fill the panel.
|