@cosmicdrift/kumiko-bundled-features 0.362.0 → 0.364.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/dist/admin-shell/feature.d.ts +3 -0
- package/dist/admin-shell/feature.js +6 -1
- package/dist/agent-tools/agent-manifest.js +2 -1
- package/dist/agent-tools/filter-ops.d.ts +1 -1
- package/dist/agent-tools/filter-ops.js +1 -3
- package/dist/agent-tools/tool-dispatch.js +2 -1
- package/dist/audit/handlers/list.query.js +9 -5
- package/dist/auth-email-password/bootstrap.d.ts +8 -5
- package/dist/auth-email-password/bootstrap.js +12 -4
- package/dist/auth-email-password/email-rate-limits.d.ts +4 -0
- package/dist/auth-email-password/email-rate-limits.js +13 -0
- package/dist/auth-email-password/email-templates.d.ts +4 -26
- package/dist/auth-email-password/email-templates.js +9 -101
- package/dist/auth-email-password/feature.js +24 -6
- package/dist/auth-email-password/handlers/change-password.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +6 -2
- package/dist/auth-email-password/handlers/confirm-account-unlock.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +4 -4
- package/dist/auth-email-password/handlers/invite-signup-complete.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/logout.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/logout.write.js +6 -2
- package/dist/auth-email-password/handlers/request-account-unlock.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-account-unlock.write.js +2 -4
- package/dist/auth-email-password/handlers/request-email-verification.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-email-verification.write.js +2 -4
- package/dist/auth-email-password/handlers/request-password-reset.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-password-reset.write.js +2 -4
- package/dist/auth-email-password/handlers/reset-password.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.js +3 -4
- package/dist/auth-email-password/handlers/signup-request.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-request.write.js +2 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/token-request-handler.d.ts +2 -3
- package/dist/auth-email-password/handlers/token-request-handler.js +2 -2
- package/dist/auth-email-password/handlers/verify-email.write.d.ts +1 -1
- package/dist/auth-email-password/index.d.ts +2 -2
- package/dist/auth-email-password/index.js +1 -1
- package/dist/auth-email-password/magic-link-mail.d.ts +3 -2
- package/dist/auth-email-password/magic-link-mail.js +19 -14
- package/dist/auth-email-password/mail-notifications.d.ts +32 -0
- package/dist/auth-email-password/mail-notifications.js +116 -0
- package/dist/auth-email-password/signup-activation.d.ts +1 -1
- package/dist/auth-email-password/signup-activation.js +2 -3
- package/dist/auth-email-password/web/auth-gate.js +16 -4
- package/dist/auth-foundation/types.js +2 -8
- package/dist/auth-mfa/feature.js +4 -4
- package/dist/auth-mfa/handlers/disable.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-start-preauth.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-start.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/verify.write.d.ts +1 -1
- package/dist/auth-mfa/hmac-token-codec.js +4 -4
- package/dist/auth-mfa/mfa-challenge-token.js +3 -3
- package/dist/auth-mfa/mfa-preauth-setup-token.js +3 -3
- package/dist/auth-mfa/mfa-setup-token.js +8 -8
- package/dist/billing-foundation/constants.d.ts +3 -3
- package/dist/billing-foundation/constants.js +5 -4
- package/dist/billing-foundation/consumer-protection/confirmation-mail.d.ts +32 -14
- package/dist/billing-foundation/consumer-protection/confirmation-mail.js +74 -32
- package/dist/billing-foundation/consumer-protection/consent-gate.d.ts +3 -0
- package/dist/billing-foundation/consumer-protection/consent-gate.js +21 -2
- package/dist/billing-foundation/consumer-protection/issue-confirmation.js +3 -3
- package/dist/billing-foundation/consumer-protection/mail-notifications.d.ts +8 -0
- package/dist/billing-foundation/consumer-protection/mail-notifications.js +95 -0
- package/dist/billing-foundation/consumer-protection/register-consent.js +2 -0
- package/dist/billing-foundation/consumer-protection/register-termination.js +11 -1
- package/dist/billing-foundation/consumer-protection/termination-mail.d.ts +25 -13
- package/dist/billing-foundation/consumer-protection/termination-mail.js +11 -23
- package/dist/billing-foundation/consumer-protection/termination-notify.js +2 -2
- package/dist/billing-foundation/consumer-protection/termination-pages.js +1 -3
- package/dist/billing-foundation/consumer-protection/termination-receipt-limit.d.ts +6 -0
- package/dist/billing-foundation/consumer-protection/termination-receipt-limit.js +34 -0
- package/dist/billing-foundation/consumer-protection/termination-record.d.ts +2 -0
- package/dist/billing-foundation/consumer-protection/termination-record.js +7 -1
- package/dist/billing-foundation/consumer-protection/termination-request.js +31 -21
- package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +1 -1
- package/dist/billing-foundation/consumer-protection/termination-texts.js +6 -0
- package/dist/billing-foundation/consumer-protection/withdrawal-period.d.ts +10 -0
- package/dist/billing-foundation/consumer-protection/withdrawal-period.js +26 -0
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +11 -5
- package/dist/billing-foundation/handlers/process-event.write.js +12 -8
- package/dist/billing-foundation/handlers/process-payment-event.write.js +1 -1
- package/dist/billing-foundation/i18n.js +3 -0
- package/dist/billing-foundation/subscription-tier-sync.d.ts +7 -1
- package/dist/billing-foundation/subscription-tier-sync.js +16 -9
- package/dist/billing-foundation/types.d.ts +7 -2
- package/dist/cap-counter/calendar-cap-usage-reservation.js +2 -0
- package/dist/cap-counter/enforce-cap.d.ts +18 -1
- package/dist/cap-counter/enforce-cap.js +49 -6
- package/dist/cap-counter/index.d.ts +1 -1
- package/dist/cap-counter/index.js +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +2 -0
- package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -1
- package/dist/cap-overview/web/cap-usage-cell.js +5 -4
- package/dist/channel-email/email-channel.d.ts +2 -2
- package/dist/channel-email/email-channel.js +101 -26
- package/dist/channel-email/feature.js +3 -3
- package/dist/channel-email/index.d.ts +1 -1
- package/dist/channel-email/index.js +1 -1
- package/dist/channel-email/pii-guard.js +10 -0
- package/dist/channel-email/smtp-transport.js +13 -0
- package/dist/channel-email/types.d.ts +8 -0
- package/dist/channel-in-app/handlers/mark-all-read.write.d.ts +1 -1
- package/dist/channel-in-app/handlers/mark-read.write.d.ts +1 -1
- package/dist/compliance-profiles/handlers/set-profile.write.d.ts +1 -1
- package/dist/config/handlers/reset.write.d.ts +1 -1
- package/dist/config/handlers/set.write.d.ts +1 -1
- package/dist/config/handlers/set.write.js +3 -4
- package/dist/config/resolver.d.ts +1 -0
- package/dist/config/resolver.js +11 -14
- package/dist/config/write-helpers.d.ts +2 -0
- package/dist/config/write-helpers.js +19 -0
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.js +29 -19
- package/dist/custom-fields/handlers/update-tenant-field.write.js +0 -1
- package/dist/custom-fields/lib/value-schema.js +10 -11
- package/dist/custom-fields/wire-user-data-rights.js +7 -6
- package/dist/data-retention/index.d.ts +1 -0
- package/dist/data-retention/index.js +1 -0
- package/dist/data-retention/run-retention-cleanup.js +6 -6
- package/dist/delivery/attachment-ref.d.ts +41 -0
- package/dist/delivery/attachment-ref.js +78 -0
- package/dist/delivery/channel-context.d.ts +8 -4
- package/dist/delivery/channel-context.js +94 -2
- package/dist/delivery/constants.d.ts +1 -0
- package/dist/delivery/constants.js +1 -0
- package/dist/delivery/delivery-service.d.ts +4 -1
- package/dist/delivery/delivery-service.js +38 -32
- package/dist/delivery/feature.js +1 -1
- package/dist/delivery/handlers/resubscribe-address.write.d.ts +1 -1
- package/dist/delivery/handlers/resubscribe-user.write.d.ts +1 -1
- package/dist/delivery/handlers/set-preference.write.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-address.write.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-user.write.d.ts +1 -1
- package/dist/delivery/index.d.ts +5 -2
- package/dist/delivery/index.js +4 -1
- package/dist/delivery/jobs.js +66 -14
- package/dist/delivery/notify-factory.js +4 -1
- package/dist/delivery/testing.d.ts +4 -1
- package/dist/delivery/types.d.ts +26 -14
- package/dist/delivery/unsubscribe.js +4 -1
- package/dist/derivatives-sharp/render.js +1 -18
- package/dist/document-ingest-foundation/pages.js +4 -4
- package/dist/feature-toggles/handlers/set.write.d.ts +1 -1
- package/dist/feature-toggles/toggle-sync-signal.js +4 -4
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-foundation/index.d.ts +1 -0
- package/dist/file-foundation/index.js +1 -0
- package/dist/file-foundation/read-file-ref-content.d.ts +27 -0
- package/dist/file-foundation/read-file-ref-content.js +51 -0
- package/dist/files-tenant-data/hooks.js +4 -0
- package/dist/folders/web/folder-manager.js +3 -2
- package/dist/form-draft/db/queries/cleanup.js +4 -4
- package/dist/form-draft/db/queries/draft-count.js +2 -2
- package/dist/form-draft/db/queries/owned-file-refs.js +2 -2
- package/dist/form-draft/handlers/discard.write.d.ts +1 -1
- package/dist/form-draft/handlers/save.write.d.ts +1 -1
- package/dist/form-draft/release-file-refs.js +3 -2
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +1 -1
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +6 -6
- package/dist/inbound-mail-foundation/handlers/scope-visibility.d.ts +1 -1
- package/dist/inbound-mail-foundation/oauth-access-token.js +8 -3
- package/dist/inbound-mail-foundation/oauth-state.js +7 -7
- package/dist/inbound-mail-foundation/types.js +4 -4
- package/dist/inbound-mail-foundation/watch-supervisor.js +24 -13
- package/dist/inbound-provider-imap/imap-client.js +4 -3
- package/dist/jobs/db/queries/stale-run-sweep.d.ts +1 -1
- package/dist/jobs/db/queries/stale-run-sweep.js +12 -5
- package/dist/jobs/feature.js +5 -3
- package/dist/jobs/handlers/list.query.js +3 -1
- package/dist/jobs/handlers/retry.write.d.ts +1 -1
- package/dist/jobs/handlers/stale-run-sweep.job.d.ts +1 -1
- package/dist/jobs/handlers/stale-run-sweep.job.js +2 -2
- package/dist/jobs/handlers/trigger.write.d.ts +1 -1
- package/dist/jobs/job-run-logger.js +32 -10
- package/dist/jobs/tenant-job-run-table.js +3 -2
- package/dist/ledger/entity.js +3 -1
- package/dist/ledger/recurring.js +1 -3
- package/dist/managed-pages/branding.d.ts +2 -0
- package/dist/managed-pages/branding.js +24 -2
- package/dist/managed-pages/feature.js +1 -0
- package/dist/managed-pages/handlers/set.write.d.ts +1 -1
- package/dist/managed-pages/i18n.js +1 -0
- package/dist/managed-pages/screens/branding-screen.js +8 -1
- package/dist/page-render/branding.d.ts +1 -0
- package/dist/page-render/branding.js +1 -0
- package/dist/page-render/markdown.js +1 -1
- package/dist/personal-access-tokens/feature.js +1 -1
- package/dist/personal-access-tokens/handlers/create.write.d.ts +1 -1
- package/dist/personal-access-tokens/handlers/list.query.js +2 -1
- package/dist/personal-access-tokens/handlers/revoke.write.d.ts +1 -1
- package/dist/personal-access-tokens/revoke-for-user.js +2 -1
- package/dist/renderer-foundation/api.d.ts +13 -13
- package/dist/renderer-foundation/api.js +1 -1
- package/dist/renderer-foundation/constants.js +2 -4
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/renderer-foundation/index.d.ts +2 -1
- package/dist/renderer-foundation/index.js +1 -0
- package/dist/renderer-foundation/types.d.ts +94 -32
- package/dist/renderer-pdf/feature.js +7 -1
- package/dist/renderer-pdf/render-table-pdf.d.ts +27 -33
- package/dist/renderer-pdf/render-table-pdf.js +95 -34
- package/dist/secrets/feature.js +4 -3
- package/dist/secrets/handlers/delete.write.d.ts +1 -1
- package/dist/secrets/handlers/set.write.d.ts +1 -1
- package/dist/secrets/secrets-context.js +15 -3
- package/dist/sessions/db/queries/cleanup.js +2 -2
- package/dist/sessions/feature.js +1 -1
- package/dist/sessions/handlers/list.query.js +2 -1
- package/dist/sessions/handlers/revoke-all-for-user.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke-all-others.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke.write.d.ts +1 -1
- package/dist/shared/attachment-file-name.d.ts +3 -0
- package/dist/shared/attachment-file-name.js +35 -0
- package/dist/shared/chunked-entity-migration.d.ts +1 -0
- package/dist/shared/chunked-entity-migration.js +1 -1
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +3 -0
- package/dist/shared/is-tenant-db.js +1 -1
- package/dist/shared/mail-template-body.d.ts +7 -0
- package/dist/shared/mail-template-body.js +27 -0
- package/dist/shared/sharp-input-limits.d.ts +6 -0
- package/dist/shared/sharp-input-limits.js +22 -0
- package/dist/shared/signup-handover.js +2 -2
- package/dist/subscription-stripe/plugin-methods.js +18 -8
- package/dist/subscription-stripe/verify-webhook.d.ts +1 -1
- package/dist/tags/handlers/assign-tag.write.js +3 -1
- package/dist/tags/web/tag-chip.js +2 -0
- package/dist/template-resolver/api.d.ts +30 -2
- package/dist/template-resolver/api.js +42 -6
- package/dist/template-resolver/compile-document-body.d.ts +12 -0
- package/dist/template-resolver/compile-document-body.js +205 -0
- package/dist/template-resolver/constants.d.ts +13 -4
- package/dist/template-resolver/constants.js +32 -10
- package/dist/template-resolver/document-sanitizer.d.ts +32 -0
- package/dist/template-resolver/document-sanitizer.js +201 -0
- package/dist/template-resolver/document-schema.d.ts +21 -0
- package/dist/template-resolver/document-schema.js +316 -0
- package/dist/template-resolver/feature.d.ts +20 -0
- package/dist/template-resolver/feature.js +53 -6
- package/dist/template-resolver/handlers/bundle-import.d.ts +20 -0
- package/dist/template-resolver/handlers/bundle-import.js +147 -0
- package/dist/template-resolver/handlers/collection-set.write.d.ts +1 -1
- package/dist/template-resolver/handlers/collection-set.write.js +25 -2
- package/dist/template-resolver/handlers/copy-locale.write.d.ts +19 -0
- package/dist/template-resolver/handlers/copy-locale.write.js +134 -0
- package/dist/template-resolver/handlers/diff-to-system.query.d.ts +22 -0
- package/dist/template-resolver/handlers/diff-to-system.query.js +30 -0
- package/dist/template-resolver/handlers/discard-draft.write.d.ts +13 -0
- package/dist/template-resolver/handlers/discard-draft.write.js +37 -0
- package/dist/template-resolver/handlers/export-bundle.query.d.ts +35 -0
- package/dist/template-resolver/handlers/export-bundle.query.js +118 -0
- package/dist/template-resolver/handlers/find-by-id.query.d.ts +2 -0
- package/dist/template-resolver/handlers/find-by-id.query.js +9 -6
- package/dist/template-resolver/handlers/import-bundle-system.write.d.ts +39 -0
- package/dist/template-resolver/handlers/import-bundle-system.write.js +36 -0
- package/dist/template-resolver/handlers/import-bundle.write.d.ts +40 -0
- package/dist/template-resolver/handlers/import-bundle.write.js +19 -0
- package/dist/template-resolver/handlers/layout-source.query.d.ts +31 -0
- package/dist/template-resolver/handlers/layout-source.query.js +87 -0
- package/dist/template-resolver/handlers/list.query.d.ts +4 -1
- package/dist/template-resolver/handlers/list.query.js +9 -8
- package/dist/template-resolver/handlers/override-diff.d.ts +20 -0
- package/dist/template-resolver/handlers/override-diff.js +41 -0
- package/dist/template-resolver/handlers/overview.query.d.ts +65 -0
- package/dist/template-resolver/handlers/overview.query.js +205 -0
- package/dist/template-resolver/handlers/preview.query.d.ts +12 -0
- package/dist/template-resolver/handlers/preview.query.js +24 -0
- package/dist/template-resolver/handlers/reset-to-system.write.d.ts +8 -0
- package/dist/template-resolver/handlers/reset-to-system.write.js +50 -0
- package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +8 -0
- package/dist/template-resolver/handlers/resource-link-pdf.write.js +32 -0
- package/dist/template-resolver/handlers/resource-remove.write.d.ts +9 -0
- package/dist/template-resolver/handlers/resource-remove.write.js +44 -0
- package/dist/template-resolver/handlers/resource-shared.d.ts +9 -0
- package/dist/template-resolver/handlers/resource-shared.js +14 -0
- package/dist/template-resolver/handlers/resource-upload.write.d.ts +13 -0
- package/dist/template-resolver/handlers/resource-upload.write.js +98 -0
- package/dist/template-resolver/handlers/send-test.write.d.ts +13 -0
- package/dist/template-resolver/handlers/send-test.write.js +108 -0
- package/dist/template-resolver/handlers/set.write.d.ts +5 -2
- package/dist/template-resolver/handlers/set.write.js +25 -3
- package/dist/template-resolver/handlers/shared.d.ts +9 -5
- package/dist/template-resolver/handlers/shared.js +6 -2
- package/dist/template-resolver/handlers/template-gates.d.ts +36 -0
- package/dist/template-resolver/handlers/template-gates.js +142 -0
- package/dist/template-resolver/handlers/template-write.d.ts +45 -0
- package/dist/template-resolver/handlers/template-write.js +141 -0
- package/dist/template-resolver/handlers/tenant-overrides.query.d.ts +49 -0
- package/dist/template-resolver/handlers/tenant-overrides.query.js +112 -0
- package/dist/template-resolver/handlers/toggle-status.write.d.ts +27 -2
- package/dist/template-resolver/handlers/toggle-status.write.js +47 -15
- package/dist/template-resolver/handlers/upsert-system.write.d.ts +5 -8
- package/dist/template-resolver/handlers/upsert-system.write.js +14 -59
- package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +5 -8
- package/dist/template-resolver/handlers/upsert-tenant.write.js +11 -62
- package/dist/template-resolver/handlers/usage.query.d.ts +17 -0
- package/dist/template-resolver/handlers/usage.query.js +24 -0
- package/dist/template-resolver/handlers/validate.query.d.ts +74 -0
- package/dist/template-resolver/handlers/validate.query.js +80 -0
- package/dist/template-resolver/index.d.ts +19 -1
- package/dist/template-resolver/index.js +17 -1
- package/dist/template-resolver/layout-appearance.d.ts +10 -0
- package/dist/template-resolver/layout-appearance.js +26 -0
- package/dist/template-resolver/layout-regions.d.ts +23 -0
- package/dist/template-resolver/layout-regions.js +125 -0
- package/dist/template-resolver/linked-resources.d.ts +17 -0
- package/dist/template-resolver/linked-resources.js +75 -0
- package/dist/template-resolver/pdf-constants.d.ts +7 -0
- package/dist/template-resolver/pdf-constants.js +8 -0
- package/dist/template-resolver/preview-display-html.d.ts +7 -0
- package/dist/template-resolver/preview-display-html.js +27 -0
- package/dist/template-resolver/print-document.d.ts +1 -0
- package/dist/template-resolver/print-document.js +55 -0
- package/dist/template-resolver/qualified-names.d.ts +34 -0
- package/dist/template-resolver/qualified-names.js +34 -0
- package/dist/template-resolver/record-mapping.d.ts +2 -0
- package/dist/template-resolver/record-mapping.js +21 -0
- package/dist/template-resolver/resource-image.d.ts +15 -0
- package/dist/template-resolver/resource-image.js +34 -0
- package/dist/template-resolver/seeding.d.ts +14 -1
- package/dist/template-resolver/seeding.js +125 -18
- package/dist/template-resolver/store-template-resource.d.ts +64 -0
- package/dist/template-resolver/store-template-resource.js +264 -0
- package/dist/template-resolver/table.d.ts +150 -8
- package/dist/template-resolver/table.js +20 -2
- package/dist/template-resolver/template-bundle.d.ts +36 -0
- package/dist/template-resolver/template-bundle.js +60 -0
- package/dist/template-resolver/template-diff.d.ts +7 -0
- package/dist/template-resolver/template-diff.js +68 -0
- package/dist/template-resolver/template-draft.d.ts +51 -0
- package/dist/template-resolver/template-draft.js +72 -0
- package/dist/template-resolver/template-meta.d.ts +85 -0
- package/dist/template-resolver/template-meta.js +145 -0
- package/dist/template-resolver/template-preview.d.ts +103 -0
- package/dist/template-resolver/template-preview.js +418 -0
- package/dist/template-resolver/template-resources.d.ts +19 -0
- package/dist/template-resolver/template-resources.js +73 -0
- package/dist/template-resolver/template-usage.d.ts +16 -0
- package/dist/template-resolver/template-usage.js +35 -0
- package/dist/template-resolver/template-validation.d.ts +22 -0
- package/dist/template-resolver/template-validation.js +173 -0
- package/dist/template-resolver/testing.js +5 -5
- package/dist/template-resolver/user-content-table.d.ts +14 -8
- package/dist/template-resolver/web/client-plugin.d.ts +1 -0
- package/dist/template-resolver/web/client-plugin.js +12 -7
- package/dist/template-resolver/web/document-editor-extensions.d.ts +18 -0
- package/dist/template-resolver/web/document-editor-extensions.js +145 -0
- package/dist/template-resolver/web/document-editor.d.ts +4 -0
- package/dist/template-resolver/web/document-editor.js +17 -0
- package/dist/template-resolver/web/document-tiptap-editor.d.ts +3 -0
- package/dist/template-resolver/web/document-tiptap-editor.js +492 -0
- package/dist/template-resolver/web/document-toolbar-blocks.d.ts +41 -0
- package/dist/template-resolver/web/document-toolbar-blocks.js +19 -0
- package/dist/template-resolver/web/editor-handle.d.ts +3 -0
- package/dist/template-resolver/web/editor-handle.js +24 -0
- package/dist/template-resolver/web/i18n.js +91 -0
- package/dist/template-resolver/web/index.d.ts +5 -0
- package/dist/template-resolver/web/index.js +5 -0
- package/dist/template-resolver/web/placeholder-line-editor-lazy.d.ts +4 -0
- package/dist/template-resolver/web/placeholder-line-editor-lazy.js +16 -0
- package/dist/template-resolver/web/placeholder-line-editor.d.ts +17 -0
- package/dist/template-resolver/web/placeholder-line-editor.js +94 -0
- package/dist/template-resolver/web/placeholder-text.d.ts +4 -0
- package/dist/template-resolver/web/placeholder-text.js +34 -0
- package/dist/template-resolver/web/use-stable-by-key.d.ts +1 -0
- package/dist/template-resolver/web/use-stable-by-key.js +13 -0
- package/dist/tenant/handlers/add-member.write.d.ts +1 -1
- package/dist/tenant/handlers/cancel-invitation.write.d.ts +1 -1
- package/dist/tenant/handlers/create.write.d.ts +1 -1
- package/dist/tenant/handlers/remove-member.write.d.ts +1 -1
- package/dist/tenant/handlers/team-list.query.js +3 -2
- package/dist/tenant/handlers/toggle-enabled.write.d.ts +2 -2
- package/dist/tenant/handlers/update-member-roles.write.d.ts +1 -1
- package/dist/tenant/handlers/update.write.d.ts +1 -1
- package/dist/tenant/seeding.js +31 -6
- package/dist/tenant-handover/handlers/claim.write.d.ts +1 -1
- package/dist/tenant-lifecycle/handlers/cancel-destruction.write.d.ts +2 -2
- package/dist/tenant-lifecycle/handlers/cancel-destruction.write.js +2 -1
- package/dist/tenant-lifecycle/handlers/request-destruction.write.d.ts +1 -1
- package/dist/tier-engine/feature.js +9 -3
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +1 -1
- package/dist/user/db/queries/stream-tenant-backfill.js +4 -4
- package/dist/user/handlers/create.write.d.ts +1 -1
- package/dist/user/handlers/detail.query.js +2 -1
- package/dist/user/handlers/update.write.d.ts +1 -1
- package/dist/user/resolve-display-names.js +5 -9
- package/dist/user/seeding.js +20 -1
- package/dist/user-data-rights/db/queries/forget-cleanup.d.ts +2 -2
- package/dist/user-data-rights/email-templates.d.ts +1 -29
- package/dist/user-data-rights/email-templates.js +5 -106
- package/dist/user-data-rights/feature.js +53 -35
- package/dist/user-data-rights/handlers/cancel-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +2 -1
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/lift-restriction.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion.write.js +5 -7
- package/dist/user-data-rights/handlers/request-export.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/restrict-account.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.d.ts +1 -1
- package/dist/user-data-rights/lib/default-mailers.d.ts +15 -7
- package/dist/user-data-rights/lib/default-mailers.js +100 -48
- package/dist/user-data-rights/lib/update-user-lifecycle.js +1 -1
- package/dist/user-data-rights/mail-notifications.d.ts +13 -0
- package/dist/user-data-rights/mail-notifications.js +118 -0
- package/dist/user-data-rights/web/privacy-center-screen.js +2 -1
- package/dist/user-profile/handlers/change-email.write.d.ts +1 -1
- package/dist/user-profile/web/profile-screen.js +2 -1
- package/dist/waitlist/feature.js +10 -0
- package/dist/waitlist/handlers/invite.write.d.ts +1 -1
- package/dist/waitlist/handlers/reject.write.d.ts +1 -1
- package/dist/waitlist/handlers/submit.write.d.ts +1 -1
- package/dist/waitlist/handlers/submit.write.js +3 -4
- package/dist/waitlist/mail.d.ts +19 -6
- package/dist/waitlist/mail.js +50 -14
- package/dist/waitlist/options.js +1 -1
- package/dist/workflow-runner/event-trigger.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +7 -2
- package/package.json +37 -17
- package/src/admin-shell/changes.json +6 -0
- package/src/audit/changes.json +6 -0
- package/src/auth-email-password/changes.json +51 -0
- package/src/billing-foundation/changes.json +43 -0
- package/src/cap-counter/changes.json +6 -0
- package/src/channel-email/changes.json +19 -0
- package/src/config/changes.json +6 -0
- package/src/crypto-shredding/changes.json +6 -0
- package/src/custom-fields/changes.json +6 -0
- package/src/data-retention/changes.json +6 -0
- package/src/delivery/changes.json +66 -0
- package/src/file-foundation/changes.json +6 -0
- package/src/files-tenant-data/changes.json +6 -0
- package/src/inbound-mail-foundation/changes.json +6 -0
- package/src/jobs/changes.json +19 -0
- package/src/ledger/changes.json +7 -0
- package/src/managed-pages/changes.json +6 -0
- package/src/renderer-foundation/changes.json +39 -0
- package/src/renderer-pdf/changes.json +12 -0
- package/src/secrets/changes.json +6 -0
- package/src/shared/changes.json +6 -0
- package/src/subscription-stripe/changes.json +6 -0
- package/src/template-resolver/changes.json +186 -0
- package/src/tier-engine/changes.json +6 -0
- package/src/user/changes.json +6 -0
- package/src/user-data-rights/changes.json +13 -0
- package/src/user-profile/changes.json +1 -1
- package/src/waitlist/changes.json +7 -0
- package/src/workflow-runner/changes.json +6 -0
- package/dist/renderer-simple/feature.d.ts +0 -10
- package/dist/renderer-simple/feature.js +0 -42
- package/dist/renderer-simple/index.d.ts +0 -3
- package/dist/renderer-simple/index.js +0 -2
- package/dist/renderer-simple/mail-blocks.d.ts +0 -21
- package/dist/renderer-simple/mail-blocks.js +0 -107
- package/dist/renderer-simple/resolve-variables.d.ts +0 -7
- package/dist/renderer-simple/resolve-variables.js +0 -47
- package/dist/renderer-simple/simple-renderer.d.ts +0 -24
- package/dist/renderer-simple/simple-renderer.js +0 -200
- package/src/renderer-simple/changes.json +0 -27
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { withParsedDocument } from "./document-sanitizer.js";
|
|
3
|
+
import { isDocumentPlaceholderHref, isDocumentReferenceName } from "./document-schema.js";
|
|
4
|
+
export const SYSTEM_PLACEHOLDERS = new Set([
|
|
5
|
+
"tenantName",
|
|
6
|
+
"signature",
|
|
7
|
+
"imprint",
|
|
8
|
+
"unsubscribeUrl",
|
|
9
|
+
]);
|
|
10
|
+
const PAGE_PLACEHOLDERS = ["page", "pages"];
|
|
11
|
+
const PAGED_KINDS = new Set(["document-pdf", "pdf-layout"]);
|
|
12
|
+
export function systemPlaceholdersFor(kind) {
|
|
13
|
+
return PAGED_KINDS.has(kind)
|
|
14
|
+
? new Set([...SYSTEM_PLACEHOLDERS, ...PAGE_PLACEHOLDERS])
|
|
15
|
+
: SYSTEM_PLACEHOLDERS;
|
|
16
|
+
}
|
|
17
|
+
const BASE_RESOURCE_KEYS = ["logo"];
|
|
18
|
+
// Mirrors TemplateVariableDef: a stored or draft schema keeps its label and example, which the
|
|
19
|
+
// preview uses as sample values.
|
|
20
|
+
const variableCommon = {
|
|
21
|
+
label: z.string().optional(),
|
|
22
|
+
required: z.boolean().optional(),
|
|
23
|
+
};
|
|
24
|
+
const textLikeExample = z.string().optional();
|
|
25
|
+
const scalarVariableSchema = z.discriminatedUnion("type", [
|
|
26
|
+
z.object({ ...variableCommon, type: z.literal("text"), example: textLikeExample }),
|
|
27
|
+
z.object({ ...variableCommon, type: z.literal("link"), example: textLikeExample }),
|
|
28
|
+
z.object({ ...variableCommon, type: z.literal("richText"), example: textLikeExample }),
|
|
29
|
+
z.object({
|
|
30
|
+
...variableCommon,
|
|
31
|
+
type: z.literal("money"),
|
|
32
|
+
example: z
|
|
33
|
+
.union([z.number(), z.object({ amount: z.number(), currency: z.string() })])
|
|
34
|
+
.optional(),
|
|
35
|
+
}),
|
|
36
|
+
z.object({ ...variableCommon, type: z.literal("date"), example: textLikeExample }),
|
|
37
|
+
]);
|
|
38
|
+
const variableDefSchema = z.union([
|
|
39
|
+
scalarVariableSchema,
|
|
40
|
+
z.object({
|
|
41
|
+
...variableCommon,
|
|
42
|
+
type: z.literal("list"),
|
|
43
|
+
item: z.record(z.string(), scalarVariableSchema),
|
|
44
|
+
example: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
45
|
+
}),
|
|
46
|
+
]);
|
|
47
|
+
// A stored variableSchema value is either a bare string (legacy "this is a text
|
|
48
|
+
// variable") or a TemplateVariableDef object; anything else is not declared and
|
|
49
|
+
// therefore shows up as an unknown placeholder instead of being guessed at.
|
|
50
|
+
function toVariableDef(raw) {
|
|
51
|
+
if (typeof raw === "string")
|
|
52
|
+
return { type: "text" };
|
|
53
|
+
const parsed = variableDefSchema.safeParse(raw);
|
|
54
|
+
return parsed.success ? parsed.data : null;
|
|
55
|
+
}
|
|
56
|
+
export function resolveTemplateVariables(registry, slug, variableSchema) {
|
|
57
|
+
const declared = registry.getAllNotifications().get(slug)?.variables;
|
|
58
|
+
return declared ?? variablesFromSchema(variableSchema);
|
|
59
|
+
}
|
|
60
|
+
export function variablesFromSchema(variableSchema) {
|
|
61
|
+
const variables = {};
|
|
62
|
+
for (const [name, raw] of Object.entries(variableSchema)) {
|
|
63
|
+
const def = toVariableDef(raw);
|
|
64
|
+
if (def !== null)
|
|
65
|
+
variables[name] = def;
|
|
66
|
+
}
|
|
67
|
+
return variables;
|
|
68
|
+
}
|
|
69
|
+
function rootName(name) {
|
|
70
|
+
return name.split(".")[0] ?? name;
|
|
71
|
+
}
|
|
72
|
+
function listItemFields(variables, listName) {
|
|
73
|
+
const def = listName !== null && Object.hasOwn(variables, listName) ? variables[listName] : undefined;
|
|
74
|
+
return def?.type === "list" ? def.item : {};
|
|
75
|
+
}
|
|
76
|
+
function isKnownName(name, scope, itemFields) {
|
|
77
|
+
const { variables } = scope;
|
|
78
|
+
const root = rootName(name);
|
|
79
|
+
if (Object.hasOwn(itemFields, name) || Object.hasOwn(itemFields, root)) {
|
|
80
|
+
return { known: true, used: "" };
|
|
81
|
+
}
|
|
82
|
+
if (scope.systemPlaceholders.has(root))
|
|
83
|
+
return { known: true, used: "" };
|
|
84
|
+
if (Object.hasOwn(variables, name))
|
|
85
|
+
return { known: true, used: name };
|
|
86
|
+
if (Object.hasOwn(variables, root))
|
|
87
|
+
return { known: true, used: root };
|
|
88
|
+
return { known: false, used: "" };
|
|
89
|
+
}
|
|
90
|
+
function recordName(name, itemFields, scope) {
|
|
91
|
+
const resolution = isKnownName(name, scope, itemFields);
|
|
92
|
+
if (!resolution.known)
|
|
93
|
+
scope.unknown.add(name);
|
|
94
|
+
else if (resolution.used !== "")
|
|
95
|
+
scope.used.add(resolution.used);
|
|
96
|
+
}
|
|
97
|
+
function enclosingEachName(element) {
|
|
98
|
+
return element.closest("tr[data-each]")?.getAttribute("data-each") ?? null;
|
|
99
|
+
}
|
|
100
|
+
function scanBodyPlaceholders(body, scope) {
|
|
101
|
+
withParsedDocument(body, (root) => {
|
|
102
|
+
for (const element of Array.from(root.querySelectorAll("tr[data-each]"))) {
|
|
103
|
+
const listName = element.getAttribute("data-each") ?? "";
|
|
104
|
+
const def = Object.hasOwn(scope.variables, listName) ? scope.variables[listName] : undefined;
|
|
105
|
+
if (def?.type === "list")
|
|
106
|
+
scope.used.add(listName);
|
|
107
|
+
else
|
|
108
|
+
scope.unknown.add(listName);
|
|
109
|
+
}
|
|
110
|
+
for (const element of Array.from(root.querySelectorAll("span[data-variable], a[href], img[data-resource]"))) {
|
|
111
|
+
const itemFields = listItemFields(scope.variables, enclosingEachName(element));
|
|
112
|
+
const tag = element.tagName.toLowerCase();
|
|
113
|
+
if (tag === "span") {
|
|
114
|
+
recordName(element.getAttribute("data-variable") ?? "", itemFields, scope);
|
|
115
|
+
}
|
|
116
|
+
else if (tag === "a") {
|
|
117
|
+
const href = element.getAttribute("href") ?? "";
|
|
118
|
+
if (isDocumentPlaceholderHref(href))
|
|
119
|
+
recordName(href.slice(2, -2), itemFields, scope);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
const key = element.getAttribute("data-resource") ?? "";
|
|
123
|
+
if (!scope.resourceKeys.has(key))
|
|
124
|
+
scope.unknownResources.add(key);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const HANDLEBARS_EXPRESSION = /\{\{([^{}]*)\}\}/g;
|
|
130
|
+
// Meta text supports only plain `{{name}}` / `{{name.field}}`; every other
|
|
131
|
+
// Handlebars construct is reported as unknown so it can never reach the compiler.
|
|
132
|
+
function scanMetaPlaceholders(text, scope) {
|
|
133
|
+
const leftover = text.replace(HANDLEBARS_EXPRESSION, (_match, inner) => {
|
|
134
|
+
const name = inner.trim();
|
|
135
|
+
if (isDocumentReferenceName(name))
|
|
136
|
+
recordName(name, {}, scope);
|
|
137
|
+
else
|
|
138
|
+
scope.unknown.add(`{{${inner}}}`);
|
|
139
|
+
return "";
|
|
140
|
+
});
|
|
141
|
+
if (/[{}]/.test(leftover))
|
|
142
|
+
scope.unknown.add("{");
|
|
143
|
+
}
|
|
144
|
+
function metaTexts(meta) {
|
|
145
|
+
if (meta === null || !("subject" in meta))
|
|
146
|
+
return [];
|
|
147
|
+
return [meta.subject, ...(meta.previewText === undefined ? [] : [meta.previewText])];
|
|
148
|
+
}
|
|
149
|
+
export function validateTemplatePlaceholders(input) {
|
|
150
|
+
const scope = {
|
|
151
|
+
variables: input.variables,
|
|
152
|
+
systemPlaceholders: systemPlaceholdersFor(input.kind),
|
|
153
|
+
resourceKeys: new Set([...BASE_RESOURCE_KEYS, ...(input.resourceKeys ?? [])]),
|
|
154
|
+
used: new Set(),
|
|
155
|
+
unknown: new Set(),
|
|
156
|
+
unknownResources: new Set(),
|
|
157
|
+
};
|
|
158
|
+
scanBodyPlaceholders(input.body, scope);
|
|
159
|
+
for (const text of metaTexts(input.meta))
|
|
160
|
+
scanMetaPlaceholders(text, scope);
|
|
161
|
+
const missingRequired = Object.entries(input.variables)
|
|
162
|
+
.filter(([name, def]) => def.required === true && !scope.used.has(name))
|
|
163
|
+
.map(([name]) => name);
|
|
164
|
+
return {
|
|
165
|
+
unknown: [...scope.unknown].sort(),
|
|
166
|
+
missingRequired: missingRequired.sort(),
|
|
167
|
+
used: [...scope.used].sort(),
|
|
168
|
+
unknownResources: [...scope.unknownResources].sort(),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export function hasPlaceholderProblems(validation) {
|
|
172
|
+
return validation.unknown.length > 0 || validation.missingRequired.length > 0;
|
|
173
|
+
}
|
|
@@ -37,7 +37,7 @@ export async function assertConsumerHandlesNotFound(consumer, opts) {
|
|
|
37
37
|
await consumer.resolve({
|
|
38
38
|
tenantId,
|
|
39
39
|
slug,
|
|
40
|
-
kind: "mail
|
|
40
|
+
kind: "mail",
|
|
41
41
|
locale: "de",
|
|
42
42
|
});
|
|
43
43
|
}
|
|
@@ -60,7 +60,7 @@ export async function assertConsumerRespectsLocaleFallback(consumer, opts) {
|
|
|
60
60
|
await seedTemplate(db, {
|
|
61
61
|
tenantId: SYSTEM_TENANT_ID,
|
|
62
62
|
slug,
|
|
63
|
-
kind: "
|
|
63
|
+
kind: "document-pdf",
|
|
64
64
|
locale: FALLBACK_LOCALE,
|
|
65
65
|
scope: "system",
|
|
66
66
|
content: "conformance-fallback-content",
|
|
@@ -68,7 +68,7 @@ export async function assertConsumerRespectsLocaleFallback(consumer, opts) {
|
|
|
68
68
|
const result = await consumer.resolve({
|
|
69
69
|
tenantId,
|
|
70
70
|
slug,
|
|
71
|
-
kind: "
|
|
71
|
+
kind: "document-pdf",
|
|
72
72
|
locale: "tr",
|
|
73
73
|
});
|
|
74
74
|
if (result.locale !== FALLBACK_LOCALE) {
|
|
@@ -89,7 +89,7 @@ export async function assertConsumerHandlesMissingResourceKeys(consumer, opts) {
|
|
|
89
89
|
await seedTemplate(db, {
|
|
90
90
|
tenantId: SYSTEM_TENANT_ID,
|
|
91
91
|
slug,
|
|
92
|
-
kind: "mail
|
|
92
|
+
kind: "mail",
|
|
93
93
|
locale: "de",
|
|
94
94
|
scope: "system",
|
|
95
95
|
linkedResources: { logo: "file_missing" },
|
|
@@ -97,7 +97,7 @@ export async function assertConsumerHandlesMissingResourceKeys(consumer, opts) {
|
|
|
97
97
|
const template = await consumer.resolve({
|
|
98
98
|
tenantId,
|
|
99
99
|
slug,
|
|
100
|
-
kind: "mail
|
|
100
|
+
kind: "mail",
|
|
101
101
|
locale: "de",
|
|
102
102
|
});
|
|
103
103
|
try {
|
|
@@ -49,26 +49,29 @@ export declare const userContentEntryEntity: import("@cosmicdrift/kumiko-types/f
|
|
|
49
49
|
kind: {
|
|
50
50
|
readonly type: "select";
|
|
51
51
|
readonly description?: string;
|
|
52
|
-
readonly options: readonly ["
|
|
52
|
+
readonly options: readonly ["mail", "document-pdf", "image-snapshot", "notification", "text-block", "snippet", "ai-prompt", "mail-layout", "pdf-layout"];
|
|
53
53
|
readonly required?: boolean;
|
|
54
54
|
readonly sortable?: boolean;
|
|
55
55
|
readonly filterable?: boolean;
|
|
56
56
|
readonly sensitive?: boolean;
|
|
57
|
-
readonly default?: "ai-prompt" | "document-pdf" | "image-snapshot" | "mail-
|
|
57
|
+
readonly default?: "ai-prompt" | "document-pdf" | "image-snapshot" | "mail" | "mail-layout" | "notification" | "pdf-layout" | "snippet" | "text-block" | undefined;
|
|
58
58
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
59
59
|
readonly display?: "radio" | "dropdown";
|
|
60
60
|
readonly optionTones?: {
|
|
61
61
|
readonly "ai-prompt"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
62
62
|
readonly "document-pdf"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
63
63
|
readonly "image-snapshot"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
64
|
-
readonly
|
|
64
|
+
readonly mail?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
65
|
+
readonly "mail-layout"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
65
66
|
readonly notification?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
67
|
+
readonly "pdf-layout"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
68
|
+
readonly snippet?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
66
69
|
readonly "text-block"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
67
70
|
} | undefined;
|
|
68
71
|
readonly optionsQuery?: string;
|
|
69
72
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
70
73
|
readonly optionsAvailabilityQuery?: string;
|
|
71
|
-
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail-
|
|
74
|
+
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail" | "mail-layout" | "notification" | "pdf-layout" | "snippet" | "text-block">[] | undefined;
|
|
72
75
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
73
76
|
required: true;
|
|
74
77
|
};
|
|
@@ -232,26 +235,29 @@ export declare const userContentEntriesTable: import("@cosmicdrift/kumiko-framew
|
|
|
232
235
|
kind: {
|
|
233
236
|
readonly type: "select";
|
|
234
237
|
readonly description?: string;
|
|
235
|
-
readonly options: readonly ["
|
|
238
|
+
readonly options: readonly ["mail", "document-pdf", "image-snapshot", "notification", "text-block", "snippet", "ai-prompt", "mail-layout", "pdf-layout"];
|
|
236
239
|
readonly required?: boolean;
|
|
237
240
|
readonly sortable?: boolean;
|
|
238
241
|
readonly filterable?: boolean;
|
|
239
242
|
readonly sensitive?: boolean;
|
|
240
|
-
readonly default?: "ai-prompt" | "document-pdf" | "image-snapshot" | "mail-
|
|
243
|
+
readonly default?: "ai-prompt" | "document-pdf" | "image-snapshot" | "mail" | "mail-layout" | "notification" | "pdf-layout" | "snippet" | "text-block" | undefined;
|
|
241
244
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
242
245
|
readonly display?: "radio" | "dropdown";
|
|
243
246
|
readonly optionTones?: {
|
|
244
247
|
readonly "ai-prompt"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
245
248
|
readonly "document-pdf"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
246
249
|
readonly "image-snapshot"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
247
|
-
readonly
|
|
250
|
+
readonly mail?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
251
|
+
readonly "mail-layout"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
248
252
|
readonly notification?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
253
|
+
readonly "pdf-layout"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
254
|
+
readonly snippet?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
249
255
|
readonly "text-block"?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
250
256
|
} | undefined;
|
|
251
257
|
readonly optionsQuery?: string;
|
|
252
258
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
253
259
|
readonly optionsAvailabilityQuery?: string;
|
|
254
|
-
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail-
|
|
260
|
+
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail" | "mail-layout" | "notification" | "pdf-layout" | "snippet" | "text-block">[] | undefined;
|
|
255
261
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
256
262
|
required: true;
|
|
257
263
|
};
|
|
@@ -9,6 +9,7 @@ export type BlockSummary = {
|
|
|
9
9
|
readonly modifiedAt: string | null;
|
|
10
10
|
};
|
|
11
11
|
export declare function groupBlocksByFolder(blocks: readonly BlockSummary[], tenantIdOverride?: string, collectionId?: string): readonly TreeNode[];
|
|
12
|
+
export declare function resolveWriteContentFormat(collectionContentFormat: string | undefined, loadedContentFormat: string | undefined): string | undefined;
|
|
12
13
|
export declare function textBlocksClient(opts?: {
|
|
13
14
|
readonly navId?: string;
|
|
14
15
|
readonly tenantId?: string;
|
|
@@ -16,6 +16,8 @@ import { ContentPreview, useAppFeatures, useContentEditor, useDispatcher, usePri
|
|
|
16
16
|
import { PlainContentEditor, RichContentEditor, } from "@cosmicdrift/kumiko-renderer-web";
|
|
17
17
|
import { useEffect, useId, useState } from "react";
|
|
18
18
|
import { collectionHandlerName, collectionQueryName, TemplateResolverHandlers, TemplateResolverQueries, } from "../qualified-names.js";
|
|
19
|
+
import { DocumentBlocksContext, DocumentContentEditor } from "./document-editor.js";
|
|
20
|
+
import { documentBlocksForKind } from "./document-toolbar-blocks.js";
|
|
19
21
|
import { defaultTranslations } from "./i18n.js";
|
|
20
22
|
function newFolderNode() {
|
|
21
23
|
return { leaves: [], subFolders: new Map() };
|
|
@@ -163,19 +165,20 @@ function findContentFormat(features, collectionId) {
|
|
|
163
165
|
function findVariableExamples(features, collectionId) {
|
|
164
166
|
return findCollection(features, collectionId)?.variableSchema ?? {};
|
|
165
167
|
}
|
|
166
|
-
// The collection's declared contentFormat ("plain" | "rich" | "markdown"
|
|
167
|
-
// see ContentCollectionDefinition.contentFormat) uses a different vocabulary
|
|
168
|
+
// The collection's declared contentFormat ("plain" | "rich" | "markdown" |
|
|
169
|
+
// "document", see ContentCollectionDefinition.contentFormat) uses a different vocabulary
|
|
168
170
|
// than the stored entry's contentFormat ("plain" | "html" | "markdown" |
|
|
169
|
-
// "mjml", see CONTENT_FORMATS) — "rich" always
|
|
171
|
+
// "mjml", see CONTENT_FORMATS) — "rich" and "document" always store HTML. Without this,
|
|
170
172
|
// handleSave omitting contentFormat let the write schema's
|
|
171
173
|
// contentFormatSchema.default("markdown") silently stamp every save as
|
|
172
174
|
// markdown, clobbering e.g. a "plain" entry. Undefined (no collection, or
|
|
173
175
|
// the collection didn't declare a format) keeps whatever was already saved
|
|
174
176
|
// instead of guessing.
|
|
175
|
-
|
|
177
|
+
// Exported for the unit test — resolveWriteContentFormat is a pure function.
|
|
178
|
+
export function resolveWriteContentFormat(collectionContentFormat, loadedContentFormat) {
|
|
176
179
|
if (collectionContentFormat === "plain")
|
|
177
180
|
return "plain";
|
|
178
|
-
if (collectionContentFormat === "rich")
|
|
181
|
+
if (collectionContentFormat === "rich" || collectionContentFormat === "document")
|
|
179
182
|
return "html";
|
|
180
183
|
if (collectionContentFormat === "markdown")
|
|
181
184
|
return "markdown";
|
|
@@ -203,6 +206,7 @@ function TextBlockEditor({ target, }) {
|
|
|
203
206
|
const contentFormat = findContentFormat(features, collectionId);
|
|
204
207
|
const variableExamples = findVariableExamples(features, collectionId);
|
|
205
208
|
const variables = Object.keys(variableExamples);
|
|
209
|
+
const documentBlocks = documentBlocksForKind(findCollection(features, collectionId)?.kind);
|
|
206
210
|
const ContentEditor = useContentEditor(contentFormat);
|
|
207
211
|
const canWrite = user?.roles.includes("TenantAdmin") === true || user?.roles.includes("SystemAdmin") === true;
|
|
208
212
|
// Same split as the tree provider: a node without a collection reads through
|
|
@@ -266,7 +270,7 @@ function TextBlockEditor({ target, }) {
|
|
|
266
270
|
void handleSave();
|
|
267
271
|
};
|
|
268
272
|
const disabled = submitting || loading || !canWrite;
|
|
269
|
-
return (_jsxs(Form, { onSubmit: onSubmit, testId: "text-block-editor", title: title || slug || "—", subtitle: locale !== "" ? `${slug} · (${locale})` : slug, actions: canWrite ? (_jsx(Button, { type: "submit", loading: submitting, disabled: disabled, children: submitting ? t("template-resolver.editor.saving") : t("template-resolver.editor.save") })) : undefined, children: [loading && _jsx(Banner, { variant: "loading", children: t("template-resolver.editor.loading") }), loadError !== null && (_jsxs(Banner, { variant: "error", children: [t("template-resolver.editor.loadFailed"), ": ", loadError.code] })), !canWrite && !loading && (_jsx(Banner, { variant: "info", children: t("template-resolver.editor.readOnly") })), _jsx(Field, { id: "text-block-title", label: t("template-resolver.editor.titleLabel"), required: true, children: _jsx(Input, { kind: "text", id: "text-block-title", name: "text-block-title", value: title, onChange: setTitle, disabled: disabled, required: true }) }), _jsx(Field, { id: contentEditorId, label: t("template-resolver.editor.contentLabel"), labelAppendix: _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setPreviewing((p) => !p), children: previewing ? t("kumiko.contentEditor.editMode") : t("kumiko.contentEditor.preview") }), children: previewing ? (_jsx(ContentPreview, { content: content, variables: variableExamples, contentFormat: contentFormat })) : (_jsx(ContentEditor, { id: contentEditorId, value: content, onChange: setContent, variables: variables, readOnly: disabled })) }), saveError !== null && _jsx(Banner, { variant: "error", children: saveError }), savedMsg !== null && _jsx(Banner, { variant: "info", children: savedMsg })] }));
|
|
273
|
+
return (_jsxs(Form, { onSubmit: onSubmit, testId: "text-block-editor", title: title || slug || "—", subtitle: locale !== "" ? `${slug} · (${locale})` : slug, actions: canWrite ? (_jsx(Button, { type: "submit", loading: submitting, disabled: disabled, children: submitting ? t("template-resolver.editor.saving") : t("template-resolver.editor.save") })) : undefined, children: [loading && _jsx(Banner, { variant: "loading", children: t("template-resolver.editor.loading") }), loadError !== null && (_jsxs(Banner, { variant: "error", children: [t("template-resolver.editor.loadFailed"), ": ", loadError.code] })), !canWrite && !loading && (_jsx(Banner, { variant: "info", children: t("template-resolver.editor.readOnly") })), _jsx(Field, { id: "text-block-title", label: t("template-resolver.editor.titleLabel"), required: true, children: _jsx(Input, { kind: "text", id: "text-block-title", name: "text-block-title", value: title, onChange: setTitle, disabled: disabled, required: true }) }), _jsx(Field, { id: contentEditorId, label: t("template-resolver.editor.contentLabel"), labelAppendix: _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setPreviewing((p) => !p), children: previewing ? t("kumiko.contentEditor.editMode") : t("kumiko.contentEditor.preview") }), children: previewing ? (_jsx(ContentPreview, { content: content, variables: variableExamples, contentFormat: contentFormat })) : (_jsx(DocumentBlocksContext.Provider, { value: documentBlocks, children: _jsx(ContentEditor, { id: contentEditorId, value: content, onChange: setContent, variables: variables, readOnly: disabled }) })) }), saveError !== null && _jsx(Banner, { variant: "error", children: saveError }), savedMsg !== null && _jsx(Banner, { variant: "info", children: savedMsg })] }));
|
|
270
274
|
}
|
|
271
275
|
// `navId` = the QN of the r.nav({ provider: true }) node the app registers for
|
|
272
276
|
// the content tree (e.g. "publicstatus:nav:content"). The app owns the node's
|
|
@@ -301,12 +305,13 @@ export function textBlocksClient(opts) {
|
|
|
301
305
|
resolvers: {
|
|
302
306
|
"template-resolver:edit": TextBlockEditor,
|
|
303
307
|
},
|
|
304
|
-
// The default for every "plain" collection (ai-prompt, mail
|
|
308
|
+
// The default for every "plain" collection (ai-prompt, mail without
|
|
305
309
|
// an explicit rich override) — an app-registered "plain" editor on
|
|
306
310
|
// another clientFeature still wins, last-wins same as columnRenderers.
|
|
307
311
|
contentEditors: {
|
|
308
312
|
plain: PlainContentEditor,
|
|
309
313
|
rich: RichContentEditor,
|
|
314
|
+
document: DocumentContentEditor,
|
|
310
315
|
// ponytail: same textarea+chips as "plain" — markdown is stored as
|
|
311
316
|
// text either way. Shares PlainContentEditor's fixed-DOM-id ceiling
|
|
312
317
|
// (see its own file comment); swap for a live-preview widget or a
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Extensions, NodeViewRenderer } from "@tiptap/core";
|
|
2
|
+
import type { DocumentResourcePreview } from "./document-toolbar-blocks.js";
|
|
3
|
+
export declare const DOCUMENT_BLOCK_ATTRIBUTE = "data-document-block";
|
|
4
|
+
export type DocumentEditorLabels = {
|
|
5
|
+
readonly placeholder: string;
|
|
6
|
+
readonly image: string;
|
|
7
|
+
readonly pageBreak: string;
|
|
8
|
+
readonly button?: string;
|
|
9
|
+
/** Canvas block label of an image, e.g. "Image · inline". */
|
|
10
|
+
readonly imageBlock?: string;
|
|
11
|
+
readonly variableLabels?: Readonly<Record<string, string>>;
|
|
12
|
+
readonly systemVariables?: readonly string[];
|
|
13
|
+
readonly resourcePreviews?: Readonly<Record<string, DocumentResourcePreview>>;
|
|
14
|
+
/** Canvas chrome labels every block with its type. */
|
|
15
|
+
readonly blockLabels?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare function createVariableView(variableLabels: Readonly<Record<string, string>>, systemVariables: readonly string[], labelOnly?: boolean): NodeViewRenderer;
|
|
18
|
+
export declare function createDocumentEditorExtensions(labels: DocumentEditorLabels): Extensions;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { ListKeymap } from "@tiptap/extension-list";
|
|
2
|
+
import { Dropcursor, Gapcursor, Placeholder, UndoRedo } from "@tiptap/extensions";
|
|
3
|
+
import { DocumentButton, DocumentPageBreak, DocumentResource, DocumentVariable, documentExtensions, } from "../document-schema.js";
|
|
4
|
+
const DOCUMENT_RESOURCE_SIZE_TOKEN = "{size}";
|
|
5
|
+
export const DOCUMENT_BLOCK_ATTRIBUTE = "data-document-block";
|
|
6
|
+
function createElementWithClass(tag, className, text) {
|
|
7
|
+
const element = document.createElement(tag);
|
|
8
|
+
element.className = className;
|
|
9
|
+
if (text !== undefined)
|
|
10
|
+
element.textContent = text;
|
|
11
|
+
return element;
|
|
12
|
+
}
|
|
13
|
+
const CHIP_CLASS = "mx-0.5 inline-flex items-center gap-1 rounded border px-1.5 py-0.5 text-xs";
|
|
14
|
+
const USER_CHIP_CLASS = `${CHIP_CLASS} border-primary/30 bg-primary/10 text-primary`;
|
|
15
|
+
const SYSTEM_CHIP_CLASS = `${CHIP_CLASS} border-input bg-muted text-muted-foreground`;
|
|
16
|
+
// A chip inside a repeat row names an item field; its label is registered as `list.field`.
|
|
17
|
+
function repeatRowListAt(doc, position) {
|
|
18
|
+
if (position === undefined)
|
|
19
|
+
return null;
|
|
20
|
+
const resolved = doc.resolve(position);
|
|
21
|
+
for (let depth = resolved.depth; depth > 0; depth--) {
|
|
22
|
+
const each = resolved.node(depth).attrs["each"];
|
|
23
|
+
if (typeof each === "string" && each !== "")
|
|
24
|
+
return each;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
// The chip is display only: the stored node carries just the name, so a
|
|
29
|
+
// label never reaches the document.
|
|
30
|
+
export function createVariableView(variableLabels, systemVariables, labelOnly = false) {
|
|
31
|
+
return ({ node, editor, getPos }) => {
|
|
32
|
+
const name = String(node.attrs["name"]);
|
|
33
|
+
const listName = repeatRowListAt(editor.state.doc, getPos());
|
|
34
|
+
const labelKey = listName === null ? name : `${listName}.${name}`;
|
|
35
|
+
const label = Object.hasOwn(variableLabels, labelKey) ? variableLabels[labelKey] : undefined;
|
|
36
|
+
const dom = createElementWithClass("span", systemVariables.includes(name) ? SYSTEM_CHIP_CLASS : USER_CHIP_CLASS);
|
|
37
|
+
dom.contentEditable = "false";
|
|
38
|
+
dom.append(document.createTextNode(label !== undefined && label !== "" ? label : name));
|
|
39
|
+
if (!labelOnly && label !== undefined && label !== "" && label !== name) {
|
|
40
|
+
dom.append(createElementWithClass("small", "font-mono text-[10px] opacity-75", name));
|
|
41
|
+
}
|
|
42
|
+
return { dom };
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// Same rule the sanitizer's image handling follows: previews never carry a
|
|
46
|
+
// scriptable scheme.
|
|
47
|
+
const PREVIEW_SRC = /^(data:image\/(png|jpeg|gif|webp);|blob:|https:\/\/|\/)/;
|
|
48
|
+
function createBlockLabel(text) {
|
|
49
|
+
const label = createElementWithClass("span", "absolute -top-2 left-2 bg-card px-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", text);
|
|
50
|
+
label.contentEditable = "false";
|
|
51
|
+
return label;
|
|
52
|
+
}
|
|
53
|
+
function createResourceView(labels) {
|
|
54
|
+
return ({ node }) => {
|
|
55
|
+
const key = String(node.attrs["resource"]);
|
|
56
|
+
const previews = labels.resourcePreviews ?? {};
|
|
57
|
+
const preview = Object.hasOwn(previews, key) ? previews[key] : undefined;
|
|
58
|
+
const hasImage = preview !== undefined && PREVIEW_SRC.test(preview.src);
|
|
59
|
+
// A rendered image needs no frame until the node is selected (ProseMirror marks it).
|
|
60
|
+
const dom = createElementWithClass("div", hasImage
|
|
61
|
+
? "relative my-1 flex items-center gap-2 rounded border border-transparent px-2 py-1 text-sm text-muted-foreground [.ProseMirror-focused_&.ProseMirror-selectednode]:border-dashed [.ProseMirror-focused_&.ProseMirror-selectednode]:border-input"
|
|
62
|
+
: "relative my-3 flex items-center gap-3 rounded border border-dashed border-input px-3 py-3 text-sm text-muted-foreground");
|
|
63
|
+
dom.setAttribute(DOCUMENT_BLOCK_ATTRIBUTE, "");
|
|
64
|
+
dom.contentEditable = "false";
|
|
65
|
+
if (labels.blockLabels) {
|
|
66
|
+
const label = createBlockLabel(labels.imageBlock ?? labels.image);
|
|
67
|
+
if (hasImage)
|
|
68
|
+
label.classList.add("hidden", "[.ProseMirror-focused_.ProseMirror-selectednode_&]:block");
|
|
69
|
+
dom.append(label);
|
|
70
|
+
}
|
|
71
|
+
if (hasImage) {
|
|
72
|
+
const image = createElementWithClass("img", "max-w-[180px] rounded");
|
|
73
|
+
image.src = preview.src;
|
|
74
|
+
image.alt = typeof node.attrs["alt"] === "string" ? node.attrs["alt"] : key;
|
|
75
|
+
dom.append(image);
|
|
76
|
+
// An empty caption means "no caption", not the key.
|
|
77
|
+
const caption = preview.caption ?? key;
|
|
78
|
+
if (caption !== "") {
|
|
79
|
+
const captionElement = createElementWithClass("span", "whitespace-nowrap text-[11px]", caption.replace(` · ${DOCUMENT_RESOURCE_SIZE_TOKEN}`, ""));
|
|
80
|
+
// The size is only known once the browser decoded the image (possibly already, from cache).
|
|
81
|
+
const showSize = () => {
|
|
82
|
+
captionElement.textContent = caption.replace(DOCUMENT_RESOURCE_SIZE_TOKEN, `${image.naturalWidth} × ${image.naturalHeight} px`);
|
|
83
|
+
};
|
|
84
|
+
image.addEventListener("load", showSize);
|
|
85
|
+
if (image.complete && image.naturalWidth > 0)
|
|
86
|
+
showSize();
|
|
87
|
+
dom.append(captionElement);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
dom.append(createElementWithClass("span", "font-medium", labels.image), createElementWithClass("code", "text-xs", key));
|
|
92
|
+
}
|
|
93
|
+
return { dom };
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function createButtonView(buttonLabel) {
|
|
97
|
+
return () => {
|
|
98
|
+
const dom = createElementWithClass("div", "relative my-3 rounded border border-dashed border-input p-3");
|
|
99
|
+
dom.setAttribute(DOCUMENT_BLOCK_ATTRIBUTE, "");
|
|
100
|
+
const button = document.createElement("a");
|
|
101
|
+
button.setAttribute("data-button", "");
|
|
102
|
+
dom.append(createBlockLabel(buttonLabel), button);
|
|
103
|
+
return { dom, contentDOM: button };
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function createPageBreakView(pageBreakLabel) {
|
|
107
|
+
return () => {
|
|
108
|
+
const dom = createElementWithClass("div", "my-3 border-t border-dashed border-input pt-1 text-center text-xs uppercase tracking-wide text-muted-foreground", pageBreakLabel);
|
|
109
|
+
dom.contentEditable = "false";
|
|
110
|
+
return { dom };
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// Replaced by name, not appended: the schema must keep exactly one node per
|
|
114
|
+
// name, and only the editor view differs from the shared document schema.
|
|
115
|
+
export function createDocumentEditorExtensions(labels) {
|
|
116
|
+
const base = documentExtensions.map((extension) => {
|
|
117
|
+
switch (extension.name) {
|
|
118
|
+
case DocumentVariable.name:
|
|
119
|
+
return DocumentVariable.extend({
|
|
120
|
+
addNodeView: () => createVariableView(labels.variableLabels ?? {}, labels.systemVariables ?? [], labels.blockLabels === true),
|
|
121
|
+
});
|
|
122
|
+
case DocumentResource.name:
|
|
123
|
+
return DocumentResource.extend({ addNodeView: () => createResourceView(labels) });
|
|
124
|
+
case DocumentButton.name:
|
|
125
|
+
return labels.blockLabels
|
|
126
|
+
? DocumentButton.extend({ addNodeView: () => createButtonView(labels.button ?? "") })
|
|
127
|
+
: extension;
|
|
128
|
+
case DocumentPageBreak.name:
|
|
129
|
+
return DocumentPageBreak.extend({
|
|
130
|
+
addNodeView: () => createPageBreakView(labels.pageBreak),
|
|
131
|
+
});
|
|
132
|
+
default:
|
|
133
|
+
return extension;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
// No TrailingNode: it appends an empty paragraph that breaks the HTML roundtrip.
|
|
137
|
+
return [
|
|
138
|
+
...base,
|
|
139
|
+
UndoRedo,
|
|
140
|
+
Gapcursor,
|
|
141
|
+
Dropcursor,
|
|
142
|
+
ListKeymap,
|
|
143
|
+
Placeholder.configure({ placeholder: labels.placeholder }),
|
|
144
|
+
];
|
|
145
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { DocumentEditorProps, DocumentToolbarBlock } from "./document-toolbar-blocks.js";
|
|
3
|
+
export declare const DocumentBlocksContext: import("react").Context<readonly DocumentToolbarBlock[] | undefined>;
|
|
4
|
+
export declare function DocumentContentEditor(props: DocumentEditorProps): ReactNode;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @runtime client
|
|
3
|
+
//
|
|
4
|
+
// Lazy boundary: tiptap only loads when a "document" collection is rendered.
|
|
5
|
+
// Never import document-tiptap-editor or document-editor-extensions statically here.
|
|
6
|
+
import { TextareaContentEditor } from "@cosmicdrift/kumiko-renderer";
|
|
7
|
+
import { createContext, lazy, Suspense, useContext } from "react";
|
|
8
|
+
const LazyDocumentTiptapEditor = lazy(() => import("./document-tiptap-editor.js"));
|
|
9
|
+
// The editor registry only hands ContentEditorProps to an editor, so the
|
|
10
|
+
// collection's block set (mail vs. PDF) reaches it through this context. An
|
|
11
|
+
// explicit `blocks` prop still wins.
|
|
12
|
+
export const DocumentBlocksContext = createContext(undefined);
|
|
13
|
+
export function DocumentContentEditor(props) {
|
|
14
|
+
const contextBlocks = useContext(DocumentBlocksContext);
|
|
15
|
+
const editorProps = props.blocks === undefined ? { ...props, blocks: contextBlocks } : props;
|
|
16
|
+
return (_jsx(Suspense, { fallback: _jsx(TextareaContentEditor, { id: props.id, value: props.value, onChange: props.onChange, variables: props.variables, readOnly: props.readOnly }), children: _jsx(LazyDocumentTiptapEditor, { ...editorProps }) }));
|
|
17
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type DocumentEditorProps } from "./document-toolbar-blocks.js";
|
|
3
|
+
export default function DocumentTiptapEditor({ id, value, onChange, variables, readOnly, blocks, variableLabels, systemVariables, resourcePreviews, chrome, toolbar, renderPaper, toolbarHost, onEditorReady, }: DocumentEditorProps): ReactNode;
|