includio-cms 0.25.0 → 0.26.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/API.md +57 -4
- package/CHANGELOG.md +53 -0
- package/DOCS.md +1 -1
- package/README.md +2 -0
- package/ROADMAP.md +6 -0
- package/dist/admin/client/account/lang.d.ts +1 -0
- package/dist/admin/client/account/lang.js +4 -2
- package/dist/admin/client/account/profile-section.svelte +2 -2
- package/dist/admin/client/account/security-section.svelte +27 -4
- package/dist/admin/client/account/sessions-section.svelte +1 -1
- package/dist/admin/client/admin/admin-after-login-layout-content.svelte +1 -1
- package/dist/admin/client/admin/dashboard-page.svelte +34 -10
- package/dist/admin/client/collection/bulk-actions-bar.svelte +86 -44
- package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +3 -1
- package/dist/admin/client/collection/collection-entries.svelte +52 -36
- package/dist/admin/client/collection/collection-entries.svelte.d.ts +3 -0
- package/dist/admin/client/collection/collection.svelte +28 -14
- package/dist/admin/client/collection/collection.svelte.d.ts +3 -0
- package/dist/admin/client/collection/data-table.svelte +279 -130
- package/dist/admin/client/collection/data-table.svelte.d.ts +11 -0
- package/dist/admin/client/collection/date-cell.svelte +4 -4
- package/dist/admin/client/collection/row-actions.svelte +2 -1
- package/dist/admin/client/collection/sortable-header.svelte +33 -9
- package/dist/admin/client/collection/state-display.svelte +102 -0
- package/dist/admin/client/collection/state-display.svelte.d.ts +12 -0
- package/dist/admin/client/collection/status-badge.svelte +99 -11
- package/dist/admin/client/collection/status-badge.svelte.d.ts +15 -1
- package/dist/admin/client/collection/table-pagination.svelte +21 -6
- package/dist/admin/client/collection/table-toolbar.svelte +105 -80
- package/dist/admin/client/collection/table-toolbar.svelte.d.ts +11 -8
- package/dist/admin/client/entry/entry-form.svelte +36 -11
- package/dist/admin/client/entry/entry-form.svelte.d.ts +1 -0
- package/dist/admin/client/entry/entry-header.svelte +22 -15
- package/dist/admin/client/entry/entry-header.svelte.d.ts +1 -0
- package/dist/admin/client/entry/entry.svelte +269 -165
- package/dist/admin/client/entry/header/a11y-header-badge.svelte +47 -0
- package/dist/admin/client/entry/header/a11y-header-badge.svelte.d.ts +8 -0
- package/dist/admin/client/entry/header/publish-panel.svelte +69 -13
- package/dist/admin/client/entry/header/save-indicator.svelte +57 -28
- package/dist/admin/client/entry/header/save-indicator.svelte.d.ts +1 -0
- package/dist/admin/client/entry/header/status-badge.svelte +60 -15
- package/dist/admin/client/entry/header/status-badge.svelte.d.ts +1 -2
- package/dist/admin/client/entry/header/version-history-sheet.svelte +1 -1
- package/dist/admin/client/entry/hybrid/hybrid-layout.svelte +74 -23
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +1 -1
- package/dist/admin/client/entry/utils.d.ts +14 -0
- package/dist/admin/client/entry/utils.js +28 -0
- package/dist/admin/client/form/form-submission/form-submission.svelte +2 -2
- package/dist/admin/client/form/form-submissions.svelte +143 -194
- package/dist/admin/client/form/form-submissions.svelte.d.ts +2 -0
- package/dist/admin/client/login/lang.d.ts +3 -0
- package/dist/admin/client/login/lang.js +10 -4
- package/dist/admin/client/login/login-form.svelte +8 -1
- package/dist/admin/client/login/reset-password-page.svelte +24 -3
- package/dist/admin/client/login/schema.d.ts +14 -2
- package/dist/admin/client/login/schema.js +19 -8
- package/dist/admin/client/maintenance/maintenance-page.svelte +16 -17
- package/dist/admin/client/media/media-page.svelte +1 -1
- package/dist/admin/client/shop/coupon-edit-page.svelte +117 -13
- package/dist/admin/client/shop/coupon-form.svelte +282 -138
- package/dist/admin/client/shop/coupon-form.svelte.d.ts +1 -9
- package/dist/admin/client/shop/coupon-new-page.svelte +40 -10
- package/dist/admin/client/shop/coupon-new-page.svelte.d.ts +2 -17
- package/dist/admin/client/shop/coupon-schema.d.ts +28 -0
- package/dist/admin/client/shop/coupon-schema.js +53 -0
- package/dist/admin/client/shop/coupons-list-page.svelte +262 -118
- package/dist/admin/client/shop/coupons-list-page.svelte.d.ts +16 -1
- package/dist/admin/client/shop/shipping-method-edit-page.svelte +108 -59
- package/dist/admin/client/shop/shipping-method-form.svelte +36 -9
- package/dist/admin/client/shop/shipping-method-new-page.svelte +44 -13
- package/dist/admin/client/shop/shipping-methods-list-page.svelte +101 -59
- package/dist/admin/client/shop/shop-order-detail-page.svelte +113 -84
- package/dist/admin/client/shop/shop-orders-list-page.svelte +302 -152
- package/dist/admin/client/shop/shop-orders-list-page.svelte.d.ts +18 -1
- package/dist/admin/client/shop/shop-products-list-page.svelte +355 -118
- package/dist/admin/client/shop/shop-products-list-page.svelte.d.ts +19 -1
- package/dist/admin/client/users/accept-invite-page.svelte +24 -3
- package/dist/admin/client/users/create-user-dialog.svelte +3 -8
- package/dist/admin/client/users/lang.d.ts +2 -0
- package/dist/admin/client/users/lang.js +4 -0
- package/dist/admin/client/users/pending-invitations.svelte +2 -9
- package/dist/admin/client/users/user-name-cell.svelte +20 -0
- package/dist/admin/client/users/user-name-cell.svelte.d.ts +9 -0
- package/dist/admin/client/users/user-role-badge.svelte +16 -0
- package/dist/admin/client/users/user-role-badge.svelte.d.ts +7 -0
- package/dist/admin/client/users/user-row-actions.svelte +72 -0
- package/dist/admin/client/users/user-row-actions.svelte.d.ts +20 -0
- package/dist/admin/client/users/user-sessions-sheet.svelte +2 -11
- package/dist/admin/client/users/users-page.svelte +283 -497
- package/dist/admin/client/users/users-page.svelte.d.ts +12 -1
- package/dist/admin/components/dashboard/form-submissions-widget.svelte +59 -74
- package/dist/admin/components/dashboard/recent-activity.svelte +17 -5
- package/dist/admin/components/dashboard/recent-entries.svelte +19 -7
- package/dist/admin/components/dialogs/confirmation-dialog.svelte +105 -0
- package/dist/admin/components/dialogs/confirmation-dialog.svelte.d.ts +13 -0
- package/dist/admin/components/fields/block-picker-modal.svelte +6 -0
- package/dist/admin/components/fields/blocks-field.svelte +46 -1
- package/dist/admin/components/fields/boolean-field.svelte +1 -1
- package/dist/admin/components/fields/field-renderer.svelte +23 -21
- package/dist/admin/components/fields/file-field.svelte +344 -30
- package/dist/admin/components/fields/media-field.svelte +16 -2
- package/dist/admin/components/fields/radio-field.svelte +22 -0
- package/dist/admin/components/fields/relation-field.svelte +123 -97
- package/dist/admin/components/fields/relation-picker-dialog.svelte +2 -2
- package/dist/admin/components/fields/seo-field.svelte +60 -30
- package/dist/admin/components/fields/shop-field.svelte +9 -4
- package/dist/admin/components/fields/simple-array-field.svelte +321 -151
- package/dist/admin/components/fields/simple-array-field.svelte.d.ts +3 -0
- package/dist/admin/components/fields/slug-field.svelte +146 -21
- package/dist/admin/components/fields/text-field-wrapper.svelte +37 -20
- package/dist/admin/components/fields/text-field.svelte +7 -2
- package/dist/admin/components/fields/url-field-wrapper.svelte +10 -0
- package/dist/admin/components/fields/url-field.svelte +36 -23
- package/dist/admin/components/forms/form-error-summary.svelte +143 -0
- package/dist/admin/components/forms/form-error-summary.svelte.d.ts +27 -0
- package/dist/admin/components/layout/app-sidebar.svelte +7 -2
- package/dist/admin/components/layout/detail-page-shell.svelte +71 -0
- package/dist/admin/components/layout/detail-page-shell.svelte.d.ts +24 -0
- package/dist/admin/components/layout/lang.d.ts +5 -0
- package/dist/admin/components/layout/lang.js +10 -0
- package/dist/admin/components/layout/layout-renderer.svelte +71 -2
- package/dist/admin/components/layout/layout-renderer.svelte.d.ts +1 -0
- package/dist/admin/components/layout/layout-tabs.svelte +172 -0
- package/dist/admin/components/layout/layout-tabs.svelte.d.ts +24 -0
- package/dist/admin/components/layout/nav-breadcrumbs.svelte +25 -7
- package/dist/admin/components/layout/nav-collections.svelte +23 -36
- package/dist/admin/components/layout/nav-forms.svelte +19 -35
- package/dist/admin/components/layout/nav-main.svelte +3 -28
- package/dist/admin/components/layout/nav-search.svelte +70 -2
- package/dist/admin/components/layout/nav-section.svelte +77 -0
- package/dist/admin/components/layout/nav-section.svelte.d.ts +22 -0
- package/dist/admin/components/layout/nav-shop.svelte +3 -27
- package/dist/admin/components/layout/nav-singletons.svelte +16 -28
- package/dist/admin/components/layout/page-header.stories.svelte +93 -0
- package/dist/admin/components/layout/page-header.stories.svelte.d.ts +27 -0
- package/dist/admin/components/layout/page-header.svelte +68 -0
- package/dist/admin/components/layout/page-header.svelte.d.ts +17 -0
- package/dist/admin/components/layout/site-header.svelte +9 -0
- package/dist/admin/components/layout/site-header.svelte.d.ts +2 -17
- package/dist/admin/components/media/file/file-name-input.svelte +6 -2
- package/dist/admin/components/media/file/file-preview.svelte +130 -17
- package/dist/admin/components/media/file-upload.svelte +16 -7
- package/dist/admin/components/media/file-upload.svelte.d.ts +1 -0
- package/dist/admin/components/media/files-list.svelte +153 -53
- package/dist/admin/components/media/files-list.svelte.d.ts +1 -0
- package/dist/admin/components/media/media-library.svelte +577 -198
- package/dist/admin/components/media/media-library.svelte.d.ts +4 -0
- package/dist/admin/components/media/media-selector.svelte +4 -2
- package/dist/admin/components/media/media-selector.svelte.d.ts +1 -0
- package/dist/admin/components/media/tag-sidebar.svelte +4 -4
- package/dist/admin/components/tiptap/FigureNodeView.svelte +10 -0
- package/dist/admin/components/tiptap/bubble-menu.svelte +104 -0
- package/dist/admin/components/tiptap/bubble-menu.svelte.d.ts +19 -0
- package/dist/admin/components/tiptap/content-editor.svelte +28 -24
- package/dist/admin/components/tiptap/editor-toolbar.svelte +7 -7
- package/dist/admin/components/tiptap/extensions.js +5 -1
- package/dist/admin/components/tiptap/image-dialog.svelte +5 -1
- package/dist/admin/components/tiptap/link-dialog.svelte +2 -0
- package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -20
- package/dist/admin/components/tiptap/video-dialog.svelte +1 -1
- package/dist/admin/i18n/errors.d.ts +140 -0
- package/dist/admin/i18n/errors.js +151 -0
- package/dist/admin/remote/entry.remote.d.ts +59 -4
- package/dist/admin/remote/entry.remote.js +239 -62
- package/dist/admin/remote/shop.remote.d.ts +37 -32
- package/dist/admin/remote/shop.remote.js +9 -2
- package/dist/admin/shared/password-generate.d.ts +6 -0
- package/dist/admin/shared/password-generate.js +40 -0
- package/dist/admin/shared/password-schema.d.ts +6 -0
- package/dist/admin/shared/password-schema.js +10 -3
- package/dist/admin/styles/admin.css +23 -6
- package/dist/admin/styles/tokens.md +244 -0
- package/dist/admin/utils/accordionActivation.d.ts +13 -0
- package/dist/admin/utils/accordionActivation.js +35 -0
- package/dist/admin/utils/entryLabel.d.ts +23 -0
- package/dist/admin/utils/entryLabel.js +51 -12
- package/dist/admin/utils/field-a11y.d.ts +29 -0
- package/dist/admin/utils/field-a11y.js +23 -0
- package/dist/admin/utils/fieldPathElement.d.ts +9 -0
- package/dist/admin/utils/fieldPathElement.js +18 -0
- package/dist/admin/utils/fileDisplay.d.ts +10 -0
- package/dist/admin/utils/fileDisplay.js +26 -0
- package/dist/admin/utils/flattenFormErrors.d.ts +19 -0
- package/dist/admin/utils/flattenFormErrors.js +102 -0
- package/dist/admin/utils/formatters.d.ts +12 -0
- package/dist/admin/utils/{formatDate.js → formatters.js} +23 -2
- package/dist/admin/utils/scrollWithin.d.ts +9 -0
- package/dist/admin/utils/scrollWithin.js +32 -0
- package/dist/admin/utils/tabActivation.d.ts +12 -0
- package/dist/admin/utils/tabActivation.js +24 -0
- package/dist/cms/runtime/schema.d.ts +1 -0
- package/dist/cms/runtime/schema.js +1 -0
- package/dist/cms/runtime/types.d.ts +80 -7
- package/dist/components/ui/accordion/accordion-content.svelte +17 -3
- package/dist/components/ui/accordion/accordion.stories.svelte +21 -1
- package/dist/components/ui/alert/alert.stories.svelte +14 -0
- package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte +45 -0
- package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte.d.ts +27 -0
- package/dist/components/ui/avatar/avatar.stories.svelte +27 -0
- package/dist/components/ui/badge/badge.stories.svelte +15 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +47 -0
- package/dist/components/ui/breadcrumb/breadcrumb.svelte +1 -1
- package/dist/components/ui/button/button.stories.svelte +53 -6
- package/dist/components/ui/button/button.svelte +39 -5
- package/dist/components/ui/button/button.svelte.d.ts +4 -0
- package/dist/components/ui/button-group/button-group.stories.svelte +44 -0
- package/dist/components/ui/button-group/button-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/calendar/calendar.stories.svelte +36 -0
- package/dist/components/ui/calendar/calendar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/card/card.stories.svelte +7 -0
- package/dist/components/ui/carousel/carousel.stories.svelte +43 -0
- package/dist/components/ui/carousel/carousel.stories.svelte.d.ts +27 -0
- package/dist/components/ui/checkbox/checkbox.stories.svelte +67 -0
- package/dist/components/ui/checkbox/checkbox.stories.svelte.d.ts +27 -0
- package/dist/components/ui/checkbox/checkbox.svelte +3 -3
- package/dist/components/ui/command/command.stories.svelte +18 -0
- package/dist/components/ui/data-table/data-table.stories.svelte +61 -0
- package/dist/components/ui/data-table/data-table.stories.svelte.d.ts +18 -0
- package/dist/components/ui/dialog/dialog-content.svelte +5 -0
- package/dist/components/ui/dialog/dialog-content.svelte.d.ts +2 -0
- package/dist/components/ui/dialog/dialog.stories.svelte +35 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte +74 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte.d.ts +27 -0
- package/dist/components/ui/field/field-context.svelte.d.ts +22 -0
- package/dist/components/ui/field/field-context.svelte.js +9 -0
- package/dist/components/ui/field/field-control.svelte +18 -0
- package/dist/components/ui/field/field-control.svelte.d.ts +8 -0
- package/dist/components/ui/field/field-description.svelte +12 -0
- package/dist/components/ui/field/field-error.svelte +14 -6
- package/dist/components/ui/field/field-label.svelte +10 -0
- package/dist/components/ui/field/field.stories.svelte +95 -9
- package/dist/components/ui/field/field.svelte +57 -0
- package/dist/components/ui/field/field.svelte.d.ts +2 -0
- package/dist/components/ui/field/index.d.ts +3 -1
- package/dist/components/ui/field/index.js +4 -2
- package/dist/components/ui/form/form-field-errors.svelte +1 -1
- package/dist/components/ui/form/form.stories.svelte +25 -0
- package/dist/components/ui/form/form.stories.svelte.d.ts +26 -0
- package/dist/components/ui/input/input.stories.svelte +26 -0
- package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
- package/dist/components/ui/input-group/input-group.stories.svelte +43 -0
- package/dist/components/ui/input-group/input-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/item/item.stories.svelte +61 -0
- package/dist/components/ui/item/item.stories.svelte.d.ts +27 -0
- package/dist/components/ui/label/label.stories.svelte +7 -0
- package/dist/components/ui/live-region/index.d.ts +1 -0
- package/dist/components/ui/live-region/index.js +1 -0
- package/dist/components/ui/live-region/live-region-demo.svelte +32 -0
- package/dist/components/ui/live-region/live-region-demo.svelte.d.ts +7 -0
- package/dist/components/ui/live-region/live-region.stories.svelte +23 -0
- package/dist/components/ui/live-region/live-region.stories.svelte.d.ts +26 -0
- package/dist/components/ui/live-region/live-region.svelte +12 -0
- package/dist/components/ui/live-region/live-region.svelte.d.ts +8 -0
- package/dist/components/ui/popover/popover.stories.svelte +34 -0
- package/dist/components/ui/radio-group/radio-group.stories.svelte +58 -0
- package/dist/components/ui/radio-group/radio-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/resizable/resizable.stories.svelte +56 -0
- package/dist/components/ui/resizable/resizable.stories.svelte.d.ts +27 -0
- package/dist/components/ui/select/select.stories.svelte +49 -0
- package/dist/components/ui/separator/separator.stories.svelte +18 -0
- package/dist/components/ui/sheet/sheet.stories.svelte +34 -0
- package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte +1 -0
- package/dist/components/ui/sidebar/sidebar-trigger.svelte +1 -1
- package/dist/components/ui/sidebar/sidebar.stories.svelte +72 -0
- package/dist/components/ui/sidebar/sidebar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/skeleton/skeleton.stories.svelte +39 -0
- package/dist/components/ui/skeleton/skeleton.stories.svelte.d.ts +27 -0
- package/dist/components/ui/skeleton/skeleton.svelte +6 -0
- package/dist/components/ui/sonner/index.d.ts +1 -1
- package/dist/components/ui/sonner/index.js +1 -1
- package/dist/components/ui/sonner/sonner.stories.svelte +7 -0
- package/dist/components/ui/sonner/sonner.svelte +17 -1
- package/dist/components/ui/sonner/sonner.svelte.d.ts +6 -0
- package/dist/components/ui/spinner/spinner.stories.svelte +30 -0
- package/dist/components/ui/spinner/spinner.stories.svelte.d.ts +27 -0
- package/dist/components/ui/switch/switch.stories.svelte +56 -0
- package/dist/components/ui/switch/switch.stories.svelte.d.ts +27 -0
- package/dist/components/ui/table/table-cell.svelte +1 -1
- package/dist/components/ui/table/table-head.svelte +1 -1
- package/dist/components/ui/table/table.stories.svelte +68 -0
- package/dist/components/ui/table/table.stories.svelte.d.ts +27 -0
- package/dist/components/ui/table/table.svelte +1 -1
- package/dist/components/ui/tabs/tabs.stories.svelte +48 -0
- package/dist/components/ui/tabs/tabs.stories.svelte.d.ts +27 -0
- package/dist/components/ui/textarea/textarea.stories.svelte +21 -0
- package/dist/components/ui/toggle/toggle.stories.svelte +23 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte +43 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte +46 -6
- package/dist/core/fields/fieldSchemaToTs.d.ts +7 -0
- package/dist/core/fields/fieldSchemaToTs.js +234 -90
- package/dist/core/fields/layoutUtils.d.ts +4 -1
- package/dist/core/fields/layoutUtils.js +41 -4
- package/dist/core/fields/resolveSeo.d.ts +70 -0
- package/dist/core/fields/resolveSeo.js +88 -0
- package/dist/core/fields/seoFieldDescriptor.d.ts +43 -0
- package/dist/core/fields/seoFieldDescriptor.js +74 -0
- package/dist/core/fields/slugPath.d.ts +13 -0
- package/dist/core/fields/slugPath.js +32 -0
- package/dist/core/fields/urlUtils.d.ts +8 -0
- package/dist/core/fields/urlUtils.js +27 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/server/entries/operations/create.js +13 -0
- package/dist/core/server/entries/operations/get.d.ts +7 -0
- package/dist/core/server/entries/operations/get.js +10 -6
- package/dist/core/server/entries/operations/slugUniqueness.d.ts +37 -0
- package/dist/core/server/entries/operations/slugUniqueness.js +116 -0
- package/dist/core/server/entries/operations/update.d.ts +6 -1
- package/dist/core/server/entries/operations/update.js +24 -1
- package/dist/core/server/fields/slugResolver.d.ts +3 -13
- package/dist/core/server/fields/slugResolver.js +8 -37
- package/dist/core/server/generator/fields.js +10 -17
- package/dist/core/server/generator/formFields.js +2 -1
- package/dist/core/server/generator/generator.js +4 -4
- package/dist/core/server/generator/utils.d.ts +1 -0
- package/dist/core/server/generator/utils.js +4 -0
- package/dist/paraglide/messages/_index.d.ts +3 -36
- package/dist/paraglide/messages/_index.js +3 -71
- package/dist/paraglide/messages/hello_world.d.ts +5 -0
- package/dist/paraglide/messages/hello_world.js +33 -0
- package/dist/paraglide/messages/login_hello.d.ts +16 -0
- package/dist/paraglide/messages/login_hello.js +34 -0
- package/dist/paraglide/messages/login_please_login.d.ts +16 -0
- package/dist/paraglide/messages/login_please_login.js +34 -0
- package/dist/shop/server/orders.d.ts +1 -0
- package/dist/shop/server/orders.js +14 -0
- package/dist/shop/server/shop-data.d.ts +2 -0
- package/dist/shop/server/shop-data.js +20 -5
- package/dist/sveltekit/server/handle.js +17 -0
- package/dist/types/cms.schema.js +4 -2
- package/dist/types/fields.d.ts +35 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/layout.d.ts +35 -2
- package/dist/updates/0.26.0/index.d.ts +2 -0
- package/dist/updates/0.26.0/index.js +51 -0
- package/dist/updates/index.js +3 -1
- package/package.json +29 -7
- package/dist/admin/client/collection/empty-state.svelte +0 -28
- package/dist/admin/client/collection/empty-state.svelte.d.ts +0 -9
- package/dist/admin/client/form/submission-status-badge.svelte +0 -41
- package/dist/admin/client/form/submission-status-badge.svelte.d.ts +0 -7
- package/dist/admin/components/media/file-preview.svelte +0 -51
- package/dist/admin/components/media/file-preview.svelte.d.ts +0 -6
- package/dist/admin/utils/formatDate.d.ts +0 -5
- package/dist/paraglide/messages/en.d.ts +0 -5
- package/dist/paraglide/messages/en.js +0 -14
- package/dist/paraglide/messages/pl.d.ts +0 -5
- package/dist/paraglide/messages/pl.js +0 -14
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useInterfaceLanguage } from '../../../state/interface-language.svelte.js';
|
|
3
|
+
import { getContentLanguage } from '../../../state/content-language.svelte.js';
|
|
4
|
+
import type { Field } from '../../../../types/fields.js';
|
|
5
|
+
import type { InterfaceLanguage } from '../../../../types/languages.js';
|
|
6
|
+
import AlertTriangle from '@tabler/icons-svelte/icons/alert-triangle';
|
|
7
|
+
import { validateA11y, a11yLangPl, a11yLangEn } from './a11y-validator.js';
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
data: Record<string, unknown>;
|
|
11
|
+
fields: Field[];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
let { data, fields }: Props = $props();
|
|
15
|
+
|
|
16
|
+
const interfaceLanguage = useInterfaceLanguage();
|
|
17
|
+
const contentLanguage = getContentLanguage();
|
|
18
|
+
|
|
19
|
+
const lang: Record<InterfaceLanguage, { title: (n: number) => string }> = {
|
|
20
|
+
en: {
|
|
21
|
+
title: (n) => `${n} accessibility issue${n === 1 ? '' : 's'} — open settings to review`
|
|
22
|
+
},
|
|
23
|
+
pl: {
|
|
24
|
+
title: (n) =>
|
|
25
|
+
`${n} ${n === 1 ? 'kwestia' : n < 5 ? 'kwestie' : 'kwestii'} dostępności — otwórz ustawienia, by zobaczyć`
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const warningCount = $derived.by(() => {
|
|
30
|
+
if (!fields.length) return 0;
|
|
31
|
+
const a11yLang = interfaceLanguage.current === 'pl' ? a11yLangPl : a11yLangEn;
|
|
32
|
+
const issues = validateA11y(data, fields, a11yLang, contentLanguage.all);
|
|
33
|
+
return issues.filter((i) => i.type === 'warning').length;
|
|
34
|
+
});
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
{#if warningCount > 0}
|
|
38
|
+
<span
|
|
39
|
+
class="text-warning inline-flex items-center gap-1 rounded-md bg-[var(--warning-bg)] px-1.5 py-0.5 text-xs font-medium"
|
|
40
|
+
role="status"
|
|
41
|
+
aria-label={lang[interfaceLanguage.current].title(warningCount)}
|
|
42
|
+
title={lang[interfaceLanguage.current].title(warningCount)}
|
|
43
|
+
>
|
|
44
|
+
<AlertTriangle class="size-3.5" aria-hidden="true" />
|
|
45
|
+
<span aria-hidden="true">{warningCount}</span>
|
|
46
|
+
</span>
|
|
47
|
+
{/if}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Field } from '../../../../types/fields.js';
|
|
2
|
+
type Props = {
|
|
3
|
+
data: Record<string, unknown>;
|
|
4
|
+
fields: Field[];
|
|
5
|
+
};
|
|
6
|
+
declare const A11yHeaderBadge: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type A11yHeaderBadge = ReturnType<typeof A11yHeaderBadge>;
|
|
8
|
+
export default A11yHeaderBadge;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { Field } from '../../../../types/fields.js';
|
|
7
7
|
import * as Sheet from '../../../../components/ui/sheet/index.js';
|
|
8
8
|
import Button from '../../../../components/ui/button/button.svelte';
|
|
9
|
+
import ConfirmationDialog from '../../../components/dialogs/confirmation-dialog.svelte';
|
|
9
10
|
import SettingsIcon from '@tabler/icons-svelte/icons/settings';
|
|
10
11
|
import CalendarClock from '@tabler/icons-svelte/icons/calendar-clock';
|
|
11
12
|
import SquareCheckFilled from '@tabler/icons-svelte/icons/square-check-filled';
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
import InfoCircle from '@tabler/icons-svelte/icons/info-circle';
|
|
17
18
|
import Shield from '@tabler/icons-svelte/icons/shield';
|
|
18
19
|
import CircleCheck from '@tabler/icons-svelte/icons/circle-check';
|
|
19
|
-
import {
|
|
20
|
+
import { getLangPublishState } from '../utils.js';
|
|
20
21
|
import { validateA11y, a11yLangPl, a11yLangEn, type A11yIssue } from './a11y-validator.js';
|
|
21
22
|
import { getContentLanguage } from '../../../state/content-language.svelte.js';
|
|
22
23
|
import LanguageIcon from '@tabler/icons-svelte/icons/language';
|
|
@@ -32,11 +33,14 @@
|
|
|
32
33
|
scheduledFor: string;
|
|
33
34
|
schedulePublish: string;
|
|
34
35
|
scheduleUpdate: string;
|
|
36
|
+
rescheduleUpdate: string;
|
|
37
|
+
scheduledUpdateAt: string;
|
|
35
38
|
reschedule: string;
|
|
36
39
|
schedule: string;
|
|
37
40
|
cancel: string;
|
|
38
41
|
unpublish: string;
|
|
39
42
|
cancelSchedule: string;
|
|
43
|
+
cancelScheduledUpdate: string;
|
|
40
44
|
archive: string;
|
|
41
45
|
dangerZone: string;
|
|
42
46
|
date: string;
|
|
@@ -47,6 +51,9 @@
|
|
|
47
51
|
translations: string;
|
|
48
52
|
translationsHint: string;
|
|
49
53
|
missingFieldsLabel: (lang: string) => string;
|
|
54
|
+
confirmArchiveTitle: string;
|
|
55
|
+
confirmArchiveDescription: string;
|
|
56
|
+
confirmArchiveAction: string;
|
|
50
57
|
}
|
|
51
58
|
> = {
|
|
52
59
|
en: {
|
|
@@ -63,11 +70,14 @@
|
|
|
63
70
|
scheduledFor: 'Scheduled for',
|
|
64
71
|
schedulePublish: 'Schedule Publish',
|
|
65
72
|
scheduleUpdate: 'Schedule Update',
|
|
73
|
+
rescheduleUpdate: 'Reschedule Update',
|
|
74
|
+
scheduledUpdateAt: 'Scheduled update',
|
|
66
75
|
reschedule: 'Reschedule',
|
|
67
76
|
schedule: 'Schedule',
|
|
68
77
|
cancel: 'Cancel',
|
|
69
78
|
unpublish: 'Unpublish',
|
|
70
79
|
cancelSchedule: 'Cancel Schedule',
|
|
80
|
+
cancelScheduledUpdate: 'Cancel scheduled update',
|
|
71
81
|
archive: 'Archive entry',
|
|
72
82
|
dangerZone: 'Danger Zone',
|
|
73
83
|
date: 'Date',
|
|
@@ -77,7 +87,11 @@
|
|
|
77
87
|
a11yHint: 'Resolve issues before publishing',
|
|
78
88
|
translations: 'Translations',
|
|
79
89
|
translationsHint: 'Fill in missing fields to publish',
|
|
80
|
-
missingFieldsLabel: (lang: string) => `Missing fields (${lang.toUpperCase()})
|
|
90
|
+
missingFieldsLabel: (lang: string) => `Missing fields (${lang.toUpperCase()})`,
|
|
91
|
+
confirmArchiveTitle: 'Archive this entry?',
|
|
92
|
+
confirmArchiveDescription:
|
|
93
|
+
'It will disappear from the list and stop being publicly visible. You can restore it from the archive at any time.',
|
|
94
|
+
confirmArchiveAction: 'Archive'
|
|
81
95
|
},
|
|
82
96
|
pl: {
|
|
83
97
|
title: 'Publikacja',
|
|
@@ -93,11 +107,14 @@
|
|
|
93
107
|
scheduledFor: 'Zaplanowano na',
|
|
94
108
|
schedulePublish: 'Zaplanuj publikację',
|
|
95
109
|
scheduleUpdate: 'Zaplanuj aktualizację',
|
|
110
|
+
rescheduleUpdate: 'Zmień termin aktualizacji',
|
|
111
|
+
scheduledUpdateAt: 'Zaplanowana aktualizacja',
|
|
96
112
|
reschedule: 'Zmień termin',
|
|
97
113
|
schedule: 'Zaplanuj',
|
|
98
114
|
cancel: 'Anuluj',
|
|
99
115
|
unpublish: 'Cofnij publikację',
|
|
100
116
|
cancelSchedule: 'Anuluj planowanie',
|
|
117
|
+
cancelScheduledUpdate: 'Anuluj zaplanowaną aktualizację',
|
|
101
118
|
archive: 'Archiwizuj wpis',
|
|
102
119
|
dangerZone: 'Strefa zagrożenia',
|
|
103
120
|
date: 'Data',
|
|
@@ -107,7 +124,11 @@
|
|
|
107
124
|
a11yHint: 'Rozwiąż problemy przed publikacją',
|
|
108
125
|
translations: 'Tłumaczenia',
|
|
109
126
|
translationsHint: 'Uzupełnij brakujące pola, żeby opublikować',
|
|
110
|
-
missingFieldsLabel: (lang: string) => `Brakujące pola (${lang.toUpperCase()})
|
|
127
|
+
missingFieldsLabel: (lang: string) => `Brakujące pola (${lang.toUpperCase()})`,
|
|
128
|
+
confirmArchiveTitle: 'Zarchiwizować wpis?',
|
|
129
|
+
confirmArchiveDescription:
|
|
130
|
+
'Wpis zniknie z listy i przestanie być publicznie widoczny. Możesz go przywrócić z archiwum w każdej chwili.',
|
|
131
|
+
confirmArchiveAction: 'Zarchiwizuj'
|
|
111
132
|
}
|
|
112
133
|
};
|
|
113
134
|
|
|
@@ -132,7 +153,9 @@
|
|
|
132
153
|
let a11yIssues = $state<A11yIssue[]>([]);
|
|
133
154
|
|
|
134
155
|
// Status is per current language
|
|
135
|
-
const
|
|
156
|
+
const langState = $derived(getLangPublishState(entry, contentLanguage.current));
|
|
157
|
+
const entryStatus = $derived(langState.status);
|
|
158
|
+
const hasScheduledUpdate = $derived(langState.hasScheduledUpdate);
|
|
136
159
|
const t = $derived(lang[interfaceLanguage.current]);
|
|
137
160
|
|
|
138
161
|
const hasA11yWarnings = $derived(a11yIssues.some((i) => i.type === 'warning'));
|
|
@@ -141,7 +164,7 @@
|
|
|
141
164
|
const scheduleLabel = $derived.by(() => {
|
|
142
165
|
switch (entryStatus) {
|
|
143
166
|
case 'published':
|
|
144
|
-
return t.scheduleUpdate;
|
|
167
|
+
return hasScheduledUpdate ? t.rescheduleUpdate : t.scheduleUpdate;
|
|
145
168
|
case 'scheduled':
|
|
146
169
|
return t.reschedule;
|
|
147
170
|
default:
|
|
@@ -167,7 +190,7 @@
|
|
|
167
190
|
|
|
168
191
|
function setDefaultValues() {
|
|
169
192
|
const scheduledVersion = entry.scheduledVersions[contentLanguage.current];
|
|
170
|
-
if (entryStatus === 'scheduled'
|
|
193
|
+
if (scheduledVersion?.publishedAt && (entryStatus === 'scheduled' || hasScheduledUpdate)) {
|
|
171
194
|
const scheduled = new Date(scheduledVersion.publishedAt);
|
|
172
195
|
dateValue = scheduled.toISOString().slice(0, 10);
|
|
173
196
|
timeValue = `${String(scheduled.getHours()).padStart(2, '0')}:${String(scheduled.getMinutes()).padStart(2, '0')}`;
|
|
@@ -194,12 +217,20 @@
|
|
|
194
217
|
}
|
|
195
218
|
|
|
196
219
|
function handleCancelSchedule() {
|
|
197
|
-
|
|
220
|
+
// Drafts only the future-dated version(s); a live published version (if any) stays online.
|
|
221
|
+
onSave('cancel-scheduled');
|
|
198
222
|
open = false;
|
|
199
223
|
}
|
|
200
224
|
|
|
225
|
+
let archiveConfirmOpen = $state(false);
|
|
226
|
+
|
|
201
227
|
function handleArchive() {
|
|
228
|
+
archiveConfirmOpen = true;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function performArchive() {
|
|
202
232
|
onArchive();
|
|
233
|
+
archiveConfirmOpen = false;
|
|
203
234
|
open = false;
|
|
204
235
|
}
|
|
205
236
|
|
|
@@ -234,7 +265,7 @@
|
|
|
234
265
|
<Sheet.Root bind:open>
|
|
235
266
|
<Sheet.Trigger>
|
|
236
267
|
{#snippet child({ props })}
|
|
237
|
-
<Button variant="ghost" size="icon-sm" {...props}>
|
|
268
|
+
<Button variant="ghost" size="icon-sm" aria-label={t.title} {...props}>
|
|
238
269
|
<SettingsIcon class="size-4" />
|
|
239
270
|
</Button>
|
|
240
271
|
{/snippet}
|
|
@@ -268,21 +299,28 @@
|
|
|
268
299
|
</div>
|
|
269
300
|
</div>
|
|
270
301
|
|
|
271
|
-
{#if entryStatus === 'published' &&
|
|
302
|
+
{#if entryStatus === 'published' && langState.publishedAt}
|
|
272
303
|
<div class="publish-detail-row">
|
|
273
304
|
<span>{t.publishedAt}</span>
|
|
274
|
-
<span class="tabular-nums">{formatDateTime(
|
|
305
|
+
<span class="tabular-nums">{formatDateTime(langState.publishedAt!)}</span>
|
|
275
306
|
</div>
|
|
276
307
|
{/if}
|
|
277
308
|
|
|
278
|
-
{#if entryStatus === 'scheduled' &&
|
|
309
|
+
{#if entryStatus === 'scheduled' && langState.scheduledAt}
|
|
279
310
|
<div class="publish-detail-row">
|
|
280
311
|
<span>{t.scheduledFor}</span>
|
|
281
|
-
<span class="tabular-nums">{formatDateTime(
|
|
312
|
+
<span class="tabular-nums">{formatDateTime(langState.scheduledAt!)}</span>
|
|
282
313
|
</div>
|
|
283
314
|
{/if}
|
|
284
315
|
|
|
285
|
-
{#if
|
|
316
|
+
{#if entryStatus === 'published' && hasScheduledUpdate && langState.scheduledAt}
|
|
317
|
+
<div class="publish-detail-row">
|
|
318
|
+
<span>{t.scheduledUpdateAt}</span>
|
|
319
|
+
<span class="tabular-nums">{formatDateTime(langState.scheduledAt)}</span>
|
|
320
|
+
</div>
|
|
321
|
+
{/if}
|
|
322
|
+
|
|
323
|
+
{#if entry.publishedVersions[contentLanguage.current] && entry.publishedVersions[contentLanguage.current].id !== version.id}
|
|
286
324
|
<div class="publish-detail-row">
|
|
287
325
|
<span>{t.publishedVersion}</span>
|
|
288
326
|
<span class="tabular-nums">{formatDateTime(entry.publishedVersions[contentLanguage.current].createdAt)}</span>
|
|
@@ -404,6 +442,12 @@
|
|
|
404
442
|
{t.dangerZone}
|
|
405
443
|
</div>
|
|
406
444
|
|
|
445
|
+
{#if entryStatus === 'published' && hasScheduledUpdate}
|
|
446
|
+
<button class="btn-danger-outline" onclick={handleCancelSchedule}>
|
|
447
|
+
{t.cancelScheduledUpdate}
|
|
448
|
+
</button>
|
|
449
|
+
{/if}
|
|
450
|
+
|
|
407
451
|
{#if entryStatus === 'published'}
|
|
408
452
|
<button class="btn-danger-outline" onclick={handleUnpublish}>
|
|
409
453
|
{t.unpublish}
|
|
@@ -429,6 +473,14 @@
|
|
|
429
473
|
</Sheet.Content>
|
|
430
474
|
</Sheet.Root>
|
|
431
475
|
|
|
476
|
+
<ConfirmationDialog
|
|
477
|
+
bind:open={archiveConfirmOpen}
|
|
478
|
+
title={lang[interfaceLanguage.current].confirmArchiveTitle}
|
|
479
|
+
description={lang[interfaceLanguage.current].confirmArchiveDescription}
|
|
480
|
+
confirmLabel={lang[interfaceLanguage.current].confirmArchiveAction}
|
|
481
|
+
onConfirm={performArchive}
|
|
482
|
+
/>
|
|
483
|
+
|
|
432
484
|
<style>
|
|
433
485
|
.sheet-body {
|
|
434
486
|
padding: 18px 20px;
|
|
@@ -524,6 +576,10 @@
|
|
|
524
576
|
.schedule-input:focus {
|
|
525
577
|
border-color: var(--primary);
|
|
526
578
|
}
|
|
579
|
+
.schedule-input:focus-visible {
|
|
580
|
+
outline: 2px solid var(--ring);
|
|
581
|
+
outline-offset: 1px;
|
|
582
|
+
}
|
|
527
583
|
.btn-schedule {
|
|
528
584
|
width: 100%;
|
|
529
585
|
padding: 8px;
|
|
@@ -1,42 +1,65 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useInterfaceLanguage } from '../../../state/interface-language.svelte.js';
|
|
3
3
|
import type { InterfaceLanguage } from '../../../../types/languages.js';
|
|
4
|
+
import { formatRelativeDate } from '../../../utils/formatters.js';
|
|
4
5
|
import Loader2 from '@tabler/icons-svelte/icons/loader-2';
|
|
5
6
|
import Check from '@tabler/icons-svelte/icons/check';
|
|
6
7
|
import AlertCircle from '@tabler/icons-svelte/icons/alert-circle';
|
|
7
8
|
|
|
9
|
+
type SaveStatus = 'idle' | 'saving' | 'saved' | 'unsaved' | 'error';
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
status: SaveStatus;
|
|
13
|
+
lastSavedAt?: Date | null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
let { status, lastSavedAt = null }: Props = $props();
|
|
17
|
+
|
|
18
|
+
const interfaceLanguage = useInterfaceLanguage();
|
|
19
|
+
|
|
8
20
|
const lang: Record<
|
|
9
21
|
InterfaceLanguage,
|
|
10
22
|
{
|
|
11
23
|
saving: string;
|
|
12
|
-
|
|
24
|
+
savedJustNow: string;
|
|
25
|
+
savedAgo: (relative: string) => string;
|
|
13
26
|
unsaved: string;
|
|
14
27
|
error: string;
|
|
15
28
|
}
|
|
16
29
|
> = {
|
|
17
|
-
en: {
|
|
18
|
-
saving: 'Saving draft...',
|
|
19
|
-
saved: 'Draft saved',
|
|
20
|
-
unsaved: 'Unsaved changes',
|
|
21
|
-
error: 'Could not save — try again'
|
|
22
|
-
},
|
|
23
30
|
pl: {
|
|
24
|
-
saving: '
|
|
25
|
-
|
|
31
|
+
saving: 'Zapisuję…',
|
|
32
|
+
savedJustNow: 'Zapisano przed chwilą',
|
|
33
|
+
savedAgo: (rel: string) => `Zapisano ${rel}`,
|
|
26
34
|
unsaved: 'Niezapisane zmiany',
|
|
27
|
-
error: '
|
|
35
|
+
error: 'Błąd zapisu — spróbuj ponownie'
|
|
36
|
+
},
|
|
37
|
+
en: {
|
|
38
|
+
saving: 'Saving…',
|
|
39
|
+
savedJustNow: 'Saved just now',
|
|
40
|
+
savedAgo: (rel: string) => `Saved ${rel}`,
|
|
41
|
+
unsaved: 'Unsaved changes',
|
|
42
|
+
error: 'Save failed — try again'
|
|
28
43
|
}
|
|
29
44
|
};
|
|
30
45
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
type SaveStatus = 'idle' | 'saving' | 'saved' | 'unsaved' | 'error';
|
|
46
|
+
let now = $state(new Date());
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
status
|
|
37
|
-
|
|
48
|
+
$effect(() => {
|
|
49
|
+
if (status !== 'saved' || !lastSavedAt) return;
|
|
50
|
+
const interval = setInterval(() => {
|
|
51
|
+
now = new Date();
|
|
52
|
+
}, 30000);
|
|
53
|
+
return () => clearInterval(interval);
|
|
54
|
+
});
|
|
38
55
|
|
|
39
|
-
|
|
56
|
+
const savedLabel = $derived.by(() => {
|
|
57
|
+
if (!lastSavedAt) return lang[interfaceLanguage.current].savedJustNow;
|
|
58
|
+
const diffMs = now.getTime() - lastSavedAt.getTime();
|
|
59
|
+
if (diffMs < 10000) return lang[interfaceLanguage.current].savedJustNow;
|
|
60
|
+
const rel = formatRelativeDate(lastSavedAt, interfaceLanguage.current);
|
|
61
|
+
return lang[interfaceLanguage.current].savedAgo(rel);
|
|
62
|
+
});
|
|
40
63
|
|
|
41
64
|
const isError = $derived(status === 'error');
|
|
42
65
|
</script>
|
|
@@ -45,24 +68,30 @@
|
|
|
45
68
|
role={isError ? 'alert' : 'status'}
|
|
46
69
|
aria-live={isError ? 'assertive' : 'polite'}
|
|
47
70
|
aria-atomic="true"
|
|
48
|
-
class="flex items-center gap-1.5 text-xs font-medium transition-all duration-200 {status ===
|
|
71
|
+
class="flex items-center gap-1.5 text-xs font-medium transition-all duration-200 {status ===
|
|
72
|
+
'idle'
|
|
73
|
+
? 'invisible'
|
|
74
|
+
: ''}"
|
|
49
75
|
>
|
|
50
76
|
{#if status === 'saving'}
|
|
51
|
-
<Loader2 class="size-3.5 animate-spin
|
|
52
|
-
<span class="text-muted-foreground"
|
|
77
|
+
<Loader2 class="text-muted-foreground size-3.5 animate-spin" aria-hidden="true" />
|
|
78
|
+
<span class="text-muted-foreground max-sm:sr-only"
|
|
79
|
+
>{lang[interfaceLanguage.current].saving}</span
|
|
80
|
+
>
|
|
53
81
|
{:else if status === 'saved'}
|
|
54
|
-
<Check class="size-3.5 text-emerald-
|
|
55
|
-
<span class="text-emerald-
|
|
82
|
+
<Check class="size-3.5 text-emerald-700 dark:text-emerald-400" aria-hidden="true" />
|
|
83
|
+
<span class="text-emerald-700 max-sm:sr-only dark:text-emerald-400">{savedLabel}</span>
|
|
56
84
|
{:else if status === 'unsaved'}
|
|
57
|
-
<span class="size-1.5 rounded-full bg-amber-500
|
|
58
|
-
<span class="text-amber-
|
|
85
|
+
<span class="size-1.5 animate-pulse rounded-full bg-amber-500" aria-hidden="true"></span>
|
|
86
|
+
<span class="text-amber-700 max-sm:sr-only dark:text-amber-400"
|
|
87
|
+
>{lang[interfaceLanguage.current].unsaved}</span
|
|
88
|
+
>
|
|
59
89
|
{:else if status === 'error'}
|
|
60
|
-
<span class="flex items-center gap-1.5 rounded-md
|
|
61
|
-
<AlertCircle class="size-3.5
|
|
62
|
-
<span class="text-
|
|
90
|
+
<span class="bg-destructive-bg flex items-center gap-1.5 rounded-md px-2 py-0.5">
|
|
91
|
+
<AlertCircle class="text-destructive size-3.5" aria-hidden="true" />
|
|
92
|
+
<span class="text-destructive max-sm:sr-only">{lang[interfaceLanguage.current].error}</span>
|
|
63
93
|
</span>
|
|
64
94
|
{:else}
|
|
65
|
-
<!-- idle: invisible but in DOM so live region is registered -->
|
|
66
95
|
<span class="sr-only"> </span>
|
|
67
96
|
{/if}
|
|
68
97
|
</div>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
type SaveStatus = 'idle' | 'saving' | 'saved' | 'unsaved' | 'error';
|
|
2
2
|
type Props = {
|
|
3
3
|
status: SaveStatus;
|
|
4
|
+
lastSavedAt?: Date | null;
|
|
4
5
|
};
|
|
5
6
|
declare const SaveIndicator: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type SaveIndicator = ReturnType<typeof SaveIndicator>;
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useInterfaceLanguage } from '../../../state/interface-language.svelte.js';
|
|
3
|
-
import
|
|
3
|
+
import { getContentLanguage } from '../../../state/content-language.svelte.js';
|
|
4
|
+
import type { EntryVersionStatus, RawEntry } from '../../../../types/entries.js';
|
|
4
5
|
import type { InterfaceLanguage } from '../../../../types/languages.js';
|
|
6
|
+
import { getLangPublishState } from '../utils.js';
|
|
7
|
+
import ClockFilled from '@tabler/icons-svelte/icons/clock-filled';
|
|
5
8
|
|
|
6
9
|
const lang: Record<
|
|
7
10
|
InterfaceLanguage,
|
|
8
11
|
{
|
|
9
12
|
status: Record<EntryVersionStatus, string>;
|
|
10
13
|
ariaLabel: Record<EntryVersionStatus, string>;
|
|
14
|
+
scheduledUpdate: (date: string) => string;
|
|
15
|
+
scheduledUpdateAria: (date: string) => string;
|
|
11
16
|
}
|
|
12
17
|
> = {
|
|
13
18
|
en: {
|
|
@@ -20,7 +25,9 @@
|
|
|
20
25
|
draft: 'You are editing a draft — it is not yet visible to readers',
|
|
21
26
|
scheduled: 'This entry is scheduled for publication',
|
|
22
27
|
published: 'This entry is published and visible to readers'
|
|
23
|
-
}
|
|
28
|
+
},
|
|
29
|
+
scheduledUpdate: (date) => `update ${date}`,
|
|
30
|
+
scheduledUpdateAria: (date) => `; a content update is scheduled for ${date}`
|
|
24
31
|
},
|
|
25
32
|
pl: {
|
|
26
33
|
status: {
|
|
@@ -32,40 +39,78 @@
|
|
|
32
39
|
draft: 'Edytujesz szkic — nie jest jeszcze widoczny dla czytelników',
|
|
33
40
|
scheduled: 'Ten wpis jest zaplanowany do publikacji',
|
|
34
41
|
published: 'Ten wpis jest opublikowany i widoczny dla czytelników'
|
|
35
|
-
}
|
|
42
|
+
},
|
|
43
|
+
scheduledUpdate: (date) => `aktualizacja ${date}`,
|
|
44
|
+
scheduledUpdateAria: (date) => `; zaplanowana aktualizacja treści na ${date}`
|
|
36
45
|
}
|
|
37
46
|
};
|
|
38
47
|
|
|
39
48
|
const interfaceLanguage = useInterfaceLanguage();
|
|
49
|
+
const contentLanguage = getContentLanguage();
|
|
40
50
|
|
|
41
51
|
type Props = {
|
|
42
52
|
entry: RawEntry;
|
|
43
|
-
version: DbEntryVersion;
|
|
44
53
|
};
|
|
45
54
|
|
|
46
|
-
let { entry
|
|
55
|
+
let { entry }: Props = $props();
|
|
47
56
|
|
|
48
|
-
const
|
|
49
|
-
const isScheduledVersion = $derived(entry.scheduledVersions[version.lang]?.id === version.id);
|
|
57
|
+
const state = $derived(getLangPublishState(entry, contentLanguage.current));
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
// Badge never renders 'archived' here (header hides actions when archived);
|
|
60
|
+
// fall back to 'draft' styling defensively.
|
|
61
|
+
const currentStatus = $derived<EntryVersionStatus>(
|
|
62
|
+
state.status === 'published' || state.status === 'scheduled' ? state.status : 'draft'
|
|
63
|
+
);
|
|
56
64
|
|
|
57
65
|
const dotColor = $derived.by(() => {
|
|
58
66
|
if (currentStatus === 'published') return 'var(--success)';
|
|
59
67
|
if (currentStatus === 'scheduled') return 'var(--warning)';
|
|
60
68
|
return 'var(--text-light)';
|
|
61
69
|
});
|
|
70
|
+
|
|
71
|
+
const showUpdateHint = $derived(
|
|
72
|
+
state.status === 'published' && state.hasScheduledUpdate && state.scheduledAt != null
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
function formatShort(date: Date): string {
|
|
76
|
+
return date.toLocaleString(interfaceLanguage.current, {
|
|
77
|
+
day: '2-digit',
|
|
78
|
+
month: '2-digit',
|
|
79
|
+
hour: '2-digit',
|
|
80
|
+
minute: '2-digit'
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const t = $derived(lang[interfaceLanguage.current]);
|
|
85
|
+
const scheduledLabel = $derived(
|
|
86
|
+
showUpdateHint && state.scheduledAt ? formatShort(state.scheduledAt) : ''
|
|
87
|
+
);
|
|
88
|
+
const ariaLabel = $derived(
|
|
89
|
+
t.ariaLabel[currentStatus] +
|
|
90
|
+
(showUpdateHint ? t.scheduledUpdateAria(scheduledLabel) : '')
|
|
91
|
+
);
|
|
62
92
|
</script>
|
|
63
93
|
|
|
64
94
|
<span
|
|
65
95
|
role="status"
|
|
66
|
-
aria-label={
|
|
96
|
+
aria-label={ariaLabel}
|
|
67
97
|
class="inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-xs font-semibold text-muted-foreground"
|
|
68
98
|
>
|
|
69
|
-
<span
|
|
70
|
-
|
|
99
|
+
<span
|
|
100
|
+
class="size-[7px] rounded-full shrink-0"
|
|
101
|
+
style="background:{dotColor}"
|
|
102
|
+
aria-hidden="true"
|
|
103
|
+
></span>
|
|
104
|
+
{t.status[currentStatus]}
|
|
105
|
+
|
|
106
|
+
{#if showUpdateHint}
|
|
107
|
+
<span
|
|
108
|
+
class="inline-flex items-center gap-1 border-l border-border/70 pl-1.5"
|
|
109
|
+
style="color: var(--warning)"
|
|
110
|
+
aria-hidden="true"
|
|
111
|
+
>
|
|
112
|
+
<ClockFilled class="size-3" />
|
|
113
|
+
{t.scheduledUpdate(scheduledLabel)}
|
|
114
|
+
</span>
|
|
115
|
+
{/if}
|
|
71
116
|
</span>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RawEntry } from '../../../../types/entries.js';
|
|
2
2
|
type Props = {
|
|
3
3
|
entry: RawEntry;
|
|
4
|
-
version: DbEntryVersion;
|
|
5
4
|
};
|
|
6
5
|
declare const StatusBadge: import("svelte").Component<Props, {}, "">;
|
|
7
6
|
type StatusBadge = ReturnType<typeof StatusBadge>;
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
<Sheet.Root bind:open>
|
|
171
171
|
<Sheet.Trigger>
|
|
172
172
|
{#snippet child({ props })}
|
|
173
|
-
<Button variant="ghost" size="icon-sm" {...props}>
|
|
173
|
+
<Button variant="ghost" size="icon-sm" aria-label={t.history} {...props}>
|
|
174
174
|
<HistoryIcon class="size-4" />
|
|
175
175
|
</Button>
|
|
176
176
|
{/snippet}
|