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,18 +1,110 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import * as Dialog from '../../../components/ui/dialog/index.js';
|
|
3
3
|
import { onMount } from 'svelte';
|
|
4
|
-
import
|
|
5
|
-
import { buttonVariants } from '../../../components/ui/button/button.svelte';
|
|
6
|
-
import MediaLibrary from '../media/media-library.svelte';
|
|
4
|
+
import Button from '../../../components/ui/button/button.svelte';
|
|
7
5
|
import type { FileField } from '../../../types/fields.js';
|
|
8
|
-
import
|
|
6
|
+
import type { InterfaceLanguage } from '../../../types/languages.js';
|
|
7
|
+
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
8
|
+
import Plus from '@tabler/icons-svelte/icons/plus';
|
|
9
|
+
import X from '@tabler/icons-svelte/icons/x';
|
|
10
|
+
import ChevronLeft from '@tabler/icons-svelte/icons/chevron-left';
|
|
11
|
+
import ChevronRight from '@tabler/icons-svelte/icons/chevron-right';
|
|
12
|
+
import AlertTriangle from '@tabler/icons-svelte/icons/alert-triangle';
|
|
13
|
+
import FileMiniature from '../media/file/file-miniature.svelte';
|
|
14
|
+
import { getRemotes } from '../../../sveltekit/index.js';
|
|
15
|
+
import MediaSelector from '../media/media-selector.svelte';
|
|
16
|
+
import type { MediaFile } from '../../../types/media.js';
|
|
17
|
+
import { formatFileSize, getFileExtension } from '../../utils/fileDisplay.js';
|
|
18
|
+
|
|
19
|
+
const lang: Record<
|
|
20
|
+
InterfaceLanguage,
|
|
21
|
+
{
|
|
22
|
+
selectFile: string;
|
|
23
|
+
addFile: string;
|
|
24
|
+
remove: string;
|
|
25
|
+
change: string;
|
|
26
|
+
of: string;
|
|
27
|
+
missingFile: string;
|
|
28
|
+
removeAria: string;
|
|
29
|
+
}
|
|
30
|
+
> = {
|
|
31
|
+
pl: {
|
|
32
|
+
selectFile: 'Wybierz plik',
|
|
33
|
+
addFile: 'Dodaj plik',
|
|
34
|
+
remove: 'Usuń',
|
|
35
|
+
change: 'Zmień',
|
|
36
|
+
of: 'z',
|
|
37
|
+
missingFile: 'Brakujący plik',
|
|
38
|
+
removeAria: 'Usuń plik'
|
|
39
|
+
},
|
|
40
|
+
en: {
|
|
41
|
+
selectFile: 'Select file',
|
|
42
|
+
addFile: 'Add file',
|
|
43
|
+
remove: 'Remove',
|
|
44
|
+
change: 'Change',
|
|
45
|
+
of: 'of',
|
|
46
|
+
missingFile: 'Missing file',
|
|
47
|
+
removeAria: 'Remove file'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const interfaceLanguage = useInterfaceLanguage();
|
|
52
|
+
const remotes = getRemotes();
|
|
53
|
+
|
|
54
|
+
let currentIndex = $state(0);
|
|
55
|
+
let dialogOpen = $state(false);
|
|
56
|
+
|
|
57
|
+
function openPicker() {
|
|
58
|
+
dialogOpen = true;
|
|
59
|
+
}
|
|
9
60
|
|
|
10
61
|
type Props = {
|
|
11
62
|
field: FileField;
|
|
12
63
|
value: string | string[] | undefined;
|
|
13
64
|
};
|
|
14
65
|
|
|
15
|
-
let { field, value = $bindable()
|
|
66
|
+
let { field, value = $bindable() }: Props = $props();
|
|
67
|
+
|
|
68
|
+
// Single-file state: fetch MediaFile via a plain fetch inside an $effect instead of
|
|
69
|
+
// `$derived(remotes.getFileById(value))`. Reason: wrapping the remote query in a
|
|
70
|
+
// $derived couples its lifecycle to the derivation's refcounting — rapid toggling
|
|
71
|
+
// of value ('' → id) around dialog unmount triggered "query instance is no longer
|
|
72
|
+
// active" errors. Wzorzec z media-field.
|
|
73
|
+
let singleFile = $state<MediaFile | null>(null);
|
|
74
|
+
let singleFileReady = $state(false);
|
|
75
|
+
$effect(() => {
|
|
76
|
+
const v = value;
|
|
77
|
+
if (typeof v !== 'string' || !v) {
|
|
78
|
+
singleFile = null;
|
|
79
|
+
singleFileReady = true;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
singleFileReady = false;
|
|
83
|
+
let cancelled = false;
|
|
84
|
+
(async () => {
|
|
85
|
+
try {
|
|
86
|
+
const data = await remotes.getFileById(v);
|
|
87
|
+
if (!cancelled) {
|
|
88
|
+
singleFile = data as MediaFile;
|
|
89
|
+
singleFileReady = true;
|
|
90
|
+
}
|
|
91
|
+
} catch {
|
|
92
|
+
if (!cancelled) {
|
|
93
|
+
singleFile = null;
|
|
94
|
+
singleFileReady = true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
})();
|
|
98
|
+
return () => {
|
|
99
|
+
cancelled = true;
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const mFilesQuery = $derived(
|
|
104
|
+
Array.isArray(value) && value.length > 0
|
|
105
|
+
? remotes.getMediaFiles({ data: { ids: value as string[] } })
|
|
106
|
+
: null
|
|
107
|
+
);
|
|
16
108
|
|
|
17
109
|
onMount(() => {
|
|
18
110
|
if (value === undefined) {
|
|
@@ -21,33 +113,255 @@
|
|
|
21
113
|
});
|
|
22
114
|
</script>
|
|
23
115
|
|
|
24
|
-
{#
|
|
25
|
-
<
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
<Dialog.Content class="max-h-[80vh] w-[80vw] !max-w-none overflow-y-scroll">
|
|
30
|
-
<MediaLibrary bind:selected={value} multiple={field.multiple} accept={field.accept} />
|
|
31
|
-
</Dialog.Content>
|
|
32
|
-
</Dialog.Root>
|
|
116
|
+
{#snippet filePreview(file: MediaFile)}
|
|
117
|
+
<div class="aspect-square w-full overflow-hidden rounded-2xl border">
|
|
118
|
+
<FileMiniature {file} />
|
|
119
|
+
</div>
|
|
120
|
+
{/snippet}
|
|
33
121
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
122
|
+
{#snippet missingPlaceholder()}
|
|
123
|
+
<div
|
|
124
|
+
class="flex aspect-square w-full flex-col items-center justify-center gap-2 rounded-2xl border-2 border-dashed border-warning/50 bg-warning/5 p-6"
|
|
125
|
+
>
|
|
126
|
+
<div class="rounded-full bg-warning/10 p-3">
|
|
127
|
+
<AlertTriangle class="h-6 w-6 text-warning" />
|
|
128
|
+
</div>
|
|
129
|
+
<span class="text-sm text-warning">{lang[interfaceLanguage.current].missingFile}</span>
|
|
130
|
+
</div>
|
|
131
|
+
{/snippet}
|
|
132
|
+
|
|
133
|
+
{#snippet listRow(file: MediaFile, onRemove: () => void)}
|
|
134
|
+
{@const ext = getFileExtension(file.url)}
|
|
135
|
+
<div class="flex items-center gap-3 rounded-lg border bg-card p-2 shadow-sm">
|
|
136
|
+
<div class="relative aspect-square w-10 shrink-0 overflow-hidden rounded">
|
|
137
|
+
<FileMiniature {file} mode="thumb" />
|
|
138
|
+
</div>
|
|
139
|
+
<div class="min-w-0 flex-1">
|
|
140
|
+
<div class="flex items-center gap-1.5 min-w-0">
|
|
141
|
+
<p class="truncate text-sm font-medium">{file.name}</p>
|
|
142
|
+
{#if ext}
|
|
143
|
+
<span class="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">{ext}</span>
|
|
42
144
|
{/if}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
145
|
+
</div>
|
|
146
|
+
<p class="text-xs text-muted-foreground">{formatFileSize(file.size)}</p>
|
|
147
|
+
</div>
|
|
148
|
+
{#if !field.required || (Array.isArray(value) && value.length > 1)}
|
|
149
|
+
<Button
|
|
150
|
+
variant="ghost"
|
|
151
|
+
size="icon"
|
|
152
|
+
class="h-7 w-7 shrink-0 text-muted-foreground hover:text-destructive"
|
|
153
|
+
aria-label={lang[interfaceLanguage.current].removeAria}
|
|
154
|
+
onclick={onRemove}
|
|
155
|
+
>
|
|
156
|
+
<X class="h-4 w-4" />
|
|
157
|
+
</Button>
|
|
51
158
|
{/if}
|
|
52
159
|
</div>
|
|
160
|
+
{/snippet}
|
|
161
|
+
|
|
162
|
+
{#snippet listMissingRow(onRemove: () => void)}
|
|
163
|
+
<div class="flex items-center gap-3 rounded-lg border border-warning/40 bg-warning/5 p-2">
|
|
164
|
+
<div class="flex aspect-square w-10 shrink-0 items-center justify-center rounded bg-warning/10">
|
|
165
|
+
<AlertTriangle class="h-4 w-4 text-warning" />
|
|
166
|
+
</div>
|
|
167
|
+
<p class="min-w-0 flex-1 truncate text-sm text-warning">{lang[interfaceLanguage.current].missingFile}</p>
|
|
168
|
+
{#if !field.required || (Array.isArray(value) && value.length > 1)}
|
|
169
|
+
<Button
|
|
170
|
+
variant="ghost"
|
|
171
|
+
size="icon"
|
|
172
|
+
class="h-7 w-7 shrink-0 text-muted-foreground hover:text-destructive"
|
|
173
|
+
aria-label={lang[interfaceLanguage.current].removeAria}
|
|
174
|
+
onclick={onRemove}
|
|
175
|
+
>
|
|
176
|
+
<X class="h-4 w-4" />
|
|
177
|
+
</Button>
|
|
178
|
+
{/if}
|
|
179
|
+
</div>
|
|
180
|
+
{/snippet}
|
|
181
|
+
|
|
182
|
+
{#snippet mediaActions(onRemove: () => void)}
|
|
183
|
+
<div class="flex items-center justify-between gap-2 mt-1.5">
|
|
184
|
+
<Button size="sm" variant="secondary" class="h-8" onclick={openPicker}>
|
|
185
|
+
<Plus class="h-4 w-4" />
|
|
186
|
+
{lang[interfaceLanguage.current].change}
|
|
187
|
+
</Button>
|
|
188
|
+
{#if !field.required}
|
|
189
|
+
<Button variant="destructive" size="sm" class="h-8" onclick={onRemove}>
|
|
190
|
+
<X class="h-4 w-4" />
|
|
191
|
+
{lang[interfaceLanguage.current].remove}
|
|
192
|
+
</Button>
|
|
193
|
+
{/if}
|
|
194
|
+
</div>
|
|
195
|
+
{/snippet}
|
|
196
|
+
|
|
197
|
+
{#if value !== undefined}
|
|
198
|
+
{#if field.display === 'list'}
|
|
199
|
+
<!-- Compact list variant (non-visual files: PDF, audio, raw) -->
|
|
200
|
+
<div class="space-y-2 max-w-md">
|
|
201
|
+
{#if typeof value === 'string' && value !== ''}
|
|
202
|
+
{#if !singleFileReady}
|
|
203
|
+
<div class="animate-pulse bg-muted h-14 rounded-lg"></div>
|
|
204
|
+
{:else if singleFile}
|
|
205
|
+
{@render listRow(singleFile, () => { value = ''; })}
|
|
206
|
+
{:else}
|
|
207
|
+
{@render listMissingRow(() => { value = ''; })}
|
|
208
|
+
{/if}
|
|
209
|
+
{:else if Array.isArray(value) && value.length > 0}
|
|
210
|
+
{#if !mFilesQuery?.ready}
|
|
211
|
+
<div class="animate-pulse bg-muted h-14 rounded-lg"></div>
|
|
212
|
+
{:else if mFilesQuery?.current}
|
|
213
|
+
{@const files = mFilesQuery.current}
|
|
214
|
+
{#each value as id, i (id + '__' + i)}
|
|
215
|
+
{@const file = files.find((f) => f.id === id)}
|
|
216
|
+
{#if file}
|
|
217
|
+
{@render listRow(file, () => {
|
|
218
|
+
if (Array.isArray(value)) {
|
|
219
|
+
value = value.filter((_, idx) => idx !== i);
|
|
220
|
+
}
|
|
221
|
+
})}
|
|
222
|
+
{:else}
|
|
223
|
+
{@render listMissingRow(() => {
|
|
224
|
+
if (Array.isArray(value)) {
|
|
225
|
+
value = value.filter((_, idx) => idx !== i);
|
|
226
|
+
}
|
|
227
|
+
})}
|
|
228
|
+
{/if}
|
|
229
|
+
{/each}
|
|
230
|
+
{/if}
|
|
231
|
+
{/if}
|
|
232
|
+
|
|
233
|
+
{#if field.multiple || !value || (typeof value === 'string' && value === '') || (Array.isArray(value) && value.length === 0)}
|
|
234
|
+
<Button variant="outline" size="sm" onclick={openPicker}>
|
|
235
|
+
<Plus class="h-4 w-4" />
|
|
236
|
+
{field.multiple && Array.isArray(value) && value.length > 0
|
|
237
|
+
? lang[interfaceLanguage.current].addFile
|
|
238
|
+
: lang[interfaceLanguage.current].selectFile}
|
|
239
|
+
</Button>
|
|
240
|
+
{:else}
|
|
241
|
+
<Button variant="outline" size="sm" onclick={openPicker}>
|
|
242
|
+
<Plus class="h-4 w-4" />
|
|
243
|
+
{lang[interfaceLanguage.current].change}
|
|
244
|
+
</Button>
|
|
245
|
+
{/if}
|
|
246
|
+
</div>
|
|
247
|
+
{:else if value && ((typeof value === 'string' && value !== '') || (Array.isArray(value) && value.length > 0))}
|
|
248
|
+
<div class="max-w-64">
|
|
249
|
+
{#if typeof value === 'string'}
|
|
250
|
+
{#if !singleFileReady}
|
|
251
|
+
<div class="animate-pulse bg-muted w-full aspect-square rounded-2xl"></div>
|
|
252
|
+
{:else if singleFile}
|
|
253
|
+
{@render filePreview(singleFile)}
|
|
254
|
+
{@render mediaActions(() => { value = ''; })}
|
|
255
|
+
{:else}
|
|
256
|
+
{@render missingPlaceholder()}
|
|
257
|
+
{@render mediaActions(() => { value = ''; })}
|
|
258
|
+
{/if}
|
|
259
|
+
{:else if Array.isArray(value) && value.length > 0}
|
|
260
|
+
{@const valueArr = value}
|
|
261
|
+
{#if !mFilesQuery?.ready}
|
|
262
|
+
<div class="animate-pulse bg-muted w-full aspect-square rounded-2xl"></div>
|
|
263
|
+
{:else if mFilesQuery?.current}
|
|
264
|
+
{@const file = mFilesQuery.current[currentIndex]}
|
|
265
|
+
{#if file}
|
|
266
|
+
<div class="relative">
|
|
267
|
+
{@render filePreview(file)}
|
|
268
|
+
|
|
269
|
+
{#if valueArr.length > 1}
|
|
270
|
+
<div class="absolute inset-x-0 top-1/2 flex -translate-y-1/2 justify-between px-1 pointer-events-none">
|
|
271
|
+
<button
|
|
272
|
+
type="button"
|
|
273
|
+
class="pointer-events-auto flex h-8 w-8 items-center justify-center rounded-full bg-white/80 backdrop-blur shadow-md transition hover:bg-white hover:scale-105 dark:bg-background/80 dark:hover:bg-background"
|
|
274
|
+
onclick={() => { currentIndex = currentIndex > 0 ? currentIndex - 1 : valueArr.length - 1; }}
|
|
275
|
+
>
|
|
276
|
+
<ChevronLeft class="h-5 w-5" />
|
|
277
|
+
</button>
|
|
278
|
+
<button
|
|
279
|
+
type="button"
|
|
280
|
+
class="pointer-events-auto flex h-8 w-8 items-center justify-center rounded-full bg-white/80 backdrop-blur shadow-md transition hover:bg-white hover:scale-105 dark:bg-background/80 dark:hover:bg-background"
|
|
281
|
+
onclick={() => { currentIndex = currentIndex < valueArr.length - 1 ? currentIndex + 1 : 0; }}
|
|
282
|
+
>
|
|
283
|
+
<ChevronRight class="h-5 w-5" />
|
|
284
|
+
</button>
|
|
285
|
+
</div>
|
|
286
|
+
<div class="absolute top-2 right-2 rounded-full bg-plum-darker/60 px-2 py-0.5 text-xs font-medium text-white backdrop-blur">
|
|
287
|
+
{currentIndex + 1} / {valueArr.length}
|
|
288
|
+
</div>
|
|
289
|
+
{/if}
|
|
290
|
+
</div>
|
|
291
|
+
{@render mediaActions(() => {
|
|
292
|
+
if (Array.isArray(value)) {
|
|
293
|
+
const next = value.filter((_, i) => i !== currentIndex);
|
|
294
|
+
value = field.multiple ? next : next[0] ?? '';
|
|
295
|
+
if (currentIndex >= next.length) currentIndex = Math.max(0, next.length - 1);
|
|
296
|
+
}
|
|
297
|
+
})}
|
|
298
|
+
{:else}
|
|
299
|
+
<div class="relative">
|
|
300
|
+
{@render missingPlaceholder()}
|
|
301
|
+
{#if valueArr.length > 1}
|
|
302
|
+
<div class="absolute inset-x-0 top-1/2 flex -translate-y-1/2 justify-between px-1 pointer-events-none">
|
|
303
|
+
<button
|
|
304
|
+
type="button"
|
|
305
|
+
class="pointer-events-auto flex h-8 w-8 items-center justify-center rounded-full bg-white/80 backdrop-blur shadow-md transition hover:bg-white hover:scale-105 dark:bg-background/80 dark:hover:bg-background"
|
|
306
|
+
onclick={() => { currentIndex = currentIndex > 0 ? currentIndex - 1 : valueArr.length - 1; }}
|
|
307
|
+
>
|
|
308
|
+
<ChevronLeft class="h-5 w-5" />
|
|
309
|
+
</button>
|
|
310
|
+
<button
|
|
311
|
+
type="button"
|
|
312
|
+
class="pointer-events-auto flex h-8 w-8 items-center justify-center rounded-full bg-white/80 backdrop-blur shadow-md transition hover:bg-white hover:scale-105 dark:bg-background/80 dark:hover:bg-background"
|
|
313
|
+
onclick={() => { currentIndex = currentIndex < valueArr.length - 1 ? currentIndex + 1 : 0; }}
|
|
314
|
+
>
|
|
315
|
+
<ChevronRight class="h-5 w-5" />
|
|
316
|
+
</button>
|
|
317
|
+
</div>
|
|
318
|
+
<div class="absolute top-2 right-2 rounded-full bg-plum-darker/60 px-2 py-0.5 text-xs font-medium text-white backdrop-blur">
|
|
319
|
+
{currentIndex + 1} / {valueArr.length}
|
|
320
|
+
</div>
|
|
321
|
+
{/if}
|
|
322
|
+
</div>
|
|
323
|
+
{@render mediaActions(() => {
|
|
324
|
+
if (Array.isArray(value)) {
|
|
325
|
+
const next = value.filter((_, i) => i !== currentIndex);
|
|
326
|
+
value = field.multiple ? next : next[0] ?? '';
|
|
327
|
+
if (currentIndex >= next.length) currentIndex = Math.max(0, next.length - 1);
|
|
328
|
+
}
|
|
329
|
+
})}
|
|
330
|
+
{/if}
|
|
331
|
+
{:else}
|
|
332
|
+
{@render missingPlaceholder()}
|
|
333
|
+
{@render mediaActions(() => { value = field.multiple ? [] : ''; })}
|
|
334
|
+
{/if}
|
|
335
|
+
{/if}
|
|
336
|
+
</div>
|
|
337
|
+
{:else}
|
|
338
|
+
<button
|
|
339
|
+
type="button"
|
|
340
|
+
class="flex aspect-square max-w-64 w-full flex-col items-center justify-center gap-2 rounded-2xl border-2 border-dashed border-border bg-card/80 p-6 transition-colors hover:border-primary/50 hover:bg-card"
|
|
341
|
+
onclick={openPicker}
|
|
342
|
+
>
|
|
343
|
+
<div class="rounded-full bg-muted p-3">
|
|
344
|
+
<Plus class="h-6 w-6 text-muted-foreground" />
|
|
345
|
+
</div>
|
|
346
|
+
<span class="text-sm text-muted-foreground">{lang[interfaceLanguage.current].selectFile}</span>
|
|
347
|
+
</button>
|
|
348
|
+
{/if}
|
|
349
|
+
|
|
350
|
+
<Dialog.Root bind:open={dialogOpen}>
|
|
351
|
+
<Dialog.Content
|
|
352
|
+
fullscreenMobile
|
|
353
|
+
class="flex h-[85vh] w-full max-w-6xl! flex-col overflow-hidden p-0 sm:max-w-6xl!"
|
|
354
|
+
>
|
|
355
|
+
<Dialog.Title class="sr-only">{lang[interfaceLanguage.current].selectFile}</Dialog.Title>
|
|
356
|
+
<Dialog.Description class="sr-only">{lang[interfaceLanguage.current].selectFile}</Dialog.Description>
|
|
357
|
+
<MediaSelector
|
|
358
|
+
bind:selected={value}
|
|
359
|
+
multiple={field.multiple}
|
|
360
|
+
accept={field.accept}
|
|
361
|
+
maxSizeMB={field.maxSizeMB}
|
|
362
|
+
onConfirm={() => (dialogOpen = false)}
|
|
363
|
+
onCancel={() => (dialogOpen = false)}
|
|
364
|
+
/>
|
|
365
|
+
</Dialog.Content>
|
|
366
|
+
</Dialog.Root>
|
|
53
367
|
{/if}
|
|
@@ -332,7 +332,12 @@
|
|
|
332
332
|
{/if}
|
|
333
333
|
|
|
334
334
|
<Dialog.Root bind:open={dialogOpen}>
|
|
335
|
-
<Dialog.Content
|
|
335
|
+
<Dialog.Content
|
|
336
|
+
fullscreenMobile
|
|
337
|
+
class="flex h-[85vh] w-full max-w-6xl! flex-col overflow-hidden p-0 sm:max-w-6xl!"
|
|
338
|
+
>
|
|
339
|
+
<Dialog.Title class="sr-only">{lang[interfaceLanguage.current].selectMedia}</Dialog.Title>
|
|
340
|
+
<Dialog.Description class="sr-only">{lang[interfaceLanguage.current].selectMedia}</Dialog.Description>
|
|
336
341
|
<MediaSelector
|
|
337
342
|
bind:selected={value}
|
|
338
343
|
multiple={field.multiple}
|
|
@@ -345,7 +350,16 @@
|
|
|
345
350
|
|
|
346
351
|
<!-- Lightbox for images -->
|
|
347
352
|
<Dialog.Root bind:open={lightboxOpen}>
|
|
348
|
-
<Dialog.Content
|
|
353
|
+
<Dialog.Content
|
|
354
|
+
fullscreenMobile
|
|
355
|
+
class="max-h-[90vh] max-w-[90vw]! border-none bg-black/95 p-2"
|
|
356
|
+
>
|
|
357
|
+
<Dialog.Title class="sr-only">
|
|
358
|
+
{lightboxFile?.alt || lightboxFile?.name || ''}
|
|
359
|
+
</Dialog.Title>
|
|
360
|
+
<Dialog.Description class="sr-only">
|
|
361
|
+
{lightboxFile?.alt || lightboxFile?.name || ''}
|
|
362
|
+
</Dialog.Description>
|
|
349
363
|
{#if lightboxFile}
|
|
350
364
|
<div class="checkered-lightbox flex items-center justify-center">
|
|
351
365
|
<img
|
|
@@ -15,11 +15,18 @@
|
|
|
15
15
|
|
|
16
16
|
const interfaceLanguage = useInterfaceLanguage();
|
|
17
17
|
|
|
18
|
+
const clearLabel: Record<string, string> = {
|
|
19
|
+
pl: 'Wyczyść wybór',
|
|
20
|
+
en: 'Clear selection'
|
|
21
|
+
};
|
|
22
|
+
|
|
18
23
|
onMount(() => {
|
|
19
24
|
if (value === undefined) {
|
|
20
25
|
value = field.defaultValue ?? '';
|
|
21
26
|
}
|
|
22
27
|
});
|
|
28
|
+
|
|
29
|
+
const canClear = $derived(!field.required && typeof value === 'string' && value !== '');
|
|
23
30
|
</script>
|
|
24
31
|
|
|
25
32
|
{#if value !== undefined}
|
|
@@ -35,4 +42,19 @@
|
|
|
35
42
|
</div>
|
|
36
43
|
{/each}
|
|
37
44
|
</RadioGroup.Root>
|
|
45
|
+
|
|
46
|
+
{#if canClear}
|
|
47
|
+
<!--
|
|
48
|
+
Native radios have no native "uncheck" gesture. For optional fields,
|
|
49
|
+
expose an explicit Clear link so the editor can return to the
|
|
50
|
+
"no value" state without picking a sentinel option.
|
|
51
|
+
-->
|
|
52
|
+
<button
|
|
53
|
+
type="button"
|
|
54
|
+
class="text-muted-foreground hover:text-foreground mt-1 self-start text-xs underline-offset-2 hover:underline"
|
|
55
|
+
onclick={() => (value = '')}
|
|
56
|
+
>
|
|
57
|
+
{clearLabel[interfaceLanguage.current] ?? clearLabel.en}
|
|
58
|
+
</button>
|
|
59
|
+
{/if}
|
|
38
60
|
{/if}
|