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
package/API.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# includio-cms — Public API v0.
|
|
1
|
+
# includio-cms — Public API v0.26.0
|
|
2
2
|
|
|
3
3
|
> Auto-generated by `scripts/generate-api-md.ts`. Do not edit by hand.
|
|
4
4
|
|
|
5
|
-
Entry points: **
|
|
5
|
+
Entry points: **18** · Stable: **413** · Experimental: **2**
|
|
6
6
|
|
|
7
7
|
Tags:
|
|
8
8
|
- `@public` — frozen for v1.0; semver-protected.
|
|
@@ -17,7 +17,9 @@ Tags:
|
|
|
17
17
|
- `getAuth(): <inferred>` — Returns the underlying `better-auth` instance from the initialized CMS.
|
|
18
18
|
- `getCMS(): CMS` — Returns the singleton CMS instance. Must be called after `includioCMS()`
|
|
19
19
|
- `interface ResolvedMedia` — Resolved media file plus its image styles + blur placeholder. Returned by
|
|
20
|
+
- `type ResolvedSeo = { [K in keyof SeoFieldData]: K extends 'ogImage' ? string | MediaFile | undefined : string | unde...` — Normalized SEO data — localized values flattened by `language`. A stable
|
|
20
21
|
- `resolveMediaWithStyles(mediaIds: string[], styles?: ImageFieldStyle[]): Promise<Record<string, ResolvedMedia>>` — Resolve media files by IDs and generate image styles. Useful for plugins or
|
|
22
|
+
- `resolveSeo(entry: { seo?: Record<string, unknown> } | Record<string,..., language?: string): ResolvedSeo` — Resolve `entry.seo` into flat fields, flattening localized objects by
|
|
21
23
|
|
|
22
24
|
### `includio-cms/core`
|
|
23
25
|
|
|
@@ -25,7 +27,9 @@ Tags:
|
|
|
25
27
|
- `getAuth(): <inferred>` — Returns the underlying `better-auth` instance from the initialized CMS.
|
|
26
28
|
- `getCMS(): CMS` — Returns the singleton CMS instance. Must be called after `includioCMS()`
|
|
27
29
|
- `interface ResolvedMedia` — Resolved media file plus its image styles + blur placeholder. Returned by
|
|
30
|
+
- `type ResolvedSeo = { [K in keyof SeoFieldData]: K extends 'ogImage' ? string | MediaFile | undefined : string | unde...` — Normalized SEO data — localized values flattened by `language`. A stable
|
|
28
31
|
- `resolveMediaWithStyles(mediaIds: string[], styles?: ImageFieldStyle[]): Promise<Record<string, ResolvedMedia>>` — Resolve media files by IDs and generate image styles. Useful for plugins or
|
|
32
|
+
- `resolveSeo(entry: { seo?: Record<string, unknown> } | Record<string,..., language?: string): ResolvedSeo` — Resolve `entry.seo` into flat fields, flattening localized objects by
|
|
29
33
|
|
|
30
34
|
### `includio-cms/types`
|
|
31
35
|
|
|
@@ -77,8 +81,8 @@ Tags:
|
|
|
77
81
|
- `interface ImageStyle`
|
|
78
82
|
- `type Language = 'en' | 'pl'`
|
|
79
83
|
- `type Layout = LayoutPreset | LayoutNode[]`
|
|
80
|
-
- `type LayoutNode = SectionNode | ColumnsNode | CardNode | AccordionNode | StackNode`
|
|
81
|
-
- `type LayoutNodeType = 'section' | 'columns' | 'card' | 'accordion' | 'stack'`
|
|
84
|
+
- `type LayoutNode = | SectionNode | ColumnsNode | CardNode | AccordionNode | StackNode | TabsNode | TabNode`
|
|
85
|
+
- `type LayoutNodeType = | 'section' | 'columns' | 'card' | 'accordion' | 'stack' | 'tabs' | 'tab'`
|
|
82
86
|
- `type LayoutPreset = | 'sidebar-right' | 'two-column' | { preset: 'sidebar-right'; sidebar: string[] } | { preset: 'tw...`
|
|
83
87
|
- `type Localized = Partial<Record<InterfaceLanguage, string>> | string`
|
|
84
88
|
- `interface MediaField`
|
|
@@ -109,6 +113,8 @@ Tags:
|
|
|
109
113
|
- `interface SlugField`
|
|
110
114
|
- `interface StackNode`
|
|
111
115
|
- `interface StructuredContentDoc`
|
|
116
|
+
- `interface TabNode` — A single tab. Only valid as a direct child of {@link TabsNode}.
|
|
117
|
+
- `interface TabsNode` — Tab strip. Renders an accessible tablist; each child `tab` becomes a panel.
|
|
112
118
|
- `interface TextField`
|
|
113
119
|
- `interface TypographyConfig`
|
|
114
120
|
- `interface UrlField`
|
|
@@ -233,6 +239,8 @@ Tags:
|
|
|
233
239
|
- `const reorderEntriesCommand: <inferred>`
|
|
234
240
|
- `const reorderShippingMethodsCmd: <inferred>`
|
|
235
241
|
- `const resendOrderEmailCmd: <inferred>`
|
|
242
|
+
- `const searchEntries: <inferred>`
|
|
243
|
+
- `const searchLinkableEntries: <inferred>`
|
|
236
244
|
- `const setFocalPoint: <inferred>`
|
|
237
245
|
- `const setMediaFileAlt: <inferred>`
|
|
238
246
|
- `const setMediaFileTags: <inferred>`
|
|
@@ -336,6 +344,51 @@ Tags:
|
|
|
336
344
|
- `const verification: <inferred>`
|
|
337
345
|
- `const videoStylesTable: <inferred>`
|
|
338
346
|
|
|
347
|
+
### `includio-cms/db-postgres/schema-core`
|
|
348
|
+
|
|
349
|
+
- `const consentLogsTable: <inferred>`
|
|
350
|
+
- `const entriesTable: <inferred>`
|
|
351
|
+
- `const entryVersionsTable: <inferred>`
|
|
352
|
+
- `const formSubmissionsTable: <inferred>`
|
|
353
|
+
- `const imageStylesTable: <inferred>`
|
|
354
|
+
- `const mediaFilesTable: <inferred>`
|
|
355
|
+
- `const mediaFileTagsTable: <inferred>`
|
|
356
|
+
- `const mediaTagsTable: <inferred>`
|
|
357
|
+
- `const videoStylesTable: <inferred>`
|
|
358
|
+
|
|
359
|
+
### `includio-cms/db-postgres/schema-shop`
|
|
360
|
+
|
|
361
|
+
- `type InpostParcelSize = 'A' | 'B' | 'C'`
|
|
362
|
+
- `type InpostServiceType = | 'inpost_locker_standard' | 'inpost_locker_express' | 'inpost_courier_standard' | 'inpost_courie...`
|
|
363
|
+
- `interface ShippingCarrierConfig`
|
|
364
|
+
- `type ShopCarrierType = 'none' | 'inpost' | string`
|
|
365
|
+
- `const shopCouponRedemptionsTable: <inferred>`
|
|
366
|
+
- `const shopCouponsTable: <inferred>`
|
|
367
|
+
- `type ShopCouponType = 'percent' | 'fixed'`
|
|
368
|
+
- `const shopOrderItemsTable: <inferred>`
|
|
369
|
+
- `const shopOrdersTable: <inferred>`
|
|
370
|
+
- `const shopOrderStatusHistoryTable: <inferred>`
|
|
371
|
+
- `const shopPaymentsTable: <inferred>`
|
|
372
|
+
- `type ShopPaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'cancelled'`
|
|
373
|
+
- `const shopProductsTable: <inferred>`
|
|
374
|
+
- `const shopProductVariantsTable: <inferred>`
|
|
375
|
+
- `const shopRefundsTable: <inferred>`
|
|
376
|
+
- `type ShopRefundStatus = 'pending' | 'succeeded' | 'failed'`
|
|
377
|
+
- `const shopShippingMethodsTable: <inferred>`
|
|
378
|
+
- `const shopStockReservationsTable: <inferred>`
|
|
379
|
+
- `const shopWebhookEventsTable: <inferred>`
|
|
380
|
+
|
|
381
|
+
### `includio-cms/auth-schema`
|
|
382
|
+
|
|
383
|
+
- `const account: <inferred>`
|
|
384
|
+
- `const accountRelations: <inferred>`
|
|
385
|
+
- `const invitation: <inferred>`
|
|
386
|
+
- `const session: <inferred>`
|
|
387
|
+
- `const sessionRelations: <inferred>`
|
|
388
|
+
- `const user: <inferred>`
|
|
389
|
+
- `const userRelations: <inferred>`
|
|
390
|
+
- `const verification: <inferred>`
|
|
391
|
+
|
|
339
392
|
### `includio-cms/shop`
|
|
340
393
|
|
|
341
394
|
- `interface CarrierAdapter`
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,59 @@
|
|
|
3
3
|
All notable changes to includio-cms are documented here.
|
|
4
4
|
Generated from `src/lib/updates/` — do not edit manually.
|
|
5
5
|
|
|
6
|
+
## 0.26.0 — 2026-05-26
|
|
7
|
+
|
|
8
|
+
UI Normalization → release readiness: slug regex camelCase + S8 detail/edit + S9 fields a11y polish + S10 a11y final audit + S10b/S10c mobile responsiveness full pass (sticky first column DataTable, Dialog fullscreenMobile prop, media library Sheet drawers, entry hybrid preview drawer toggle, dashboard mobile layout flip). 43/43 mobile Playwright pass (3 viewports × 12 widoków, 0 critical axe).
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `getFieldA11yProps({ id, hasDescription, hasError, required })` (`src/lib/admin/utils/field-a11y.ts`) — buduje `aria-describedby` chain, `aria-invalid`, `aria-required` dla pól w `ui/form` (formsnap) — bridge bez breaking migracji ui/form ↔ ui/field koegzystencji z S3.
|
|
12
|
+
- `<LiveRegion>` (`src/lib/components/ui/live-region/`) — prosty primitive (`sr-only` + `role="status"` + `aria-live`) zastąpił inline duplicates w relation-field i blocks-field; gotowy do reuse.
|
|
13
|
+
- `field-renderer.svelte` propaguje `Form.Control` `props` (formsnap snippet `children({ props })`) do wszystkich field components (boolean, number, date, datetime, select, media, file, blocks, array, object, slug, seo, shop, url, relation). Dotąd tylko text/radio/checkboxes dostawały aria — reszta była niewired.
|
|
14
|
+
- Blocks field — keyboard reorder/add/remove/duplicate ogłasza przez `<LiveRegion>` ("Przeniesiono X na pozycję Y", "Dodano blok X" itp.). Block picker modal — `aria-labelledby` z Dialog.Title + `aria-live` na search results count.
|
|
15
|
+
- Slug field — live preview slugify'd wartości pod inputem (gdy user typuje wielką literą), copy button z `UseClipboard` + toast "Skopiowano slug". Description default w demo blog-post.
|
|
16
|
+
- Relation field — combobox a11y wzmocnione: `aria-busy` na Command.List podczas async search, picker dialog `Dialog.Title`/`Dialog.Description` (sr-only), reorder LiveRegion przeniesione na primitive.
|
|
17
|
+
- Media + File fields — `Dialog.Title` + `Dialog.Description` (sr-only) na picker dialogs (eliminuje bits-ui ostrzeżenie o brakujących aria-labelledby).
|
|
18
|
+
- Shop field — `aria-pressed` na price mode toggle (Netto/Brutto), `role="group"` + `aria-label` na toggle group, `aria-label="Usuń wariant N"` na trash buttons.
|
|
19
|
+
- SEO field — `aria-live="polite"` na char counter (50/60, 120/160) — SR słyszy zmianę gdy user wpisuje.
|
|
20
|
+
- Storybook fields — nowe `file.stories.svelte` (4 warianty) i `shop.stories.svelte` (4 warianty). Slug stories rozszerzone o WithPreview/ClipboardCopy. Text stories — Required wariant. Slug ma już `tags: ['autodocs']` (zdjęty `no-test`).
|
|
21
|
+
- Slugi pól, kolekcji, singles i form akceptują camelCase (`/^[a-z][a-zA-Z0-9-]*$/`). Można pisać `slug: 'siteName'` zamiast `'site-name'` i odczytywać `entry.data.siteName` bez bracket notation. Walidacja blokuje nadal PascalCase, prefix `_` i digit-leading.
|
|
22
|
+
- Helper `quoteKey()` w `src/lib/core/server/generator/utils.ts` — opakowuje slugi nie-spełniające JS identifier shape w cudzysłowy w wygenerowanym TS.
|
|
23
|
+
- Nowy węzeł layoutu `tabs`/`tab` (`src/lib/types/layout.ts`) — taby konfigurowane per kolekcja w `layout[]`, renderowane przez `LayoutRenderer` (bits-ui Tabs: `role=tab/tablist/tabpanel`, strzałki/Home/End, `aria-selected`). Wszystkie panele pozostają zamontowane (walidacja/dirty-tracking/`showWhen` działają na nieaktywnych tabach), error-summary i klik-w-preview (hybrid) automatycznie przełączają tab i fokusują pole (`activateContainingTabs`), trigger taba z błędem ma wskaźnik (kropka + tekst dla SR, nie sam kolor). Aktywny tab najwyższego poziomu utrwalany w `?tab` (deep-link, przeżywa reload). `tab` przyjmuje `fields` (płaski) lub `children` (sekcje/karty w środku); zakaz zagnieżdżonych tabów + walidacja struktury w `validateLayout`. Stary sztywny tab Content/SEO w `entry.svelte` usunięty — SEO to teraz zwykły `tab` w configu (demo blog-post).
|
|
24
|
+
- `<FormErrorSummary>` (`src/lib/admin/components/forms/`) — banner z listą błędów, anchor links scroll do `[data-field-path]`, focus pierwszego błędnego pola, `role="alert"` + `aria-live="assertive"`. Adoptowany w entry, coupon-form, shipping-method-form, shop-order-detail.
|
|
25
|
+
- `<ConfirmationDialog>` (`src/lib/admin/components/dialogs/`) — typed wrapper na bits-ui AlertDialog z destructive/default variant, default focus na Cancel (bezpieczniejszy), loading state. Zastąpił 5× `confirm()` (form-submissions, entry, shop-order-detail, coupons-list, dashboard) + dodany dla Archive entry.
|
|
26
|
+
- `<DetailPageShell>` (`src/lib/admin/components/layout/`) — wspólny layout (PageHeader + body + opcjonalny sidebar) dla coupon-edit / shipping-method-edit. Skip-link target `#detail-main`.
|
|
27
|
+
- Coupon edit form zmigrowany na sveltekit-superforms + formsnap (jak account/profile-section) — schema zod (`coupon-schema.ts`), SPA mode, error summary + per-field errors.
|
|
28
|
+
- Entry SaveIndicator: nowe stany + COGA copy (`Niezapisane zmiany`, `Zapisuję…`, `Zapisano X temu` z `formatRelativeDate` recompute co 30s, `Błąd zapisu`), `aria-atomic` + role flip alert/status. `<svelte:window>` `beforeunload` guard gdy unsaved.
|
|
29
|
+
- `<A11yHeaderBadge>` (`src/lib/admin/client/entry/header/a11y-header-badge.svelte`) — persistent warning chip w entry-header pokazujący liczbę a11y issues (images bez alt, heading hierarchy, generic link text). Reuse `validateA11y` z `a11y-validator.ts`. Strong-warning UX (B.1) — nie blokuje save, prowadzi autora. Kolumna a11y w collection-entries.svelte (S5) + persistent header badge (S10) + publish-panel sheet detail = pełna ścieżka widoczności.
|
|
30
|
+
- `scripts/lighthouse-audit.ts` (`pnpm audit:lighthouse`) — ad-hoc CLI runner po 11 URL admin (login, dashboard, collections, users, media, forms, account, maintenance, shop ×3). Lighthouse 13 + chrome-launcher + auth cookie z `e2e/.auth/admin.json`. Output `.tmp/lighthouse/<view>.json` + `summary.md`, target a11y ≥95.
|
|
31
|
+
- `e2e/admin/a11y-baseline.spec.ts` rozszerzone 4 → 14 widoków: 10 page-level (login, dashboard, collections-list, entry-edit, users-list, media-library, forms-detail, account, maintenance, user-create-dialog) + 4 shop best-effort (skip jeśli moduł nie configured). Per spec 0 critical violations enforced.
|
|
32
|
+
- TipTap link-dialog `aria-expanded` na 2 collapsible sections (Dostępność + Indeksowanie) — uzupełnia ATAG B.3 author tool a11y. FigureNodeView/image-dialog/publish-panel: `:focus-visible` fallback z `var(--ring)` outline (focus indicator widoczny zawsze, nawet gdy `:focus` zmienia tylko border-color).
|
|
33
|
+
- Publiczny `resolveSeo(entry, language?)` (`includio-cms/core`) — stabilny znormalizowany read-path nad zamrożonym kontraktem `entry.seo.*` (wartości localized spłaszczane po języku; `ogImage` przepuszczany jako string lub MediaFile) do budowy własnego `<head>` lub zasilenia komponentu `<Seo>`. `SlugField`/`SeoField`/`SeoFieldData` oznaczone `@public` + v1.0-frozen.
|
|
34
|
+
- Wewnętrzny `seoFieldDescriptor` — pojedyncze źródło prawdy kształtu pola SEO dla generatorów Zod + TS (wyjście bit-identyczne, pilnowane snapshotami i testami drift-guard). Przygotowuje przyszły plugin-rehoming SEO bez breaking change. Istniejąca niespójność Zod(required)/TS(optional) dla `description`/`ogImage` udokumentowana i zachowana 1:1 (do rozstrzygnięcia post-1.0).
|
|
35
|
+
- Mobile responsiveness full pass (S10c) — pełny mobile UX panelu admina: `DataTable` sticky first column + edge-bleed scroll wrapper (1 fix → wszystkie 8+ list pages, w tym shop), `Dialog.Content` `fullscreenMobile` prop (media/file picker + tiptap image/video dialogi), media library tags sidebar + FileDetails jako Sheet drawer na <md (`hidden md:flex` aside), entry hybrid preview Sheet drawer toggle z `IsMobile(1024)` (<lg pokazuje tylko form + floating "Podgląd" button), shop-order detail items table z `min-w-[640px]` + horizontal scroll, char counter w `text-field-wrapper` na mobile stackowany pod polem zamiast `absolute right`, EntryHeader padding + SaveIndicator text `max-sm:sr-only`, PageHeader text-scale `text-2xl sm:text-3xl lg:text-4xl`, breadcrumb truncacja middle segments `/…/` na <sm, table-toolbar search `w-full min-w-0` na mobile, tiptap toolbar separatory `hidden sm:block`, relation popover `w-[var(--bits-popover-anchor-width)] max-w-[calc(100vw-1rem)]`. Playwright `e2e/admin/mobile-responsive.spec.ts` rozszerzony o iPad portrait (768×1024) + shop-shipping view + `scrollWidth <= window.innerWidth` page-overflow assertion: 43/43 testów pass, 0 critical, 0-2 serious axe per (3 viewports × 12 widoków).
|
|
36
|
+
- Dashboard mobile layout flip (S10c follow-up) — `dashboard-page.svelte`: main wrapper `flex gap-5` → `flex flex-col gap-5 lg:flex-row` + sub-grid `grid-cols-2` → `grid-cols-1 sm:grid-cols-2` + sidebar `max-w-80 flex-1 shrink-0` → `w-full shrink-0 lg:max-w-80 lg:flex-1`. Side-by-side 2-col layout aktywowany dopiero od `lg` (1024px); poniżej stack vertically, sub-grid kolumna pojedyncza do `sm` (640px). Eliminuje cramped 2-col scroll na 375-768px.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- `runtime/types.ts` generuje poprawny TypeScript dla kebab-case slugów (np. `'published-at'?: string` zamiast gołego `published-at?: string`, który był syntaks błędem). Naprawione w `generateTsTypeFromFields`, `generateFlatTsTypeFromFields`, `generateInlineBlockTypeString`, object/blocks variants oraz form fields generator.
|
|
40
|
+
- Shop order detail: `bg-red-50` / `bg-green-50` zamienione na tokenized `bg-destructive-bg` / `bg-success-bg` z `role="alert"`/`role="status"`. Status form ma teraz SaveIndicator + FormErrorSummary.
|
|
41
|
+
- Shipping-method form: `<fieldset>/<legend>` na payment methods (poprawne grouping dla SR), `aria-live="polite"` na carrier config panel, FormErrorSummary zamiast `bg-red-50` div, `text-amber-700` zamienione na `text-warning` token.
|
|
42
|
+
- Coupons list: delete dialog A11y (focus trap, ESC, return focus) zamiast browser `confirm()`.
|
|
43
|
+
- Form submissions bulk delete: AlertDialog zamiast `confirm()`, plural PL forms ("3 zgłoszenia" vs "5 zgłoszeń").
|
|
44
|
+
- Dashboard delete-orphaned: AlertDialog z liczbą wpisów w description zamiast `confirm()`.
|
|
45
|
+
- `pnpm demo` seed (`scripts/seed-demo.ts`) — twarda bramka walidacji: każdy `entry_version` przed surowym INSERT-em przechodzi przez realny schemat CMS (`generateZodSchemaFromFields(..., { localized: false })` — ten sam oracle co admin/publish). Niezgodne dane przerywają seed z czytelnym `collection/lang/entry: path: message`. Dane demo doprowadzone do zgodności: blog-post `title` bez nierealnego `minLength: 50` (+ usunięte śmieciowe debugowe pole `test`/`dupa` z kolekcji), media jako UUID-string zamiast `{id,url,alt}` (cover/thumbnail/image/logo/favicon/photo), daty pełne ISO, dołożone wymagane obiekty `seo`, `url` jako obiekt, bloki z `_slug` zamiast `_type`, `localizedTags`/`links` w kształcie schematu.
|
|
46
|
+
- Lista entries w kolekcji pokazuje "(bez tytułu)"/"(untitled)" zamiast surowego UUID gdy wpis nie ma tytułu — spójne z breadcrumbem na ekranie edycji. Wspólny helper `getCollectionEntryDisplayLabel` (`src/lib/admin/utils/entryLabel.ts`) używany przez list/grid i breadcrumb (fallback wykrywany po `language === null`, odporny na tytuł = id).
|
|
47
|
+
- Slug first-class: podgląd URL wpisu w adminie (`collection-entries.svelte`) odhardkodowany z wymogu pola typu `seo` — kolekcja ze standalone polem slug + skonfigurowanym `slugField` pokazuje URL; bez `slugField`/`pathTemplate` świadomie brak `_url` (np. kolekcje atrybutów), bez błędu. Wydzielony czysty resolver `slugPath.ts` (bez `getCMS`) współdzielony przez admin client i server.
|
|
48
|
+
|
|
49
|
+
### Breaking
|
|
50
|
+
- **Entry autosave usunięty** — wcześniej 30s timeout + Ctrl/Cmd+S manual. Teraz tylko manual save (button "Zapisz szkic" zawsze widoczny + Ctrl/Cmd+S shortcut). Powód: stara impl mogła w niejasnych sytuacjach modyfikować published data; bezpieczniejsza re-introdukcja z draft-only guard zaplanowana w ROADMAP backlog. Migracja: użytkownicy muszą explicit zapisać przed nawigacją (jest `beforeunload` guard).
|
|
51
|
+
- EntryHeader props: nowy `lastSavedAt?: Date | null` (default `null`). Niezbędny dla SaveIndicator "Zapisano X temu". Konsumenci niestandardowi (entry-header-story-demo, custom integracje) muszą propagować z entry.svelte.
|
|
52
|
+
- EntryForm props: usunięty hardcoded podział Content/SEO (`tabFilter` nigdy nie trafił do release'u — zastąpiony węzłem layoutu `tabs`). Grupowanie w taby = teraz config `layout[]`. Kolekcje bez `tabs` bez zmian; SEO w demo blog-post wyrażone jako `tab`. Dodany prop `errorPaths?: Set<string>` (EntryForm/LayoutRenderer) do wskaźnika błędu na tabie.
|
|
53
|
+
- `coupon-form.svelte` przepisane od zera na sveltekit-superforms — props identyczne (`initial`, `submitLabel`, `onSubmit`, `onCancel`), ale wewnętrzny mechanizm walidacji zmieniony (zod schema zamiast hand-rolled). Call-sites bez zmian.
|
|
54
|
+
|
|
55
|
+
### Notes
|
|
56
|
+
|
|
57
|
+
V1-DECISIONS.md sekcja "Sesja 8" zawiera pełny audit decyzji + grep gates. Pełna superForm migracja shipping-method-form odłożona do backlogu (skomplikowany state: net/gross toggle + dynamic carrier + multi-lang record). Storybook entry-page story też w backlogu (wymaga mock setRemotes + RawEntry fixtures — robione w S10 a11y sweep). VoiceOver smoke test (manual user-delegated) — checklist w `V1-UI-AUDIT.md` sekcja "VoiceOver smoke (manual)". Kompatybilność z istniejącymi danymi: pełna (zero schema changes; coupon zachowuje stary kontrakt API).
|
|
58
|
+
|
|
6
59
|
## 0.25.0 — 2026-05-06
|
|
7
60
|
|
|
8
61
|
Faza 11.5 — Shop polish. Stripe payment adapter (Checkout Session flow z native webhook signature verify), refund infrastructure (full + partial, cross-adapter Stripe + PayU), webhook idempotency table (`shop_webhook_events` z UNIQUE(provider, event_id)), coupons (% / fixed PLN, expiresAt, maxUses, minOrderAmount, OCC race-safe redemption), low-stock email alert (per-product `lowStockThreshold`), order export CSV w admin, default email templates rozszerzone o `refunded` status, SDK `applyCoupon`/`removeCoupon` + JSDoc body + `@public` tagi, pełna dokumentacja shopa (DOCS.md + adapter guides + cURL examples + Stripe/Coupons/Refund pages). Shop = `@public` w v1.0.
|
package/DOCS.md
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# includio-cms
|
|
2
2
|
|
|
3
3
|
[](https://github.com/includio/includio-cms/actions/workflows/ci.yml)
|
|
4
|
+
[](https://includio.github.io/includio-cms/)
|
|
4
5
|
|
|
5
6
|
A headless CMS built for SvelteKit. Type-safe, extensible, with a modern admin interface and pluggable adapters for database, files, email, and AI.
|
|
6
7
|
|
|
@@ -211,6 +212,7 @@ Global flags: `--help, -h` and `--version, -v`.
|
|
|
211
212
|
- [Changelog](./CHANGELOG.md)
|
|
212
213
|
- [Roadmap](./ROADMAP.md)
|
|
213
214
|
- [Known risks](./KNOWN-RISKS.md)
|
|
215
|
+
- [Storybook](https://includio.github.io/includio-cms/) — visual reference for all 86 UI components (designer source-of-truth)
|
|
214
216
|
|
|
215
217
|
## For AI assistants
|
|
216
218
|
|
package/ROADMAP.md
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
- [x] `[chore]` `[P1]` Faza 11 — Performance Pass (0.24.0): N+1 elimination (`getImageStyle` batch IN query, `getRawEntries` batch entry versions), Sharp srcset `Promise.allSettled` (one timeout doesn't kill batch), background maintenance in-process lock verified + tested, bench infra (`pnpm bench` + representative benchmarks), lazy adapter imports verified <!-- files: src/lib/core/server/media/styles/operations/, src/lib/core/server/fields/resolveImageFields.ts, src/lib/core/server/entries/operations/get.ts, src/lib/db-postgres/index.ts, src/lib/core/server/media/operations/backgroundMaintenance.spec.ts, src/lib/updates/0.24.0/ -->
|
|
21
21
|
- [x] `[feature]` `[P0]` Faza 11.5 — Shop polish (0.25.0): Stripe adapter (Checkout Session, sig verify, idempotency), refund infra (full + partial cross-adapter), webhook idempotency table (`shop_webhook_events`), coupons (% / fixed, expiresAt, maxUses, minOrder), low-stock email alert, order export CSV, default email templates (PL/EN), SDK JSDoc + `@public`, pełna dokumentacja shopa <!-- files: src/lib/shop/adapters/stripe/, src/lib/shop/server/{refund,coupons}.ts, src/lib/db-postgres/schema/shop/{refunds,webhookEvents,coupons,couponRedemptions}.ts, src/lib/admin/client/shop/, src/lib/updates/0.25.0/ -->
|
|
22
22
|
- [ ] `[fix]` `[P1]` Select field — `defaultValue` propagacja do zod schema (full repro: `ideas/post-v1/select-field-defaultvalue-bug.md`); fix planowany w Fazie 12 (RC)
|
|
23
|
+
- [x] `[chore]` `[P2]` Demo orchestrator — `pnpm demo` startuje czystą instancję na tmpfs DB :5436, seeduje 12 blog postów / 6 projektów / 5 contact submissions / 8 gradient PNG-ów, włącza `demo-site` frontend pod `/demo-site`, każdy start = czysty stan <!-- files: scripts/demo.ts, scripts/seed-demo.ts, src/routes/demo-site/, docker-compose.yml, .env.demo -->
|
|
24
|
+
- [x] `[feature]` `[P1]` Slug first-class + SEO v1.0 freeze (0.26.0) — `resolveSeo` public (`includio-cms/core`), `seoFieldDescriptor` SSOT (Zod+TS drift-guard), admin URL un-hardcode (`slugPath.ts` pure resolver, no `seo`-field requirement), `SlugField`/`SeoField`/`SeoFieldData` `@public` v1.0-frozen <!-- files: src/lib/core/fields/slugPath.ts, src/lib/core/fields/seoFieldDescriptor.ts, src/lib/core/fields/resolveSeo.ts, src/lib/types/fields.ts, src/lib/admin/client/collection/collection-entries.svelte, src/lib/updates/0.26.0/ -->
|
|
23
25
|
|
|
24
26
|
## v1.x — Post-v1.0 deferred
|
|
25
27
|
|
|
@@ -45,6 +47,10 @@
|
|
|
45
47
|
|
|
46
48
|
## Backlog
|
|
47
49
|
|
|
50
|
+
- [ ] `[feature]` `[P2]` Date/datetime field — przebudowa na shadcn-svelte (bits-ui Calendar/DatePicker) zamiast natywnego inputu. Zgłoszone w QA Etap 5a (4/5); funkcjonalnie OK, odłożone jako osobny redesign pola daty. <!-- files: src/lib/admin/components/fields/date-field.svelte, datetime-field.svelte -->
|
|
51
|
+
- [ ] `[feature]` `[P1]` Re-introduce entry autosave with strict draft-only guard (opt-in via `cms.config.ts`, never touch published versions, debounced + visual countdown). Removed in 0.26.0 / S8 because old impl could touch published data ambiguously.
|
|
52
|
+
- [ ] `[feature]` `[P2]` Migrate `shipping-method-form` na sveltekit-superforms + formsnap (S8 zostawił hand-rolled validation + FormErrorSummary; pełna migracja wymaga schema dla multi-lang record + dynamic carrier config + price net/gross toggle).
|
|
53
|
+
- [ ] `[feature]` `[P2]` Storybook story dla `entry-page` (Default/Saving/Saved/Error/Draft/WithErrors/Confirmation) — wymaga mock context: `setRemotes` (5 commands), `setBreadcrumbs`, `setContentLanguage`, RawEntry/DbEntryVersion fixtures. S8 odłożone do S10 a11y sweep.
|
|
48
54
|
- [ ] `[feature]` `[P1]` Server-side pagination API (formalize 0.1.0 fix)
|
|
49
55
|
- [x] `[feature]` `[P1]` Improved type generation — union types for select/checkboxes, defaultValue makes fields non-optional <!-- files: src/lib/core/server/generator/ -->
|
|
50
56
|
- [ ] `[feature]` `[P1]` Proper filtering API (SQL-level, not JS post-query)
|
|
@@ -24,7 +24,8 @@ export const accountLang = {
|
|
|
24
24
|
strengthMedium: 'Średnie',
|
|
25
25
|
strengthStrong: 'Silne',
|
|
26
26
|
strengthVeryStrong: 'Bardzo silne',
|
|
27
|
-
strengthLabel: 'Siła hasła'
|
|
27
|
+
strengthLabel: 'Siła hasła',
|
|
28
|
+
generatePassword: 'Wygeneruj hasło'
|
|
28
29
|
},
|
|
29
30
|
language: {
|
|
30
31
|
title: 'Język interfejsu',
|
|
@@ -75,7 +76,8 @@ export const accountLang = {
|
|
|
75
76
|
strengthMedium: 'Medium',
|
|
76
77
|
strengthStrong: 'Strong',
|
|
77
78
|
strengthVeryStrong: 'Very strong',
|
|
78
|
-
strengthLabel: 'Password strength'
|
|
79
|
+
strengthLabel: 'Password strength',
|
|
80
|
+
generatePassword: 'Generate password'
|
|
79
81
|
},
|
|
80
82
|
language: {
|
|
81
83
|
title: 'Interface language',
|
|
@@ -88,10 +88,10 @@
|
|
|
88
88
|
|
|
89
89
|
<!-- Email readonly -->
|
|
90
90
|
<div class="flex flex-col gap-1">
|
|
91
|
-
|
|
92
|
-
<label class="text-sm font-medium">{lang.profile.email}</label>
|
|
91
|
+
<label for="account-email" class="text-sm font-medium">{lang.profile.email}</label>
|
|
93
92
|
<div class="acct-input-wrap">
|
|
94
93
|
<Input
|
|
94
|
+
id="account-email"
|
|
95
95
|
type="email"
|
|
96
96
|
value={$session.data.user.email}
|
|
97
97
|
readonly
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
import { accountLang } from './lang.js';
|
|
10
10
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
11
11
|
import { authClient } from '../../auth-client.js';
|
|
12
|
+
import { errorMessages, pickError } from '../../i18n/errors.js';
|
|
13
|
+
import { generatePassword } from '../../shared/password-generate.js';
|
|
12
14
|
import { toast } from 'svelte-sonner';
|
|
13
15
|
|
|
14
16
|
const interfaceLanguage = useInterfaceLanguage();
|
|
@@ -31,7 +33,9 @@
|
|
|
31
33
|
newPassword: form.data.newPassword
|
|
32
34
|
});
|
|
33
35
|
if (error) {
|
|
34
|
-
toast.error(
|
|
36
|
+
toast.error(
|
|
37
|
+
error.message || pickError(errorMessages.server.saveFailed, interfaceLanguage.current),
|
|
38
|
+
);
|
|
35
39
|
} else {
|
|
36
40
|
toast.success(lang.security.passwordUpdated);
|
|
37
41
|
$passwordFormData.currentPassword = '';
|
|
@@ -73,6 +77,14 @@
|
|
|
73
77
|
return labels[strength.level];
|
|
74
78
|
});
|
|
75
79
|
|
|
80
|
+
function handleGeneratePassword() {
|
|
81
|
+
const pw = generatePassword();
|
|
82
|
+
$passwordFormData.newPassword = pw;
|
|
83
|
+
$passwordFormData.confirmPassword = pw;
|
|
84
|
+
showNew = true;
|
|
85
|
+
showConfirm = true;
|
|
86
|
+
}
|
|
87
|
+
|
|
76
88
|
</script>
|
|
77
89
|
|
|
78
90
|
<!-- Password Card -->
|
|
@@ -150,9 +162,20 @@
|
|
|
150
162
|
{lang.security.strengthLabel}: {strengthLabel}
|
|
151
163
|
</p>
|
|
152
164
|
{/if}
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
165
|
+
<div class="mt-1 flex items-center justify-between gap-2">
|
|
166
|
+
<p id="pw-hint" class="text-text-light text-xs">
|
|
167
|
+
{lang.security.passwordHint}
|
|
168
|
+
</p>
|
|
169
|
+
<Button
|
|
170
|
+
variant="link"
|
|
171
|
+
size="sm"
|
|
172
|
+
type="button"
|
|
173
|
+
class="h-auto shrink-0 p-0 text-xs"
|
|
174
|
+
onclick={handleGeneratePassword}
|
|
175
|
+
>
|
|
176
|
+
{lang.security.generatePassword}
|
|
177
|
+
</Button>
|
|
178
|
+
</div>
|
|
156
179
|
{/snippet}
|
|
157
180
|
</Form.Control>
|
|
158
181
|
<Form.FieldErrors class="text-sm text-red-500" />
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as Card from '../../../components/ui/card/index.js';
|
|
3
3
|
import { accountLang } from './lang.js';
|
|
4
4
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
5
|
-
import { toLocaleCode } from '../../utils/
|
|
5
|
+
import { toLocaleCode } from '../../utils/formatters.js';
|
|
6
6
|
import { authClient } from '../../auth-client.js';
|
|
7
7
|
import { toast } from 'svelte-sonner';
|
|
8
8
|
import Button from '../../../components/ui/button/button.svelte';
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<Sidebar.Provider style="--sidebar-width: 16rem; --header-height: calc(var(--spacing) * 13);">
|
|
27
27
|
<AppSidebar />
|
|
28
28
|
|
|
29
|
-
<Sidebar.Inset class="h-screen overflow-hidden">
|
|
29
|
+
<Sidebar.Inset id="main-content" tabindex={-1} class="h-screen overflow-hidden outline-none">
|
|
30
30
|
<SiteHeader />
|
|
31
31
|
<div class="flex grow flex-col overflow-auto">
|
|
32
32
|
{@render children()}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import RecentActivity from '../../components/dashboard/recent-activity.svelte';
|
|
7
7
|
import A11yGauge from '../../components/dashboard/a11y-gauge.svelte';
|
|
8
8
|
import TipOfTheDay from '../../components/dashboard/tip-of-the-day.svelte';
|
|
9
|
+
import ConfirmationDialog from '../../components/dialogs/confirmation-dialog.svelte';
|
|
9
10
|
import { sidebarLang } from '../../components/layout/lang.js';
|
|
10
11
|
import { getBreadcrumbs } from '../../state/breadcrumbs.svelte.js';
|
|
11
12
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
@@ -20,6 +21,23 @@
|
|
|
20
21
|
let orphanedEntries = $state<OrphanedEntry[]>([]);
|
|
21
22
|
let loadingOrphaned = $state(true);
|
|
22
23
|
let deletingOrphaned = $state(false);
|
|
24
|
+
let confirmDeleteOpen = $state(false);
|
|
25
|
+
|
|
26
|
+
const confirmText: Record<
|
|
27
|
+
InterfaceLanguage,
|
|
28
|
+
{ title: string; description: (n: number) => string }
|
|
29
|
+
> = {
|
|
30
|
+
pl: {
|
|
31
|
+
title: 'Usunąć osierocone wpisy?',
|
|
32
|
+
description: (n) =>
|
|
33
|
+
`${n} ${n === 1 ? 'wpis zostanie' : 'wpisy zostaną'} trwale usunięty z bazy. Tej akcji nie cofniesz.`
|
|
34
|
+
},
|
|
35
|
+
en: {
|
|
36
|
+
title: 'Delete orphaned entries?',
|
|
37
|
+
description: (n) =>
|
|
38
|
+
`${n} ${n === 1 ? 'entry' : 'entries'} will be permanently removed. This cannot be undone.`
|
|
39
|
+
}
|
|
40
|
+
};
|
|
23
41
|
|
|
24
42
|
async function fetchOrphanedEntries() {
|
|
25
43
|
try {
|
|
@@ -34,13 +52,11 @@
|
|
|
34
52
|
}
|
|
35
53
|
}
|
|
36
54
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
en: 'Are you sure you want to delete these entries? This cannot be undone.'
|
|
41
|
-
};
|
|
42
|
-
if (!confirm(msg[interfaceLanguage.current])) return;
|
|
55
|
+
function deleteOrphaned() {
|
|
56
|
+
confirmDeleteOpen = true;
|
|
57
|
+
}
|
|
43
58
|
|
|
59
|
+
async function performDeleteOrphaned() {
|
|
44
60
|
deletingOrphaned = true;
|
|
45
61
|
try {
|
|
46
62
|
const res = await fetch('/admin/api/orphaned', { method: 'DELETE' });
|
|
@@ -67,6 +83,14 @@
|
|
|
67
83
|
});
|
|
68
84
|
</script>
|
|
69
85
|
|
|
86
|
+
<ConfirmationDialog
|
|
87
|
+
bind:open={confirmDeleteOpen}
|
|
88
|
+
title={confirmText[interfaceLanguage.current].title}
|
|
89
|
+
description={confirmText[interfaceLanguage.current].description(orphanedEntries.length)}
|
|
90
|
+
loading={deletingOrphaned}
|
|
91
|
+
onConfirm={performDeleteOrphaned}
|
|
92
|
+
/>
|
|
93
|
+
|
|
70
94
|
<main class="dash-main">
|
|
71
95
|
{#if !loadingOrphaned}
|
|
72
96
|
<OrphanedEntriesNotice
|
|
@@ -78,9 +102,9 @@
|
|
|
78
102
|
|
|
79
103
|
<WelcomeHeader />
|
|
80
104
|
|
|
81
|
-
<div class="flex gap-5">
|
|
82
|
-
<div class="flex-1">
|
|
83
|
-
<div class="grid grid-cols-
|
|
105
|
+
<div class="flex flex-col gap-5 lg:flex-row">
|
|
106
|
+
<div class="min-w-0 flex-1">
|
|
107
|
+
<div class="grid grid-cols-1 gap-5 sm:grid-cols-2">
|
|
84
108
|
<RecentEntries />
|
|
85
109
|
<FormSubmissionsWidget />
|
|
86
110
|
</div>
|
|
@@ -88,7 +112,7 @@
|
|
|
88
112
|
<RecentActivity />
|
|
89
113
|
</div>
|
|
90
114
|
</div>
|
|
91
|
-
<div class="max-w-80 flex-1
|
|
115
|
+
<div class="w-full shrink-0 lg:max-w-80 lg:flex-1">
|
|
92
116
|
<A11yGauge />
|
|
93
117
|
<div class="mt-5">
|
|
94
118
|
<TipOfTheDay />
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { tick, type Snippet } from 'svelte';
|
|
2
3
|
import Archive from '@tabler/icons-svelte/icons/archive';
|
|
3
4
|
import ArchiveOff from '@tabler/icons-svelte/icons/archive-off';
|
|
4
5
|
import Trash from '@tabler/icons-svelte/icons/trash';
|
|
@@ -10,93 +11,134 @@
|
|
|
10
11
|
|
|
11
12
|
type Props = {
|
|
12
13
|
selectedCount: number;
|
|
13
|
-
onArchive
|
|
14
|
+
onArchive?: () => void;
|
|
14
15
|
onDelete?: () => void;
|
|
15
16
|
onClear: () => void;
|
|
16
17
|
onRestore?: () => void;
|
|
18
|
+
actions?: Snippet;
|
|
17
19
|
};
|
|
18
20
|
|
|
19
|
-
let { selectedCount, onArchive, onDelete, onClear, onRestore }: Props = $props();
|
|
21
|
+
let { selectedCount, onArchive, onDelete, onClear, onRestore, actions }: Props = $props();
|
|
20
22
|
|
|
21
23
|
const interfaceLanguage = useInterfaceLanguage();
|
|
22
24
|
|
|
23
|
-
const lang: Record<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
const lang: Record<
|
|
26
|
+
InterfaceLanguage,
|
|
27
|
+
{
|
|
28
|
+
selected: (n: number) => string;
|
|
29
|
+
archive: string;
|
|
30
|
+
restore: string;
|
|
31
|
+
delete: string;
|
|
32
|
+
bulkActions: string;
|
|
33
|
+
clearSelection: string;
|
|
34
|
+
}
|
|
35
|
+
> = {
|
|
29
36
|
en: {
|
|
30
37
|
selected: (n) => `${n} selected`,
|
|
31
38
|
archive: 'Archive',
|
|
32
39
|
restore: 'Restore',
|
|
33
|
-
delete: 'Delete'
|
|
40
|
+
delete: 'Delete',
|
|
41
|
+
bulkActions: 'Bulk actions',
|
|
42
|
+
clearSelection: 'Clear selection'
|
|
34
43
|
},
|
|
35
44
|
pl: {
|
|
36
45
|
selected: (n) => `Zaznaczono: ${n}`,
|
|
37
46
|
archive: 'Archiwizuj',
|
|
38
47
|
restore: 'Przywróć',
|
|
39
|
-
delete: 'Usuń'
|
|
48
|
+
delete: 'Usuń',
|
|
49
|
+
bulkActions: 'Akcje masowe',
|
|
50
|
+
clearSelection: 'Wyczyść zaznaczenie'
|
|
40
51
|
}
|
|
41
52
|
};
|
|
42
53
|
|
|
43
54
|
const t = $derived(lang[interfaceLanguage.current]);
|
|
55
|
+
|
|
56
|
+
let toolbarRef = $state<HTMLElement | null>(null);
|
|
57
|
+
let prevCount = 0;
|
|
58
|
+
|
|
59
|
+
$effect(() => {
|
|
60
|
+
const count = selectedCount;
|
|
61
|
+
if (prevCount === 0 && count > 0) {
|
|
62
|
+
tick().then(() => {
|
|
63
|
+
const first = toolbarRef?.querySelector<HTMLElement>('button:not([aria-label])');
|
|
64
|
+
first?.focus();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
prevCount = count;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
function handleKeydown(e: KeyboardEvent) {
|
|
71
|
+
if (e.key === 'Escape') {
|
|
72
|
+
e.stopPropagation();
|
|
73
|
+
onClear();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
44
76
|
</script>
|
|
45
77
|
|
|
46
78
|
{#if selectedCount > 0}
|
|
47
79
|
<div
|
|
80
|
+
bind:this={toolbarRef}
|
|
48
81
|
class="fixed bottom-6 left-1/2 z-50 -translate-x-1/2"
|
|
49
82
|
transition:fly={{ y: 40, duration: 200 }}
|
|
50
|
-
role="
|
|
51
|
-
aria-
|
|
83
|
+
role="toolbar"
|
|
84
|
+
aria-label={t.bulkActions}
|
|
85
|
+
tabindex="-1"
|
|
86
|
+
onkeydown={handleKeydown}
|
|
52
87
|
>
|
|
53
88
|
<div
|
|
54
|
-
class="flex items-center gap-3 rounded-xl bg-plum-darker px-5 py-3 text-white shadow-xl"
|
|
89
|
+
class="flex max-w-[calc(100vw-2rem)] flex-wrap items-center justify-center gap-3 rounded-xl bg-plum-darker px-5 py-3 text-white shadow-xl"
|
|
55
90
|
>
|
|
56
|
-
<span class="text-sm font-medium">{t.selected(selectedCount)}</span>
|
|
91
|
+
<span class="text-sm font-medium" aria-hidden="true">{t.selected(selectedCount)}</span>
|
|
57
92
|
|
|
58
|
-
<div class="h-5 w-px bg-white/20"></div>
|
|
93
|
+
<div class="h-5 w-px bg-white/20" aria-hidden="true"></div>
|
|
59
94
|
|
|
60
95
|
{#if onRestore}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
{:else}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
96
|
+
<Button
|
|
97
|
+
variant="ghost"
|
|
98
|
+
size="sm"
|
|
99
|
+
class="text-white hover:bg-white/10 hover:text-white"
|
|
100
|
+
onclick={onRestore}
|
|
101
|
+
>
|
|
102
|
+
<ArchiveOff class="mr-1.5 size-3.5" />
|
|
103
|
+
{t.restore}
|
|
104
|
+
</Button>
|
|
105
|
+
{:else if onArchive}
|
|
106
|
+
<Button
|
|
107
|
+
variant="ghost"
|
|
108
|
+
size="sm"
|
|
109
|
+
class="text-white hover:bg-white/10 hover:text-white"
|
|
110
|
+
onclick={onArchive}
|
|
111
|
+
>
|
|
112
|
+
<Archive class="mr-1.5 size-3.5" />
|
|
113
|
+
{t.archive}
|
|
114
|
+
</Button>
|
|
80
115
|
{/if}
|
|
81
116
|
{#if onDelete}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
117
|
+
<Button
|
|
118
|
+
variant="ghost"
|
|
119
|
+
size="sm"
|
|
120
|
+
class="text-white border border-white/20 hover:bg-white/10 hover:text-white"
|
|
121
|
+
onclick={onDelete}
|
|
122
|
+
>
|
|
123
|
+
<Trash class="mr-1.5 size-3.5" />
|
|
124
|
+
{t.delete}
|
|
125
|
+
</Button>
|
|
126
|
+
{/if}
|
|
127
|
+
{#if actions}
|
|
128
|
+
{@render actions()}
|
|
91
129
|
{/if}
|
|
92
130
|
|
|
93
131
|
<button
|
|
132
|
+
type="button"
|
|
94
133
|
class="ml-1 rounded-md p-1 text-white/60 hover:bg-white/10 hover:text-white"
|
|
95
134
|
onclick={onClear}
|
|
96
|
-
aria-label=
|
|
135
|
+
aria-label={t.clearSelection}
|
|
97
136
|
>
|
|
98
137
|
<X class="size-4" />
|
|
99
138
|
</button>
|
|
100
139
|
</div>
|
|
101
140
|
</div>
|
|
141
|
+
<div aria-live="polite" aria-atomic="true" class="sr-only">
|
|
142
|
+
{t.selected(selectedCount)}
|
|
143
|
+
</div>
|
|
102
144
|
{/if}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { type Snippet } from 'svelte';
|
|
1
2
|
type Props = {
|
|
2
3
|
selectedCount: number;
|
|
3
|
-
onArchive
|
|
4
|
+
onArchive?: () => void;
|
|
4
5
|
onDelete?: () => void;
|
|
5
6
|
onClear: () => void;
|
|
6
7
|
onRestore?: () => void;
|
|
8
|
+
actions?: Snippet;
|
|
7
9
|
};
|
|
8
10
|
declare const BulkActionsBar: import("svelte").Component<Props, {}, "">;
|
|
9
11
|
type BulkActionsBar = ReturnType<typeof BulkActionsBar>;
|