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
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
type User = {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
email: string;
|
|
5
|
+
role: string;
|
|
6
|
+
createdAt: Date;
|
|
7
|
+
};
|
|
8
|
+
type Props = {
|
|
9
|
+
data?: User[];
|
|
10
|
+
state?: 'loading' | 'error' | 'ok';
|
|
11
|
+
};
|
|
12
|
+
declare const UsersPage: import("svelte").Component<Props, {}, "">;
|
|
2
13
|
type UsersPage = ReturnType<typeof UsersPage>;
|
|
3
14
|
export default UsersPage;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
3
|
-
import { formatRelativeDate as formatRelativeDateUtil } from '../../utils/
|
|
3
|
+
import { formatRelativeDate as formatRelativeDateUtil } from '../../utils/formatters.js';
|
|
4
4
|
import Skeleton from '../../../components/ui/skeleton/skeleton.svelte';
|
|
5
5
|
import { getRemotes } from '../../../sveltekit/index.js';
|
|
6
6
|
import { getLocalizedLabel } from '../../utils/collectionLabel.js';
|
|
@@ -9,21 +9,9 @@
|
|
|
9
9
|
const interfaceLanguage = useInterfaceLanguage();
|
|
10
10
|
const remotes = getRemotes();
|
|
11
11
|
|
|
12
|
-
const lang: Record<InterfaceLanguage, {
|
|
13
|
-
title:
|
|
14
|
-
|
|
15
|
-
noSubmissions: string;
|
|
16
|
-
}> = {
|
|
17
|
-
pl: {
|
|
18
|
-
title: 'Zgłoszenia',
|
|
19
|
-
viewAll: 'Wszystkie →',
|
|
20
|
-
noSubmissions: 'Brak zgłoszeń'
|
|
21
|
-
},
|
|
22
|
-
en: {
|
|
23
|
-
title: 'Submissions',
|
|
24
|
-
viewAll: 'View all →',
|
|
25
|
-
noSubmissions: 'No submissions'
|
|
26
|
-
}
|
|
12
|
+
const lang: Record<InterfaceLanguage, { title: string; noSubmissions: string; unread: string }> = {
|
|
13
|
+
pl: { title: 'Zgłoszenia', noSubmissions: 'Brak zgłoszeń', unread: 'nieprzeczytane' },
|
|
14
|
+
en: { title: 'Submissions', noSubmissions: 'No submissions', unread: 'unread' }
|
|
27
15
|
};
|
|
28
16
|
|
|
29
17
|
function formatRelativeDate(date: Date): string {
|
|
@@ -31,75 +19,72 @@
|
|
|
31
19
|
}
|
|
32
20
|
|
|
33
21
|
const query = $derived(remotes.getSubmissionsOverview());
|
|
22
|
+
|
|
23
|
+
// Flat list of the most recent submissions across all forms, newest first.
|
|
24
|
+
const recentSubmissions = $derived.by(() => {
|
|
25
|
+
const overview = query.current;
|
|
26
|
+
if (!overview) return [];
|
|
27
|
+
return overview
|
|
28
|
+
.flatMap((form) =>
|
|
29
|
+
form.recent.map((s) => ({
|
|
30
|
+
...s,
|
|
31
|
+
formLabel: getLocalizedLabel(form.label as Localized, interfaceLanguage.current) ?? form.slug
|
|
32
|
+
}))
|
|
33
|
+
)
|
|
34
|
+
.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
|
|
35
|
+
.slice(0, 6);
|
|
36
|
+
});
|
|
34
37
|
</script>
|
|
35
38
|
|
|
36
39
|
<section class="dash-card dash-card--forms" aria-labelledby="forms-heading">
|
|
37
40
|
<div class="dash-card-header">
|
|
38
41
|
<h2 class="dash-card-title" id="forms-heading">{lang[interfaceLanguage.current].title}</h2>
|
|
39
|
-
<a href="/admin/forms" class="dash-card-link">{lang[interfaceLanguage.current].viewAll}</a>
|
|
40
42
|
</div>
|
|
41
43
|
|
|
42
44
|
{#if !query.ready}
|
|
43
|
-
<
|
|
44
|
-
{#each Array(
|
|
45
|
-
<
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
<ul class="entries-list">
|
|
46
|
+
{#each Array(4) as _}
|
|
47
|
+
<li class="entry-item">
|
|
48
|
+
<div class="entry-item-link" style="pointer-events:none">
|
|
49
|
+
<div class="entry-item-main">
|
|
50
|
+
<Skeleton class="h-4 w-40" />
|
|
51
|
+
<Skeleton class="h-3 w-24 mt-1" />
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</li>
|
|
50
55
|
{/each}
|
|
51
|
-
</
|
|
56
|
+
</ul>
|
|
52
57
|
{:else if query.current}
|
|
53
|
-
{@const overview = query.current}
|
|
54
58
|
<div class:opacity-60={query.loading} class="transition-opacity duration-200">
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<span style="flex:1; min-width:0; font-size:13px; font-weight:{submission.read ? '500' : '700'}; color:{submission.read ? 'var(--muted-foreground)' : 'var(--foreground)'}; overflow:hidden; text-overflow:ellipsis; white-space:nowrap">
|
|
85
|
-
{submission.preview || '—'}
|
|
86
|
-
</span>
|
|
87
|
-
<time style="font-size:11px; color:var(--text-light); white-space:nowrap; flex-shrink:0">
|
|
88
|
-
{formatRelativeDate(new Date(submission.createdAt))}
|
|
89
|
-
</time>
|
|
90
|
-
</a>
|
|
91
|
-
</li>
|
|
92
|
-
{/each}
|
|
93
|
-
</ul>
|
|
94
|
-
{:else}
|
|
95
|
-
<p style="font-size:13px; color:var(--text-light); padding:4px 10px">
|
|
96
|
-
{lang[interfaceLanguage.current].noSubmissions}
|
|
97
|
-
</p>
|
|
98
|
-
{/if}
|
|
99
|
-
</div>
|
|
100
|
-
{/each}
|
|
101
|
-
</div>
|
|
102
|
-
{/if}
|
|
59
|
+
{#if recentSubmissions.length === 0}
|
|
60
|
+
<p class="text-center text-sm py-6" style="color:var(--text-light)">
|
|
61
|
+
{lang[interfaceLanguage.current].noSubmissions}
|
|
62
|
+
</p>
|
|
63
|
+
{:else}
|
|
64
|
+
<ul class="entries-list" aria-label={lang[interfaceLanguage.current].title}>
|
|
65
|
+
{#each recentSubmissions as submission (submission.id)}
|
|
66
|
+
<li class="entry-item">
|
|
67
|
+
<a href="/admin/form-submissions/{submission.id}" class="entry-item-link">
|
|
68
|
+
<span
|
|
69
|
+
aria-hidden="true"
|
|
70
|
+
style="width:7px;height:7px;border-radius:9999px;flex:none;align-self:center;margin-right:8px;background:{submission.read
|
|
71
|
+
? 'var(--border)'
|
|
72
|
+
: 'var(--primary)'}"
|
|
73
|
+
></span>
|
|
74
|
+
<div class="entry-item-main">
|
|
75
|
+
<span class="entry-item-title" style={submission.read ? '' : 'font-weight:700'}>
|
|
76
|
+
{submission.preview || '—'}
|
|
77
|
+
{#if !submission.read}<span class="sr-only">({lang[interfaceLanguage.current].unread})</span>{/if}
|
|
78
|
+
</span>
|
|
79
|
+
<span class="entry-item-meta">
|
|
80
|
+
{submission.formLabel} · {formatRelativeDate(new Date(submission.createdAt))}
|
|
81
|
+
</span>
|
|
82
|
+
</div>
|
|
83
|
+
</a>
|
|
84
|
+
</li>
|
|
85
|
+
{/each}
|
|
86
|
+
</ul>
|
|
87
|
+
{/if}
|
|
103
88
|
</div>
|
|
104
89
|
{/if}
|
|
105
90
|
</section>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
3
|
-
import { formatRelativeDate as formatRelativeDateUtil } from '../../utils/
|
|
3
|
+
import { formatRelativeDate as formatRelativeDateUtil } from '../../utils/formatters.js';
|
|
4
|
+
import { getLocalizedLabel } from '../../utils/collectionLabel.js';
|
|
4
5
|
import Skeleton from '../../../components/ui/skeleton/skeleton.svelte';
|
|
5
6
|
import { getRemotes } from '../../../sveltekit/index.js';
|
|
6
|
-
import type { InterfaceLanguage } from '../../../types/languages.js';
|
|
7
|
+
import type { InterfaceLanguage, Localized } from '../../../types/languages.js';
|
|
7
8
|
|
|
8
9
|
const interfaceLanguage = useInterfaceLanguage();
|
|
9
10
|
const remotes = getRemotes();
|
|
@@ -29,7 +30,9 @@
|
|
|
29
30
|
return formatRelativeDateUtil(date, interfaceLanguage.current);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
const query = $derived(
|
|
33
|
+
const query = $derived(
|
|
34
|
+
remotes.getRecentActivity({ limit: 10, language: interfaceLanguage.current })
|
|
35
|
+
);
|
|
33
36
|
</script>
|
|
34
37
|
|
|
35
38
|
<section class="dash-card dash-card--activity" aria-labelledby="activity-heading">
|
|
@@ -61,6 +64,10 @@
|
|
|
61
64
|
{:else}
|
|
62
65
|
<ul class="activity-list" aria-label={lang[interfaceLanguage.current].title}>
|
|
63
66
|
{#each activity as item, i}
|
|
67
|
+
{@const containerName = (
|
|
68
|
+
getLocalizedLabel(item.containerLabel as Localized, interfaceLanguage.current) ??
|
|
69
|
+
item.slug
|
|
70
|
+
).toLocaleLowerCase(interfaceLanguage.current)}
|
|
64
71
|
<li class="activity-item">
|
|
65
72
|
<div class="activity-dot-col">
|
|
66
73
|
<div class="activity-dot activity-dot--edit" aria-hidden="true"></div>
|
|
@@ -70,10 +77,15 @@
|
|
|
70
77
|
</div>
|
|
71
78
|
<a href="/admin/entries/{item.entryId}" class="activity-body" style="text-decoration:none">
|
|
72
79
|
<p class="activity-text">
|
|
73
|
-
{
|
|
80
|
+
{#if item.kind === 'single'}
|
|
81
|
+
{lang[interfaceLanguage.current].edited} {containerName}
|
|
82
|
+
{:else}
|
|
83
|
+
{lang[interfaceLanguage.current].edited} {containerName} „{item.label || item.slug}"{#if item.label && item.labelLanguage && item.labelLanguage !== interfaceLanguage.current}<span style="color:var(--text-light);font-weight:400;font-size:0.85em">{' '}({item.labelLanguage})</span>{/if}
|
|
84
|
+
{/if}
|
|
74
85
|
</p>
|
|
75
86
|
<p class="activity-meta">
|
|
76
|
-
{
|
|
87
|
+
{(item.editorName ? item.editorName + ' · ' : '') +
|
|
88
|
+
formatRelativeDate(new Date(item.updatedAt))}
|
|
77
89
|
</p>
|
|
78
90
|
</a>
|
|
79
91
|
</li>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
3
|
-
import { formatRelativeDate as formatRelativeDateUtil } from '../../utils/
|
|
3
|
+
import { formatRelativeDate as formatRelativeDateUtil } from '../../utils/formatters.js';
|
|
4
4
|
import { getLocalizedLabel } from '../../utils/collectionLabel.js';
|
|
5
5
|
import Skeleton from '../../../components/ui/skeleton/skeleton.svelte';
|
|
6
6
|
import { getRemotes } from '../../../sveltekit/index.js';
|
|
@@ -45,13 +45,12 @@
|
|
|
45
45
|
scheduled: '◐'
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
const query = $derived(remotes.getRecentEntries(6));
|
|
48
|
+
const query = $derived(remotes.getRecentEntries({ limit: 6, language: interfaceLanguage.current }));
|
|
49
49
|
</script>
|
|
50
50
|
|
|
51
51
|
<section class="dash-card dash-card--entries" aria-labelledby="entries-heading">
|
|
52
52
|
<div class="dash-card-header">
|
|
53
53
|
<h2 class="dash-card-title" id="entries-heading">{lang[interfaceLanguage.current].title}</h2>
|
|
54
|
-
<a href="/admin/entries" class="dash-card-link">{lang[interfaceLanguage.current].viewAll}</a>
|
|
55
54
|
</div>
|
|
56
55
|
|
|
57
56
|
{#if !query.ready}
|
|
@@ -77,13 +76,26 @@
|
|
|
77
76
|
{:else}
|
|
78
77
|
<ul class="entries-list" aria-label={lang[interfaceLanguage.current].title}>
|
|
79
78
|
{#each entries as entry}
|
|
79
|
+
{@const containerName = getLocalizedLabel(
|
|
80
|
+
entry.containerLabel as Localized,
|
|
81
|
+
interfaceLanguage.current
|
|
82
|
+
)}
|
|
80
83
|
<li class="entry-item">
|
|
81
84
|
<a href="/admin/entries/{entry.entryId}" class="entry-item-link">
|
|
82
85
|
<div class="entry-item-main">
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
{#if entry.kind === 'single'}
|
|
87
|
+
<span class="entry-item-title">{containerName}</span>
|
|
88
|
+
<span class="entry-item-meta">
|
|
89
|
+
{formatRelativeDate(new Date(entry.updatedAt))}
|
|
90
|
+
</span>
|
|
91
|
+
{:else}
|
|
92
|
+
<span class="entry-item-title"
|
|
93
|
+
>{entry.label || entry.slug}{#if entry.label && entry.labelLanguage && entry.labelLanguage !== interfaceLanguage.current}<span style="color:var(--text-light);font-weight:400;font-size:0.85em">{' '}({entry.labelLanguage})</span>{/if}</span
|
|
94
|
+
>
|
|
95
|
+
<span class="entry-item-meta">
|
|
96
|
+
{containerName} · {formatRelativeDate(new Date(entry.updatedAt))}
|
|
97
|
+
</span>
|
|
98
|
+
{/if}
|
|
87
99
|
</div>
|
|
88
100
|
<span class="dash-status-badge dash-status-{entry.status}">
|
|
89
101
|
<span aria-hidden="true">{statusIcon[entry.status] ?? ''}</span>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
* Reusable confirmation dialog — wraps bits-ui AlertDialog with destructive
|
|
5
|
+
* default + safe focus (Cancel autofocus) + loading state.
|
|
6
|
+
*
|
|
7
|
+
* Used by entry-page (copy-from-lang, archive), shop-order-detail (cancel
|
|
8
|
+
* shipping), coupons-list (delete), dashboard-page (delete orphaned),
|
|
9
|
+
* form-submissions (bulk delete). S8.
|
|
10
|
+
*/
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
import * as AlertDialog from '../../../components/ui/alert-dialog/index.js';
|
|
15
|
+
import { buttonVariants } from '../../../components/ui/button/button.svelte';
|
|
16
|
+
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
17
|
+
import type { InterfaceLanguage } from '../../../types/languages.js';
|
|
18
|
+
import Loader2 from '@tabler/icons-svelte/icons/loader-2';
|
|
19
|
+
import { cn } from '../../../utils.js';
|
|
20
|
+
|
|
21
|
+
type Props = {
|
|
22
|
+
open: boolean;
|
|
23
|
+
title: string;
|
|
24
|
+
description: string;
|
|
25
|
+
confirmLabel?: string;
|
|
26
|
+
cancelLabel?: string;
|
|
27
|
+
variant?: 'destructive' | 'default';
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
onConfirm: () => void | Promise<void>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
let {
|
|
33
|
+
open = $bindable(false),
|
|
34
|
+
title,
|
|
35
|
+
description,
|
|
36
|
+
confirmLabel,
|
|
37
|
+
cancelLabel,
|
|
38
|
+
variant = 'destructive',
|
|
39
|
+
loading = false,
|
|
40
|
+
onConfirm
|
|
41
|
+
}: Props = $props();
|
|
42
|
+
|
|
43
|
+
const interfaceLanguage = useInterfaceLanguage();
|
|
44
|
+
|
|
45
|
+
const lang: Record<
|
|
46
|
+
InterfaceLanguage,
|
|
47
|
+
{ defaultConfirmDestructive: string; defaultConfirmDefault: string; defaultCancel: string }
|
|
48
|
+
> = {
|
|
49
|
+
pl: {
|
|
50
|
+
defaultConfirmDestructive: 'Usuń',
|
|
51
|
+
defaultConfirmDefault: 'Potwierdź',
|
|
52
|
+
defaultCancel: 'Anuluj'
|
|
53
|
+
},
|
|
54
|
+
en: {
|
|
55
|
+
defaultConfirmDestructive: 'Delete',
|
|
56
|
+
defaultConfirmDefault: 'Confirm',
|
|
57
|
+
defaultCancel: 'Cancel'
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const resolvedConfirm = $derived(
|
|
62
|
+
confirmLabel ??
|
|
63
|
+
(variant === 'destructive'
|
|
64
|
+
? lang[interfaceLanguage.current].defaultConfirmDestructive
|
|
65
|
+
: lang[interfaceLanguage.current].defaultConfirmDefault)
|
|
66
|
+
);
|
|
67
|
+
const resolvedCancel = $derived(cancelLabel ?? lang[interfaceLanguage.current].defaultCancel);
|
|
68
|
+
|
|
69
|
+
let cancelRef = $state<HTMLElement | null>(null);
|
|
70
|
+
|
|
71
|
+
$effect(() => {
|
|
72
|
+
if (!open) return;
|
|
73
|
+
// Defer to ensure portal mounted, then focus Cancel for safety.
|
|
74
|
+
queueMicrotask(() => cancelRef?.focus());
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
async function handleAction(event: Event) {
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
if (loading) return;
|
|
80
|
+
await onConfirm();
|
|
81
|
+
open = false;
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<AlertDialog.Root bind:open>
|
|
86
|
+
<AlertDialog.Content>
|
|
87
|
+
<AlertDialog.Title>{title}</AlertDialog.Title>
|
|
88
|
+
<AlertDialog.Description>{description}</AlertDialog.Description>
|
|
89
|
+
<AlertDialog.Footer>
|
|
90
|
+
<AlertDialog.Cancel bind:ref={cancelRef} disabled={loading}>
|
|
91
|
+
{resolvedCancel}
|
|
92
|
+
</AlertDialog.Cancel>
|
|
93
|
+
<AlertDialog.Action
|
|
94
|
+
class={cn(buttonVariants({ variant }), 'inline-flex items-center gap-2')}
|
|
95
|
+
disabled={loading}
|
|
96
|
+
onclick={handleAction}
|
|
97
|
+
>
|
|
98
|
+
{#if loading}
|
|
99
|
+
<Loader2 class="size-4 animate-spin" aria-hidden="true" />
|
|
100
|
+
{/if}
|
|
101
|
+
{resolvedConfirm}
|
|
102
|
+
</AlertDialog.Action>
|
|
103
|
+
</AlertDialog.Footer>
|
|
104
|
+
</AlertDialog.Content>
|
|
105
|
+
</AlertDialog.Root>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
5
|
+
confirmLabel?: string;
|
|
6
|
+
cancelLabel?: string;
|
|
7
|
+
variant?: 'destructive' | 'default';
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
onConfirm: () => void | Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
declare const ConfirmationDialog: import("svelte").Component<Props, {}, "open">;
|
|
12
|
+
type ConfirmationDialog = ReturnType<typeof ConfirmationDialog>;
|
|
13
|
+
export default ConfirmationDialog;
|
|
@@ -62,6 +62,12 @@
|
|
|
62
62
|
/>
|
|
63
63
|
</div>
|
|
64
64
|
|
|
65
|
+
<div class="sr-only" role="status" aria-live="polite">
|
|
66
|
+
{#if searchQuery.trim()}
|
|
67
|
+
{filteredOptions.length} {pt.noBlocksFound === 'Nie znaleziono bloków' ? 'wyników' : 'results'}
|
|
68
|
+
{/if}
|
|
69
|
+
</div>
|
|
70
|
+
|
|
65
71
|
<div class="grid max-h-[60vh] grid-cols-2 gap-4 overflow-y-auto">
|
|
66
72
|
{#each filteredOptions as option (option.slug)}
|
|
67
73
|
<button
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
import { droppable, draggable, dndState } from '@thisux/sveltednd';
|
|
29
29
|
import { flip } from 'svelte/animate';
|
|
30
30
|
import { arrayMove } from '../../utils/arrayMove.js';
|
|
31
|
+
import { LiveRegion } from '../../../components/ui/live-region/index.js';
|
|
31
32
|
|
|
32
33
|
const contentLanguage = getContentLanguage();
|
|
33
34
|
const interfaceLanguage = useInterfaceLanguage();
|
|
@@ -42,6 +43,18 @@
|
|
|
42
43
|
};
|
|
43
44
|
const bt = $derived(blocksLang[interfaceLanguage.current]);
|
|
44
45
|
|
|
46
|
+
const announceLang: Record<InterfaceLanguage, { movedTo: string; added: string; removed: string; duplicated: string }> = {
|
|
47
|
+
pl: { movedTo: 'Przeniesiono na pozycję', added: 'Dodano blok', removed: 'Usunięto blok', duplicated: 'Zduplikowano blok' },
|
|
48
|
+
en: { movedTo: 'Moved to position', added: 'Added block', removed: 'Removed block', duplicated: 'Duplicated block' }
|
|
49
|
+
};
|
|
50
|
+
const at = $derived(announceLang[interfaceLanguage.current]);
|
|
51
|
+
let announcement = $state('');
|
|
52
|
+
|
|
53
|
+
function announce(text: string) {
|
|
54
|
+
announcement = '';
|
|
55
|
+
queueMicrotask(() => { announcement = text; });
|
|
56
|
+
}
|
|
57
|
+
|
|
45
58
|
function generateId(): string {
|
|
46
59
|
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
47
60
|
return crypto.randomUUID();
|
|
@@ -111,6 +124,9 @@
|
|
|
111
124
|
}
|
|
112
125
|
];
|
|
113
126
|
|
|
127
|
+
const label = getLocalizedLabel(field.label, interfaceLanguage.current) || field.slug;
|
|
128
|
+
announce(`${at.added}: ${label}`);
|
|
129
|
+
|
|
114
130
|
openAndCloseOthers($value.length - 1);
|
|
115
131
|
}
|
|
116
132
|
|
|
@@ -122,6 +138,9 @@
|
|
|
122
138
|
const copy = JSON.parse(JSON.stringify(itemToDuplicate));
|
|
123
139
|
copy._id = generateId();
|
|
124
140
|
|
|
141
|
+
const label = getAccordionLabel(itemToDuplicate) || `${index + 1}`;
|
|
142
|
+
announce(`${at.duplicated}: ${label}`);
|
|
143
|
+
|
|
125
144
|
$value = [...$value.slice(0, index + 1), copy, ...$value.slice(index + 1)];
|
|
126
145
|
|
|
127
146
|
tick().then(() => {
|
|
@@ -131,10 +150,13 @@
|
|
|
131
150
|
|
|
132
151
|
function moveItemUp(index: number) {
|
|
133
152
|
if (!$value || index <= 0) return;
|
|
153
|
+
const label = getAccordionLabel($value[index]) || `${index + 1}`;
|
|
134
154
|
const newValue = [...$value];
|
|
135
155
|
[newValue[index - 1], newValue[index]] = [newValue[index], newValue[index - 1]];
|
|
136
156
|
$value = newValue;
|
|
137
157
|
|
|
158
|
+
announce(`${label}: ${at.movedTo} ${index}`);
|
|
159
|
+
|
|
138
160
|
tick().then(() => {
|
|
139
161
|
openAndCloseOthers(index - 1);
|
|
140
162
|
});
|
|
@@ -142,10 +164,13 @@
|
|
|
142
164
|
|
|
143
165
|
function moveItemDown(index: number) {
|
|
144
166
|
if (!$value || index >= $value.length - 1) return;
|
|
167
|
+
const label = getAccordionLabel($value[index]) || `${index + 1}`;
|
|
145
168
|
const newValue = [...$value];
|
|
146
169
|
[newValue[index], newValue[index + 1]] = [newValue[index + 1], newValue[index]];
|
|
147
170
|
$value = newValue;
|
|
148
171
|
|
|
172
|
+
announce(`${label}: ${at.movedTo} ${index + 2}`);
|
|
173
|
+
|
|
149
174
|
tick().then(() => {
|
|
150
175
|
openAndCloseOthers(index + 1);
|
|
151
176
|
});
|
|
@@ -155,8 +180,11 @@
|
|
|
155
180
|
|
|
156
181
|
function moveItem(from: number, to: number) {
|
|
157
182
|
if (!$value || from === to) return;
|
|
183
|
+
const label = getAccordionLabel($value[from]) || `${from + 1}`;
|
|
158
184
|
$value = arrayMove($value, from, to);
|
|
159
185
|
|
|
186
|
+
announce(`${label}: ${at.movedTo} ${to + 1}`);
|
|
187
|
+
|
|
160
188
|
tick().then(() => {
|
|
161
189
|
openAndCloseOthers(to);
|
|
162
190
|
});
|
|
@@ -165,8 +193,11 @@
|
|
|
165
193
|
function removeItem(index: number) {
|
|
166
194
|
if (!$value) return;
|
|
167
195
|
|
|
196
|
+
const label = getAccordionLabel($value[index]) || `${index + 1}`;
|
|
168
197
|
accordionOpenState = accordionOpenState.filter((i) => i !== index.toString());
|
|
169
198
|
$value = $value.filter((_, i) => i !== index);
|
|
199
|
+
|
|
200
|
+
announce(`${at.removed}: ${label}`);
|
|
170
201
|
}
|
|
171
202
|
|
|
172
203
|
function getAccordionLabel(item: ObjectFieldData) {
|
|
@@ -394,7 +425,19 @@
|
|
|
394
425
|
{/if}
|
|
395
426
|
</div>
|
|
396
427
|
</Accordion.Trigger>
|
|
397
|
-
|
|
428
|
+
<!--
|
|
429
|
+
forceMount keeps nested block fields in the DOM when
|
|
430
|
+
closed (so scroll-to-issue can find them and
|
|
431
|
+
activateContainingAccordions can auto-expand them).
|
|
432
|
+
accordion-content.svelte collapses forceMount content
|
|
433
|
+
with a grid-template-rows transition — animated both
|
|
434
|
+
ways, and it holds the collapsed state (the one-shot
|
|
435
|
+
keyframe cannot once the panel stays mounted).
|
|
436
|
+
-->
|
|
437
|
+
<Accordion.Content
|
|
438
|
+
forceMount
|
|
439
|
+
class="space-y-4 rounded-b-md border border-t-0 bg-card/80 p-4"
|
|
440
|
+
>
|
|
398
441
|
{@const itemPath = joinPath(path, index)}
|
|
399
442
|
<div data-field-path={itemPath}>
|
|
400
443
|
<FieldRenderer
|
|
@@ -460,3 +503,5 @@
|
|
|
460
503
|
</div>
|
|
461
504
|
{/if}
|
|
462
505
|
{/if}
|
|
506
|
+
|
|
507
|
+
<LiveRegion message={announcement} />
|
|
@@ -39,7 +39,9 @@
|
|
|
39
39
|
const { value } = formFieldProxy(form, path) as { value: import('svelte/store').Writable<any> };
|
|
40
40
|
|
|
41
41
|
const fieldsWithNoDescription: FieldType[] = ['boolean', 'object', 'blocks', 'seo', 'shop'];
|
|
42
|
-
|
|
42
|
+
// 'slug' renders its own label paired with the Auto toggle (flex header),
|
|
43
|
+
// so the field-renderer must not duplicate it.
|
|
44
|
+
const fieldsWithNoLabel: FieldType[] = ['boolean', 'object', 'blocks', 'seo', 'shop', 'slug'];
|
|
43
45
|
|
|
44
46
|
const fieldsWithAlternativeDescription: FieldType[] = ['media', 'object', 'blocks'];
|
|
45
47
|
|
|
@@ -102,10 +104,10 @@
|
|
|
102
104
|
<Form.FieldErrors />
|
|
103
105
|
</Form.Fieldset>
|
|
104
106
|
{:else if isTextField(field)}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
<!-- TextFieldWrapper is self-contained (own Form.Field + Form.FieldErrors).
|
|
108
|
+
Wrapping it again here produced a nested form-item and a duplicated
|
|
109
|
+
error message (QA 5a #1c). -->
|
|
110
|
+
<TextFieldWrapper {field} {form} {path} {...props} />
|
|
109
111
|
{:else}
|
|
110
112
|
<Form.Field {form} name={path}>
|
|
111
113
|
<Form.Control>
|
|
@@ -123,46 +125,46 @@
|
|
|
123
125
|
|
|
124
126
|
{#if field.type === 'media'}
|
|
125
127
|
{#await import('./media-field.svelte') then { default: MediaField }}
|
|
126
|
-
<MediaField {field} bind:value={$value} />
|
|
128
|
+
<MediaField {field} bind:value={$value} {...props} />
|
|
127
129
|
{/await}
|
|
128
130
|
{:else if field.type === 'file'}
|
|
129
131
|
{#await import('./file-field.svelte') then { default: FileField }}
|
|
130
|
-
<FileField {field} bind:value={$value} />
|
|
132
|
+
<FileField {field} bind:value={$value} {...props} />
|
|
131
133
|
{/await}
|
|
132
134
|
{:else if field.type === 'blocks'}
|
|
133
|
-
<LazyField loader={() => import('./blocks-field.svelte')} props={{ field, form, path, focusedPath, flashingPath, depth }} skeletonClass="h-20" />
|
|
135
|
+
<LazyField loader={() => import('./blocks-field.svelte')} props={{ field, form, path, focusedPath, flashingPath, depth, ...props }} skeletonClass="h-20" />
|
|
134
136
|
{:else if field.type === 'array'}
|
|
135
137
|
{#await import('./simple-array-field.svelte') then { default: ArrayField }}
|
|
136
|
-
<ArrayField {field} bind:value={$value} />
|
|
138
|
+
<ArrayField {field} bind:value={$value} {form} {path} {...props} />
|
|
137
139
|
{/await}
|
|
138
140
|
{:else if field.type === 'object'}
|
|
139
|
-
<LazyField loader={() => import('./object-field.svelte')} props={{ field, form, path, objectFieldType: distributed ? 'distributed' : objectFieldType, focusedPath, flashingPath, depth }} skeletonClass="h-20" />
|
|
141
|
+
<LazyField loader={() => import('./object-field.svelte')} props={{ field, form, path, objectFieldType: distributed ? 'distributed' : objectFieldType, focusedPath, flashingPath, depth, ...props }} skeletonClass="h-20" />
|
|
140
142
|
{:else if field.type === 'slug'}
|
|
141
|
-
<LazyField loader={() => import('./slug-field.svelte')} props={{ field, form, path }} skeletonClass="h-10" />
|
|
143
|
+
<LazyField loader={() => import('./slug-field.svelte')} props={{ field, form, path, ...props }} skeletonClass="h-10" />
|
|
142
144
|
{:else if field.type === 'boolean'}
|
|
143
|
-
<BooleanField {field} bind:value={$value} />
|
|
145
|
+
<BooleanField {field} bind:value={$value} {...props} />
|
|
144
146
|
{:else if field.type === 'number'}
|
|
145
|
-
<NumberField {field} bind:value={$value} />
|
|
147
|
+
<NumberField {field} bind:value={$value} {...props} />
|
|
146
148
|
{:else if field.type === 'seo'}
|
|
147
|
-
<LazyField loader={() => import('./seo-field.svelte')} props={{ field, form, path }} skeletonClass="h-16" />
|
|
149
|
+
<LazyField loader={() => import('./seo-field.svelte')} props={{ field, form, path, ...props }} skeletonClass="h-16" />
|
|
148
150
|
{:else if field.type === 'shop'}
|
|
149
|
-
<LazyField loader={() => import('./shop-field.svelte')} props={{ field }} skeletonClass="h-40" />
|
|
151
|
+
<LazyField loader={() => import('./shop-field.svelte')} props={{ field, ...props }} skeletonClass="h-40" />
|
|
150
152
|
{:else if field.type === 'url'}
|
|
151
|
-
<UrlFieldWrapper {field} {form} {path} />
|
|
153
|
+
<UrlFieldWrapper {field} {form} {path} {...props} />
|
|
152
154
|
{:else if field.type === 'relation'}
|
|
153
155
|
{#await import('./relation-field.svelte') then { default: RelationField }}
|
|
154
|
-
<RelationField {field} bind:value={$value} />
|
|
156
|
+
<RelationField {field} bind:value={$value} {...props} />
|
|
155
157
|
{/await}
|
|
156
158
|
{:else if field.type === 'date'}
|
|
157
|
-
<DateField {field} bind:value={$value} />
|
|
159
|
+
<DateField {field} bind:value={$value} {...props} />
|
|
158
160
|
{:else if field.type === 'datetime'}
|
|
159
|
-
<DateTimeField {field} bind:value={$value} />
|
|
161
|
+
<DateTimeField {field} bind:value={$value} {...props} />
|
|
160
162
|
{:else if field.type === 'select'}
|
|
161
|
-
<SelectField {field} bind:value={$value} />
|
|
163
|
+
<SelectField {field} bind:value={$value} {...props} />
|
|
162
164
|
{:else if field.type === 'custom'}
|
|
163
165
|
{@const customDef = customFieldDefs.get(field.fieldType)}
|
|
164
166
|
{#if customDef}
|
|
165
|
-
<LazyField loader={customDef.component} props={{ field, form, path }} skeletonClass="h-20" />
|
|
167
|
+
<LazyField loader={customDef.component} props={{ field, form, path, ...props }} skeletonClass="h-20" />
|
|
166
168
|
{:else}
|
|
167
169
|
<p>Nieznany custom field: {field.fieldType}</p>
|
|
168
170
|
{/if}
|