includio-cms 0.1.3 → 0.5.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/CHANGELOG.md +76 -0
- package/ROADMAP.md +23 -13
- package/dist/admin/api/accept-invite.js +1 -5
- package/dist/admin/api/invite.js +7 -16
- package/dist/admin/client/account/account-page.svelte +20 -50
- package/dist/admin/client/account/lang.d.ts +15 -23
- package/dist/admin/client/account/lang.js +51 -67
- package/dist/admin/client/account/preferences-section.svelte +26 -84
- package/dist/admin/client/account/profile-section.svelte +60 -40
- package/dist/admin/client/account/schema.d.ts +11 -3
- package/dist/admin/client/account/schema.js +25 -16
- package/dist/admin/client/account/security-section.svelte +139 -105
- package/dist/admin/client/account/sessions-section.svelte +35 -34
- package/dist/admin/client/admin/admin-after-login-layout-content.svelte +3 -5
- package/dist/admin/client/admin/admin-layout.svelte +3 -2
- package/dist/admin/client/admin/admin-preloader.svelte +36 -0
- package/dist/admin/client/admin/admin-preloader.svelte.d.ts +18 -0
- package/dist/admin/client/admin/dashboard-page.svelte +55 -41
- package/dist/admin/client/collection/a11y-score-cell.svelte +45 -0
- package/dist/admin/client/collection/a11y-score-cell.svelte.d.ts +6 -0
- package/dist/admin/client/collection/bulk-actions-bar.svelte +83 -0
- package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +9 -0
- package/dist/admin/client/collection/collection-entries.svelte +255 -256
- package/dist/admin/client/collection/collection-view.svelte.d.ts +4 -3
- package/dist/admin/client/collection/collection-view.svelte.js +9 -5
- package/dist/admin/client/collection/collection.svelte +22 -12
- package/dist/admin/client/collection/data-table.svelte +50 -39
- package/dist/admin/client/collection/data-table.svelte.d.ts +1 -0
- package/dist/admin/client/collection/date-cell.svelte +7 -5
- package/dist/admin/client/collection/date-cell.svelte.d.ts +1 -1
- package/dist/admin/client/collection/empty-state.svelte +28 -0
- package/dist/admin/client/collection/empty-state.svelte.d.ts +9 -0
- package/dist/admin/client/collection/entry-link.svelte +10 -4
- package/dist/admin/client/collection/entry-link.svelte.d.ts +1 -0
- package/dist/admin/client/collection/grid-view.svelte +21 -23
- package/dist/admin/client/collection/grid-view.svelte.d.ts +1 -2
- package/dist/admin/client/collection/row-actions.svelte +60 -0
- package/dist/admin/client/collection/row-actions.svelte.d.ts +9 -0
- package/dist/admin/client/collection/status-badge.svelte +7 -8
- package/dist/admin/client/collection/table-pagination.svelte +122 -79
- package/dist/admin/client/collection/table-pagination.svelte.d.ts +1 -0
- package/dist/admin/client/collection/table-toolbar.svelte +108 -88
- package/dist/admin/client/collection/table-toolbar.svelte.d.ts +8 -9
- package/dist/admin/client/entry/entry-form.svelte +109 -1
- package/dist/admin/client/entry/entry-header.svelte +96 -37
- package/dist/admin/client/entry/entry-header.svelte.d.ts +5 -0
- package/dist/admin/client/entry/entry.svelte +171 -60
- package/dist/admin/client/entry/header/a11y-validator.d.ts +46 -0
- package/dist/admin/client/entry/header/a11y-validator.js +311 -0
- package/dist/admin/client/entry/header/publish-panel.svelte +373 -131
- package/dist/admin/client/entry/header/publish-panel.svelte.d.ts +4 -0
- package/dist/admin/client/entry/header/save-indicator.svelte +33 -23
- package/dist/admin/client/entry/header/schedule-popover.svelte +1 -1
- package/dist/admin/client/entry/header/status-badge.svelte +25 -118
- package/dist/admin/client/entry/header/version-history-sheet.svelte +314 -98
- package/dist/admin/client/form/form-submission/form-submission.svelte +271 -83
- package/dist/admin/client/form/form-submission/submission-field.svelte +12 -12
- package/dist/admin/client/form/form-submissions.svelte +421 -139
- package/dist/admin/client/form/submission-link.svelte +8 -2
- package/dist/admin/client/form/submission-link.svelte.d.ts +1 -0
- package/dist/admin/client/form/submission-status-badge.svelte +18 -4
- package/dist/admin/client/form/submission-status-badge.svelte.d.ts +1 -0
- package/dist/admin/client/login/lang.d.ts +32 -0
- package/dist/admin/client/login/lang.js +66 -2
- package/dist/admin/client/login/login-form.svelte +237 -95
- package/dist/admin/client/login/login-form.svelte.d.ts +2 -17
- package/dist/admin/client/login/login-page.svelte +34 -98
- package/dist/admin/client/login/reset-password-page.svelte +235 -0
- package/dist/admin/client/login/reset-password-page.svelte.d.ts +4 -0
- package/dist/admin/client/login/schema.d.ts +15 -0
- package/dist/admin/client/login/schema.js +21 -0
- package/dist/admin/client/users/accept-invite-page.svelte +166 -37
- package/dist/admin/client/users/create-user-dialog.svelte +15 -7
- package/dist/admin/client/users/delete-user-dialog.svelte +81 -16
- package/dist/admin/client/users/delete-user-dialog.svelte.d.ts +4 -1
- package/dist/admin/client/users/edit-user-dialog.svelte +3 -0
- package/dist/admin/client/users/invite-user-dialog.svelte +16 -3
- package/dist/admin/client/users/lang.d.ts +27 -0
- package/dist/admin/client/users/lang.js +64 -10
- package/dist/admin/client/users/pending-invitations.svelte +59 -23
- package/dist/admin/client/users/users-page.svelte +471 -72
- package/dist/admin/components/accessibility/accessibility-overview.svelte +2 -7
- package/dist/admin/components/dashboard/a11y-gauge.svelte +90 -0
- package/dist/admin/components/dashboard/a11y-gauge.svelte.d.ts +18 -0
- package/dist/admin/components/dashboard/accessibility-hub.svelte +13 -12
- package/dist/admin/components/dashboard/form-submissions-widget.svelte +71 -113
- package/dist/admin/components/dashboard/index.d.ts +4 -2
- package/dist/admin/components/dashboard/index.js +4 -2
- package/dist/admin/components/dashboard/recent-activity.svelte +53 -75
- package/dist/admin/components/dashboard/recent-entries.svelte +94 -0
- package/dist/admin/components/dashboard/recent-entries.svelte.d.ts +18 -0
- package/dist/admin/components/dashboard/stat-card.svelte +2 -2
- package/dist/admin/components/dashboard/tip-of-the-day.svelte +109 -0
- package/dist/admin/components/dashboard/tip-of-the-day.svelte.d.ts +3 -0
- package/dist/admin/components/dashboard/welcome-header.svelte +45 -0
- package/dist/admin/components/dashboard/welcome-header.svelte.d.ts +3 -0
- package/dist/admin/components/fields/{array-field.svelte → blocks-field.svelte} +4 -4
- package/dist/admin/components/fields/{array-field.svelte.d.ts → blocks-field.svelte.d.ts} +5 -5
- package/dist/admin/components/fields/content-field.svelte +27 -0
- package/dist/admin/components/fields/content-field.svelte.d.ts +31 -0
- package/dist/admin/components/fields/field-renderer.svelte +9 -7
- package/dist/admin/components/fields/image-field.svelte +2 -2
- package/dist/admin/components/fields/media-field.svelte +2 -2
- package/dist/admin/components/fields/seo-field.svelte +205 -25
- package/dist/admin/components/fields/simple-array-field.svelte +289 -0
- package/dist/admin/components/fields/simple-array-field.svelte.d.ts +30 -0
- package/dist/admin/components/fields/slug-field.svelte +3 -2
- package/dist/admin/components/fields/standalone-field-renderer.svelte +148 -0
- package/dist/admin/components/fields/standalone-field-renderer.svelte.d.ts +9 -0
- package/dist/admin/components/fields/text-field-wrapper.svelte +13 -1
- package/dist/admin/components/fields/text-field-wrapper.svelte.d.ts +2 -2
- package/dist/admin/components/fields/url-field.svelte +5 -4
- package/dist/admin/components/layout/app-sidebar.svelte +27 -24
- package/dist/admin/components/layout/lang.d.ts +6 -0
- package/dist/admin/components/layout/lang.js +13 -1
- package/dist/admin/components/layout/layout-renderer.svelte +352 -0
- package/dist/admin/components/layout/layout-renderer.svelte.d.ts +14 -0
- package/dist/admin/components/layout/nav-breadcrumbs.svelte +4 -4
- package/dist/admin/components/layout/nav-collections.svelte +65 -36
- package/dist/admin/components/layout/nav-footer.svelte +31 -0
- package/dist/admin/components/layout/nav-footer.svelte.d.ts +18 -0
- package/dist/admin/components/layout/nav-forms.svelte +55 -30
- package/dist/admin/components/layout/nav-main.svelte +14 -52
- package/dist/admin/components/layout/nav-search.svelte +4 -3
- package/dist/admin/components/layout/nav-singletons.svelte +59 -17
- package/dist/admin/components/layout/nav-singletons.svelte.d.ts +17 -8
- package/dist/admin/components/layout/site-header.svelte +74 -13
- package/dist/admin/components/media/alt-input.svelte +32 -22
- package/dist/admin/components/media/bulk-action-bar.svelte +139 -150
- package/dist/admin/components/media/file/file-details.svelte +299 -217
- package/dist/admin/components/media/file/file-miniature.svelte +54 -41
- package/dist/admin/components/media/file/file-miniature.svelte.d.ts +1 -0
- package/dist/admin/components/media/file/file-preview.svelte +1 -1
- package/dist/admin/components/media/file-upload.svelte +24 -26
- package/dist/admin/components/media/files-list.svelte +112 -40
- package/dist/admin/components/media/files-list.svelte.d.ts +2 -0
- package/dist/admin/components/media/focal-point-input.svelte +122 -26
- package/dist/admin/components/media/media-library.svelte +127 -70
- package/dist/admin/components/media/media-search.svelte +6 -6
- package/dist/admin/components/media/media-sort.svelte +3 -1
- package/dist/admin/components/media/multi-file-summary.svelte +88 -68
- package/dist/admin/components/media/tag-combobox.svelte +141 -66
- package/dist/admin/components/media/tag-combobox.svelte.d.ts +1 -0
- package/dist/admin/components/media/tag-sidebar.svelte +139 -121
- package/dist/admin/components/tiptap/FigureNodeView.svelte +144 -15
- package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +254 -0
- package/dist/admin/components/tiptap/InlineBlockNodeView.svelte.d.ts +4 -0
- package/dist/admin/components/tiptap/SlashCommandPopup.svelte +212 -0
- package/dist/admin/components/tiptap/SlashCommandPopup.svelte.d.ts +8 -0
- package/dist/admin/components/tiptap/content-editor.svelte +280 -0
- package/dist/admin/components/tiptap/content-editor.svelte.d.ts +9 -0
- package/dist/admin/components/tiptap/editor-toolbar.svelte +230 -0
- package/dist/admin/components/tiptap/editor-toolbar.svelte.d.ts +16 -0
- package/dist/admin/components/tiptap/heading-a11y-plugin.d.ts +2 -0
- package/dist/admin/components/tiptap/heading-a11y-plugin.js +67 -0
- package/dist/admin/components/tiptap/image-dialog.svelte +172 -11
- package/dist/admin/components/tiptap/inline-block-node.d.ts +19 -0
- package/dist/admin/components/tiptap/inline-block-node.js +98 -0
- package/dist/admin/components/tiptap/link-dialog.svelte +9 -4
- package/dist/admin/components/tiptap/slash-command.d.ts +17 -0
- package/dist/admin/components/tiptap/slash-command.js +181 -0
- package/dist/admin/components/tiptap/structured-content-utils.d.ts +21 -0
- package/dist/admin/components/tiptap/structured-content-utils.js +150 -0
- package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -190
- package/dist/admin/email/invite-template.d.ts +8 -0
- package/dist/admin/email/invite-template.js +99 -0
- package/dist/admin/email/reset-password-template.d.ts +7 -0
- package/dist/admin/email/reset-password-template.js +96 -0
- package/dist/admin/remote/ai.remote.d.ts +1 -0
- package/dist/admin/remote/ai.remote.js +4 -1
- package/dist/admin/remote/entry.remote.d.ts +8 -0
- package/dist/admin/remote/entry.remote.js +53 -4
- package/dist/admin/remote/preview.remote.js +2 -1
- package/dist/admin/shared/password-schema.d.ts +5 -0
- package/dist/admin/shared/password-schema.js +10 -0
- package/dist/admin/styles/admin.css +1530 -151
- package/dist/admin/utils/formatDate.d.ts +1 -0
- package/dist/admin/utils/formatDate.js +8 -0
- package/dist/admin/utils/roleLabel.d.ts +2 -0
- package/dist/admin/utils/roleLabel.js +13 -0
- package/dist/ai-claude/index.d.ts +2 -0
- package/dist/ai-claude/index.js +56 -0
- package/dist/cms/runtime/api.d.ts +6 -1
- package/dist/cms/runtime/api.js +3 -0
- package/dist/cms/runtime/schemas.d.ts +9 -1
- package/dist/cms/runtime/schemas.js +8 -0
- package/dist/cms/runtime/types.d.ts +82 -10
- package/dist/cms/runtime/types.js +4 -0
- package/dist/components/ui/accordion/accordion.stories.svelte +39 -0
- package/dist/components/ui/accordion/accordion.stories.svelte.d.ts +27 -0
- package/dist/components/ui/alert/alert.stories.svelte +53 -0
- package/dist/components/ui/alert/alert.stories.svelte.d.ts +27 -0
- package/dist/components/ui/alert/alert.svelte +5 -0
- package/dist/components/ui/alert/alert.svelte.d.ts +9 -0
- package/dist/components/ui/avatar/avatar.stories.svelte +16 -0
- package/dist/components/ui/avatar/avatar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/badge/badge.stories.svelte +33 -0
- package/dist/components/ui/badge/badge.stories.svelte.d.ts +27 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +33 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte.d.ts +27 -0
- package/dist/components/ui/button/button.stories.svelte +43 -0
- package/dist/components/ui/button/button.stories.svelte.d.ts +27 -0
- package/dist/components/ui/button/button.svelte +1 -2
- package/dist/components/ui/button/button.svelte.d.ts +0 -3
- package/dist/components/ui/button-group/button-group-separator.svelte.d.ts +1 -1
- package/dist/components/ui/card/card.stories.svelte +42 -0
- package/dist/components/ui/card/card.stories.svelte.d.ts +27 -0
- package/dist/components/ui/command/command.stories.svelte +51 -0
- package/dist/components/ui/command/command.stories.svelte.d.ts +27 -0
- package/dist/components/ui/dialog/dialog.stories.svelte +29 -0
- package/dist/components/ui/dialog/dialog.stories.svelte.d.ts +27 -0
- package/dist/components/ui/field/field-label.svelte.d.ts +1 -1
- package/dist/components/ui/field/field.stories.svelte +21 -0
- package/dist/components/ui/field/field.stories.svelte.d.ts +27 -0
- package/dist/components/ui/input/input.stories.svelte +40 -0
- package/dist/components/ui/input/input.stories.svelte.d.ts +27 -0
- package/dist/components/ui/input/input.svelte +2 -4
- package/dist/components/ui/item/item-separator.svelte.d.ts +1 -1
- package/dist/components/ui/label/label.stories.svelte +20 -0
- package/dist/components/ui/label/label.stories.svelte.d.ts +27 -0
- package/dist/components/ui/popover/popover.stories.svelte +29 -0
- package/dist/components/ui/popover/popover.stories.svelte.d.ts +27 -0
- package/dist/components/ui/select/select-group-heading.svelte.d.ts +1 -1
- package/dist/components/ui/select/select.stories.svelte +23 -0
- package/dist/components/ui/select/select.stories.svelte.d.ts +27 -0
- package/dist/components/ui/separator/separator.stories.svelte +24 -0
- package/dist/components/ui/separator/separator.stories.svelte.d.ts +27 -0
- package/dist/components/ui/sheet/sheet.stories.svelte +29 -0
- package/dist/components/ui/sheet/sheet.stories.svelte.d.ts +27 -0
- package/dist/components/ui/sidebar/sidebar-group.svelte +3 -3
- package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +2 -2
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte +28 -30
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +7 -7
- package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-trigger.svelte +4 -4
- package/dist/components/ui/sonner/sonner.stories.svelte +22 -0
- package/dist/components/ui/sonner/sonner.stories.svelte.d.ts +26 -0
- package/dist/components/ui/sonner/sonner.svelte +8 -2
- package/dist/components/ui/sonner/toast-demo.svelte +29 -0
- package/dist/components/ui/sonner/toast-demo.svelte.d.ts +6 -0
- package/dist/components/ui/textarea/textarea.stories.svelte +22 -0
- package/dist/components/ui/textarea/textarea.stories.svelte.d.ts +27 -0
- package/dist/components/ui/textarea/textarea.svelte +0 -2
- package/dist/components/ui/toggle/toggle.stories.svelte +22 -0
- package/dist/components/ui/toggle/toggle.stories.svelte.d.ts +27 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte +17 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte +26 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte.d.ts +27 -0
- package/dist/core/fields/fieldSchemaToTs.d.ts +1 -0
- package/dist/core/fields/fieldSchemaToTs.js +133 -1
- package/dist/core/fields/layoutUtils.d.ts +17 -0
- package/dist/core/fields/layoutUtils.js +149 -0
- package/dist/core/fields/structuredToHtml.d.ts +9 -0
- package/dist/core/fields/structuredToHtml.js +161 -0
- package/dist/core/server/entries/operations/create.js +2 -1
- package/dist/core/server/entries/operations/get.js +8 -6
- package/dist/core/server/entries/operations/update.d.ts +3 -0
- package/dist/core/server/entries/operations/update.js +30 -2
- package/dist/core/server/fields/queryStructuredContent.d.ts +15 -0
- package/dist/core/server/fields/queryStructuredContent.js +65 -0
- package/dist/core/server/fields/resolveImageFields.js +51 -2
- package/dist/core/server/fields/resolveRelationFields.js +2 -2
- package/dist/core/server/fields/resolveRichtextLinks.js +80 -13
- package/dist/core/server/fields/resolveUrlFields.js +57 -6
- package/dist/core/server/fields/slugResolver.d.ts +10 -0
- package/dist/core/server/fields/slugResolver.js +34 -0
- package/dist/core/server/generator/fields.js +15 -4
- package/dist/core/server/generator/generator.js +3 -2
- package/dist/files-local/index.js +126 -64
- package/dist/paraglide/.prettierignore +3 -0
- package/dist/paraglide/messages/_index.d.ts +36 -0
- package/dist/paraglide/messages/_index.js +72 -0
- package/dist/paraglide/messages/en.d.ts +5 -0
- package/dist/paraglide/messages/en.js +14 -0
- package/dist/paraglide/messages/pl.d.ts +5 -0
- package/dist/paraglide/messages/pl.js +14 -0
- package/dist/paraglide/messages.d.ts +2 -0
- package/dist/paraglide/messages.js +4 -0
- package/dist/paraglide/registry.d.ts +21 -0
- package/dist/paraglide/registry.js +31 -0
- package/dist/paraglide/runtime.d.ts +583 -0
- package/dist/paraglide/runtime.js +1402 -0
- package/dist/paraglide/server.d.ts +67 -0
- package/dist/paraglide/server.js +175 -0
- package/dist/server/auth.d.ts +5 -0
- package/dist/server/auth.js +12 -1
- package/dist/sveltekit/components/structured-content.svelte +204 -0
- package/dist/sveltekit/components/structured-content.svelte.d.ts +21 -0
- package/dist/sveltekit/config.d.ts +13 -3
- package/dist/sveltekit/index.d.ts +3 -0
- package/dist/sveltekit/index.js +3 -0
- package/dist/sveltekit/server/handle.js +1 -0
- package/dist/types/config.d.ts +3 -0
- package/dist/types/fields.d.ts +19 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/layout.d.ts +54 -0
- package/dist/types/layout.js +6 -0
- package/dist/types/structured-content.d.ts +63 -0
- package/dist/types/structured-content.js +1 -0
- package/dist/updates/0.1.4/index.d.ts +2 -0
- package/dist/updates/0.1.4/index.js +11 -0
- package/dist/updates/0.1.5/index.d.ts +2 -0
- package/dist/updates/0.1.5/index.js +18 -0
- package/dist/updates/0.2.0/index.d.ts +2 -0
- package/dist/updates/0.2.0/index.js +11 -0
- package/dist/updates/0.2.2/index.d.ts +2 -0
- package/dist/updates/0.2.2/index.js +13 -0
- package/dist/updates/0.5.0/index.d.ts +2 -0
- package/dist/updates/0.5.0/index.js +14 -0
- package/dist/updates/index.js +6 -1
- package/package.json +17 -10
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { onMount } from 'svelte';
|
|
4
4
|
import type { MediaFile, MediaTag } from '../../../types/media.js';
|
|
5
5
|
import { getRemotes } from '../../context/remotes.js';
|
|
6
|
-
import Button from '../../../components/ui/button/button.svelte';
|
|
7
6
|
import { toast } from 'svelte-sonner';
|
|
8
7
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
9
8
|
import type { InterfaceLanguage } from '../../../types/languages.js';
|
|
@@ -15,24 +14,41 @@
|
|
|
15
14
|
import TagSidebar from './tag-sidebar.svelte';
|
|
16
15
|
import MediaSearch from './media-search.svelte';
|
|
17
16
|
import BulkActionBar from './bulk-action-bar.svelte';
|
|
17
|
+
import ListCheck from '@tabler/icons-svelte/icons/list-check';
|
|
18
|
+
import Toggle from '../../../components/ui/toggle/toggle.svelte';
|
|
18
19
|
|
|
19
20
|
const lang: Record<
|
|
20
21
|
InterfaceLanguage,
|
|
21
22
|
{
|
|
22
23
|
fileDeletedToast: string;
|
|
23
24
|
currentFilePlaceholder: string;
|
|
25
|
+
currentFileDesc: string;
|
|
24
26
|
bulkDeletedToast: string;
|
|
27
|
+
selectMode: string;
|
|
28
|
+
selectModeActive: string;
|
|
29
|
+
selectModeAnnounce: string;
|
|
30
|
+
selectModeOffAnnounce: string;
|
|
25
31
|
}
|
|
26
32
|
> = {
|
|
27
33
|
pl: {
|
|
28
34
|
fileDeletedToast: 'Plik został usunięty',
|
|
29
|
-
currentFilePlaceholder: '
|
|
30
|
-
|
|
35
|
+
currentFilePlaceholder: 'Podgląd pliku',
|
|
36
|
+
currentFileDesc: 'Wybierz plik z listy, aby zobaczyć szczegóły i edytować metadane.',
|
|
37
|
+
bulkDeletedToast: 'Pliki zostały usunięte',
|
|
38
|
+
selectMode: 'Wybierz',
|
|
39
|
+
selectModeActive: 'Zaznaczanie',
|
|
40
|
+
selectModeAnnounce: 'Tryb zaznaczania włączony. Klikaj pliki, aby je zaznaczyć.',
|
|
41
|
+
selectModeOffAnnounce: 'Tryb zaznaczania wyłączony.'
|
|
31
42
|
},
|
|
32
43
|
en: {
|
|
33
44
|
fileDeletedToast: 'File has been deleted',
|
|
34
|
-
currentFilePlaceholder: '
|
|
35
|
-
|
|
45
|
+
currentFilePlaceholder: 'File preview',
|
|
46
|
+
currentFileDesc: 'Select a file from the list to view details and edit metadata.',
|
|
47
|
+
bulkDeletedToast: 'Files have been deleted',
|
|
48
|
+
selectMode: 'Select',
|
|
49
|
+
selectModeActive: 'Selecting',
|
|
50
|
+
selectModeAnnounce: 'Selection mode enabled. Click files to select them.',
|
|
51
|
+
selectModeOffAnnounce: 'Selection mode disabled.'
|
|
36
52
|
}
|
|
37
53
|
};
|
|
38
54
|
|
|
@@ -51,8 +67,21 @@
|
|
|
51
67
|
let activeTagFilter = $state<string | null>(null);
|
|
52
68
|
let searchQuery = $state('');
|
|
53
69
|
let selectedFileIds = $state<string[]>([]);
|
|
54
|
-
let lastClickedIndex = $state<number>(-1);
|
|
55
70
|
let dropZoneRef = $state<HTMLElement | null>(null);
|
|
71
|
+
let selectionMode = $state(false);
|
|
72
|
+
let selectionAnnouncement = $state('');
|
|
73
|
+
|
|
74
|
+
function exitSelectionMode() {
|
|
75
|
+
selectionMode = false;
|
|
76
|
+
selectedFileIds = [];
|
|
77
|
+
currentFile = null;
|
|
78
|
+
selectionAnnouncement = lang[interfaceLanguage.current].selectModeOffAnnounce;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function enterSelectionMode() {
|
|
82
|
+
selectionMode = true;
|
|
83
|
+
selectionAnnouncement = lang[interfaceLanguage.current].selectModeAnnounce;
|
|
84
|
+
}
|
|
56
85
|
|
|
57
86
|
const filesQuery = $derived(
|
|
58
87
|
remotes.getMediaFiles({
|
|
@@ -71,21 +100,24 @@
|
|
|
71
100
|
|
|
72
101
|
let tagsQuery = $derived(remotes.getMediaTags());
|
|
73
102
|
|
|
74
|
-
// Multi-select with shift/ctrl
|
|
75
103
|
function handleFileSelect(file: MediaFile, event?: MouseEvent) {
|
|
76
|
-
|
|
77
|
-
|
|
104
|
+
const isModifier = event && (event.ctrlKey || event.metaKey);
|
|
105
|
+
|
|
106
|
+
if (isModifier) {
|
|
107
|
+
// Cmd/Ctrl+click: toggle selection, auto-enter selection mode
|
|
108
|
+
if (!selectionMode) enterSelectionMode();
|
|
78
109
|
selectedFileIds = selectedFileIds.includes(file.id)
|
|
79
110
|
? selectedFileIds.filter((id) => id !== file.id)
|
|
80
111
|
: [...selectedFileIds, file.id];
|
|
81
112
|
currentFile = file;
|
|
82
|
-
} else if (
|
|
83
|
-
//
|
|
84
|
-
|
|
113
|
+
} else if (selectionMode) {
|
|
114
|
+
// Normal click in selection mode: toggle
|
|
115
|
+
selectedFileIds = selectedFileIds.includes(file.id)
|
|
116
|
+
? selectedFileIds.filter((id) => id !== file.id)
|
|
117
|
+
: [...selectedFileIds, file.id];
|
|
85
118
|
currentFile = file;
|
|
86
|
-
selectedFileIds = [file.id];
|
|
87
119
|
} else {
|
|
88
|
-
//
|
|
120
|
+
// Normal click without selection mode: open details
|
|
89
121
|
selectedFileIds = [];
|
|
90
122
|
currentFile = file;
|
|
91
123
|
if (multiple && Array.isArray(selected)) {
|
|
@@ -98,6 +130,12 @@
|
|
|
98
130
|
}
|
|
99
131
|
}
|
|
100
132
|
|
|
133
|
+
function handleRangeSelect(fileIds: string[]) {
|
|
134
|
+
// Merge range into selection (union)
|
|
135
|
+
const merged = new Set([...selectedFileIds, ...fileIds]);
|
|
136
|
+
selectedFileIds = [...merged];
|
|
137
|
+
}
|
|
138
|
+
|
|
101
139
|
async function deleteFileCommand() {
|
|
102
140
|
if (currentFile) {
|
|
103
141
|
await remotes.deleteMediaFile(currentFile.id);
|
|
@@ -123,13 +161,14 @@
|
|
|
123
161
|
const result = await remotes.renameMediaFile({ fileId: currentFile.id, newName });
|
|
124
162
|
if (result.success === true) {
|
|
125
163
|
currentFile = { ...currentFile, name: result.name, url: result.url };
|
|
164
|
+
await filesQuery.refresh();
|
|
165
|
+
await allFilesQuery.refresh();
|
|
126
166
|
}
|
|
127
167
|
return result;
|
|
128
168
|
}
|
|
129
169
|
throw new Error('No current file selected');
|
|
130
170
|
}
|
|
131
171
|
|
|
132
|
-
// Tag CRUD
|
|
133
172
|
async function handleCreateTag(name: string, color: string) {
|
|
134
173
|
await remotes.createMediaTag({ name, color });
|
|
135
174
|
await tagsQuery.refresh();
|
|
@@ -149,7 +188,6 @@
|
|
|
149
188
|
await allFilesQuery.refresh();
|
|
150
189
|
}
|
|
151
190
|
|
|
152
|
-
// Bulk operations
|
|
153
191
|
async function handleBulkTag(tagIds: string[]) {
|
|
154
192
|
const fileIds = selectedFileIds;
|
|
155
193
|
await remotes.bulkSetMediaFileTags({ fileIds, tagIds });
|
|
@@ -158,7 +196,7 @@
|
|
|
158
196
|
}
|
|
159
197
|
|
|
160
198
|
async function handleBulkDelete() {
|
|
161
|
-
await remotes.bulkDeleteMediaFiles(selectedFileIds);
|
|
199
|
+
await remotes.bulkDeleteMediaFiles({ ids: selectedFileIds });
|
|
162
200
|
toast.success(lang[interfaceLanguage.current].bulkDeletedToast);
|
|
163
201
|
selectedFileIds = [];
|
|
164
202
|
currentFile = null;
|
|
@@ -175,9 +213,9 @@
|
|
|
175
213
|
});
|
|
176
214
|
</script>
|
|
177
215
|
|
|
178
|
-
<div class="flex h-full" bind:this={dropZoneRef}>
|
|
179
|
-
<!-- Tag sidebar -->
|
|
180
|
-
<
|
|
216
|
+
<div class="flex h-full overflow-hidden" bind:this={dropZoneRef}>
|
|
217
|
+
<!-- Tag sidebar (192px) -->
|
|
218
|
+
<aside class="w-48 min-w-48 shrink-0 border-r bg-card flex flex-col overflow-hidden" aria-label="Filtry tagów">
|
|
181
219
|
{#await Promise.all([tagsQuery, allFilesQuery]) then [tags, allFiles]}
|
|
182
220
|
<TagSidebar
|
|
183
221
|
{tags}
|
|
@@ -189,13 +227,26 @@
|
|
|
189
227
|
onDeleteTag={handleDeleteTag}
|
|
190
228
|
/>
|
|
191
229
|
{/await}
|
|
192
|
-
</
|
|
230
|
+
</aside>
|
|
193
231
|
|
|
194
|
-
<!-- Main content -->
|
|
195
|
-
<
|
|
196
|
-
|
|
232
|
+
<!-- Main content (flex-1) -->
|
|
233
|
+
<section class="flex flex-1 flex-col overflow-hidden" aria-label="Pliki">
|
|
234
|
+
<!-- Toolbar -->
|
|
235
|
+
<div class="flex items-center gap-2.5 border-b bg-card px-5 py-3 shrink-0">
|
|
197
236
|
<MediaSearch bind:value={searchQuery} />
|
|
198
237
|
<MediaSort />
|
|
238
|
+
<Toggle
|
|
239
|
+
variant="outline"
|
|
240
|
+
size="sm"
|
|
241
|
+
pressed={selectionMode}
|
|
242
|
+
onPressedChange={(pressed) => pressed ? enterSelectionMode() : exitSelectionMode()}
|
|
243
|
+
class="gap-1.5 px-2.5 text-xs font-semibold whitespace-nowrap shrink-0 {selectionMode ? 'bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground border-primary' : ''}"
|
|
244
|
+
aria-label={selectionMode ? lang[interfaceLanguage.current].selectModeActive : lang[interfaceLanguage.current].selectMode}
|
|
245
|
+
>
|
|
246
|
+
<ListCheck class="h-4 w-4" />
|
|
247
|
+
{selectionMode ? lang[interfaceLanguage.current].selectModeActive : lang[interfaceLanguage.current].selectMode}
|
|
248
|
+
</Toggle>
|
|
249
|
+
<div class="flex-1"></div>
|
|
199
250
|
<FileUpload
|
|
200
251
|
onUpload={() => { filesQuery.refresh(); allFilesQuery.refresh(); }}
|
|
201
252
|
{accept}
|
|
@@ -203,66 +254,72 @@
|
|
|
203
254
|
/>
|
|
204
255
|
</div>
|
|
205
256
|
|
|
206
|
-
|
|
207
|
-
|
|
257
|
+
<!-- Selection mode announcement (sr-only) -->
|
|
258
|
+
<div class="sr-only" aria-live="polite" role="status">{selectionAnnouncement}</div>
|
|
259
|
+
|
|
260
|
+
<!-- File grid -->
|
|
261
|
+
<div class="flex-1 overflow-y-auto px-5 pt-4 pb-24 scrollbar-thin" role="listbox" aria-multiselectable="true" aria-label="Siatka plików">
|
|
262
|
+
<div class="grid grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] gap-3">
|
|
208
263
|
{#await filesQuery}
|
|
209
264
|
{#each Array(8) as _}
|
|
210
|
-
<Skeleton class="block
|
|
265
|
+
<Skeleton class="block h-[168px] rounded-xl" />
|
|
211
266
|
{/each}
|
|
212
267
|
{:then files}
|
|
213
268
|
<FilesList
|
|
214
269
|
{files}
|
|
215
270
|
selected={selectedFileIds.length > 0 ? selectedFileIds : (selected ?? '')}
|
|
216
271
|
onSelect={handleFileSelect}
|
|
272
|
+
onRangeSelect={handleRangeSelect}
|
|
273
|
+
{selectionMode}
|
|
217
274
|
/>
|
|
218
275
|
{/await}
|
|
219
276
|
</div>
|
|
220
277
|
</div>
|
|
221
|
-
</
|
|
278
|
+
</section>
|
|
222
279
|
|
|
223
|
-
<!-- Detail panel -->
|
|
224
|
-
<
|
|
225
|
-
|
|
226
|
-
{#
|
|
227
|
-
{#await
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
/>
|
|
235
|
-
{/await}
|
|
280
|
+
<!-- Detail panel (384px) -->
|
|
281
|
+
<aside class="w-96 min-w-96 shrink-0 border-l bg-card flex flex-col overflow-hidden" aria-label="Szczegóły pliku">
|
|
282
|
+
{#if selectionMode}
|
|
283
|
+
{#await filesQuery then allFiles}
|
|
284
|
+
{#await tagsQuery then tags}
|
|
285
|
+
<MultiFileSummary
|
|
286
|
+
files={allFiles.filter((f) => selectedFileIds.includes(f.id))}
|
|
287
|
+
allTags={tags}
|
|
288
|
+
onBulkTag={handleBulkTag}
|
|
289
|
+
onBulkDelete={handleBulkDelete}
|
|
290
|
+
/>
|
|
236
291
|
{/await}
|
|
237
|
-
{
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
{/
|
|
254
|
-
{
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
292
|
+
{/await}
|
|
293
|
+
{:else if currentFile}
|
|
294
|
+
{#key currentFile}
|
|
295
|
+
{#await tagsQuery then tags}
|
|
296
|
+
<FileDetails
|
|
297
|
+
file={currentFile}
|
|
298
|
+
allTags={tags}
|
|
299
|
+
onDelete={deleteFileCommand}
|
|
300
|
+
onReplace={(updated) => {
|
|
301
|
+
currentFile = updated;
|
|
302
|
+
filesQuery.refresh();
|
|
303
|
+
allFilesQuery.refresh();
|
|
304
|
+
}}
|
|
305
|
+
{onTagUpdate}
|
|
306
|
+
{onNameUpdate}
|
|
307
|
+
/>
|
|
308
|
+
{/await}
|
|
309
|
+
{/key}
|
|
310
|
+
{:else}
|
|
311
|
+
<!-- Empty state -->
|
|
312
|
+
<div class="flex flex-1 flex-col items-center justify-center px-5 py-10 text-center">
|
|
313
|
+
<div class="mb-3.5 flex h-14 w-14 items-center justify-center rounded-xl bg-muted">
|
|
314
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-text-light" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
315
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
|
316
|
+
</svg>
|
|
262
317
|
</div>
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
318
|
+
<p class="text-sm font-bold text-foreground">{lang[interfaceLanguage.current].currentFilePlaceholder}</p>
|
|
319
|
+
<p class="mt-1 text-[13px] leading-relaxed text-muted-foreground">{lang[interfaceLanguage.current].currentFileDesc}</p>
|
|
320
|
+
</div>
|
|
321
|
+
{/if}
|
|
322
|
+
</aside>
|
|
266
323
|
</div>
|
|
267
324
|
|
|
268
325
|
<!-- Bulk action bar -->
|
|
@@ -274,7 +331,7 @@
|
|
|
274
331
|
{tags}
|
|
275
332
|
onBulkTag={handleBulkTag}
|
|
276
333
|
onBulkDelete={handleBulkDelete}
|
|
277
|
-
onClear={
|
|
334
|
+
onClear={exitSelectionMode}
|
|
278
335
|
onSelectAll={() => { selectedFileIds = allFiles.map((f) => f.id); }}
|
|
279
336
|
onCreateTag={handleCreateTag}
|
|
280
337
|
onUpdateTagColor={async (id, color) => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
3
3
|
import type { InterfaceLanguage } from '../../../types/languages.js';
|
|
4
|
-
import Input from '../../../components/ui/input/input.svelte';
|
|
5
4
|
import Search from '@tabler/icons-svelte/icons/search';
|
|
6
5
|
import X from '@tabler/icons-svelte/icons/x';
|
|
7
6
|
|
|
@@ -36,20 +35,21 @@
|
|
|
36
35
|
}
|
|
37
36
|
</script>
|
|
38
37
|
|
|
39
|
-
<div class="
|
|
40
|
-
<Search class="
|
|
41
|
-
<
|
|
38
|
+
<div class="flex flex-1 items-center gap-2 rounded-lg bg-muted/60 border border-transparent px-3 py-1.5 transition-all focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/10 focus-within:bg-card max-w-xs min-w-[200px]">
|
|
39
|
+
<Search class="h-4 w-4 shrink-0 text-text-light" />
|
|
40
|
+
<input
|
|
42
41
|
type="search"
|
|
42
|
+
class="flex-1 border-none bg-transparent text-[13px] text-foreground placeholder:text-text-light outline-none"
|
|
43
43
|
placeholder={lang[interfaceLanguage.current].placeholder}
|
|
44
|
-
class="h-9 w-full pl-9 pr-8 text-sm"
|
|
45
44
|
value={inputValue}
|
|
46
45
|
oninput={handleInput}
|
|
47
46
|
/>
|
|
48
47
|
{#if inputValue}
|
|
49
48
|
<button
|
|
50
49
|
type="button"
|
|
51
|
-
class="
|
|
50
|
+
class="rounded-sm p-0.5 text-muted-foreground hover:text-foreground transition-colors"
|
|
52
51
|
onclick={clear}
|
|
52
|
+
aria-label="Wyczyść wyszukiwanie"
|
|
53
53
|
>
|
|
54
54
|
<X class="h-3.5 w-3.5" />
|
|
55
55
|
</button>
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import type { InterfaceLanguage } from '../../../types/languages.js';
|
|
4
4
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
5
5
|
import { sortOptions, getMediaSort } from '../../state/media-sort.svelte.js';
|
|
6
|
+
import ArrowsSort from '@tabler/icons-svelte/icons/arrows-sort';
|
|
6
7
|
|
|
7
8
|
const lang: Record<
|
|
8
9
|
InterfaceLanguage,
|
|
@@ -34,7 +35,8 @@
|
|
|
34
35
|
</script>
|
|
35
36
|
|
|
36
37
|
<Select.Root type="single" name="sort" value={sort.current}>
|
|
37
|
-
<Select.Trigger>
|
|
38
|
+
<Select.Trigger class="inline-flex items-center gap-1.5 rounded-lg border border-border bg-card px-3 py-1.5 text-[13px] font-medium text-muted-foreground transition-colors hover:bg-lavender-lighter hover:border-lavender hover:text-primary focus-visible:outline-2 focus-visible:outline-primary focus-visible:outline-offset-2 h-auto">
|
|
39
|
+
<ArrowsSort class="h-3.5 w-3.5" />
|
|
38
40
|
{triggerContent}
|
|
39
41
|
</Select.Trigger>
|
|
40
42
|
<Select.Content>
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
deleteConfirmDesc: string;
|
|
23
23
|
cancel: string;
|
|
24
24
|
delete: string;
|
|
25
|
+
typesLabel: string;
|
|
26
|
+
emptyHint: string;
|
|
25
27
|
}
|
|
26
28
|
> = {
|
|
27
29
|
pl: {
|
|
@@ -35,7 +37,9 @@
|
|
|
35
37
|
deleteConfirmTitle: 'Usunąć pliki?',
|
|
36
38
|
deleteConfirmDesc: 'Zaznaczone pliki zostaną trwale usunięte.',
|
|
37
39
|
cancel: 'Anuluj',
|
|
38
|
-
delete: 'Usuń'
|
|
40
|
+
delete: 'Usuń',
|
|
41
|
+
typesLabel: 'Typy',
|
|
42
|
+
emptyHint: 'Kliknij pliki, aby je zaznaczyć'
|
|
39
43
|
},
|
|
40
44
|
en: {
|
|
41
45
|
filesSelected: 'files selected',
|
|
@@ -48,7 +52,9 @@
|
|
|
48
52
|
deleteConfirmTitle: 'Delete files?',
|
|
49
53
|
deleteConfirmDesc: 'Selected files will be permanently deleted.',
|
|
50
54
|
cancel: 'Cancel',
|
|
51
|
-
delete: 'Delete'
|
|
55
|
+
delete: 'Delete',
|
|
56
|
+
typesLabel: 'Types',
|
|
57
|
+
emptyHint: 'Click files to select them'
|
|
52
58
|
}
|
|
53
59
|
};
|
|
54
60
|
|
|
@@ -89,7 +95,6 @@
|
|
|
89
95
|
return allTags.filter((t) => firstTagIds.has(t.id));
|
|
90
96
|
});
|
|
91
97
|
|
|
92
|
-
// Initialize bulkTagIds with shared tags when files change
|
|
93
98
|
$effect(() => {
|
|
94
99
|
bulkTagIds = sharedTags.map((t) => t.id);
|
|
95
100
|
});
|
|
@@ -103,87 +108,101 @@
|
|
|
103
108
|
});
|
|
104
109
|
</script>
|
|
105
110
|
|
|
106
|
-
|
|
107
|
-
<div class="flex
|
|
108
|
-
<div class="flex h-
|
|
109
|
-
<Files class="h-
|
|
110
|
-
</div>
|
|
111
|
-
<div>
|
|
112
|
-
<div class="text-lg font-semibold tabular-nums">{files.length}</div>
|
|
113
|
-
<div class="text-xs glass-text-muted">{lang[interfaceLanguage.current].filesSelected}</div>
|
|
111
|
+
{#if files.length === 0}
|
|
112
|
+
<div class="flex flex-1 flex-col items-center justify-center px-5 py-10 text-center h-full">
|
|
113
|
+
<div class="mb-3.5 flex h-14 w-14 items-center justify-center rounded-xl bg-muted">
|
|
114
|
+
<Files class="h-6 w-6 text-text-light" />
|
|
114
115
|
</div>
|
|
116
|
+
<p class="text-sm font-bold text-foreground">0 {lang[interfaceLanguage.current].filesSelected}</p>
|
|
117
|
+
<p class="mt-1 text-[13px] leading-relaxed text-muted-foreground">{lang[interfaceLanguage.current].emptyHint}</p>
|
|
115
118
|
</div>
|
|
116
|
-
|
|
117
|
-
<div class="
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
<div class="
|
|
121
|
-
<div class="
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
{#each Object.entries(typeBreakdown) as [type, count]}
|
|
128
|
-
<span class="text-xs">{count} {type}</span>
|
|
129
|
-
{/each}
|
|
119
|
+
{:else}
|
|
120
|
+
<div class="flex h-full flex-col overflow-hidden">
|
|
121
|
+
<div class="flex-1 overflow-y-auto scrollbar-thin">
|
|
122
|
+
<!-- Header -->
|
|
123
|
+
<div class="flex items-center gap-3 border-b px-5 py-4">
|
|
124
|
+
<div class="flex h-10 w-10 items-center justify-center rounded-xl bg-primary/10">
|
|
125
|
+
<Files class="h-5 w-5 text-primary" />
|
|
126
|
+
</div>
|
|
127
|
+
<div>
|
|
128
|
+
<div class="text-lg font-bold tabular-nums text-foreground">{files.length}</div>
|
|
129
|
+
<div class="text-xs text-text-light font-medium">{lang[interfaceLanguage.current].filesSelected}</div>
|
|
130
130
|
</div>
|
|
131
131
|
</div>
|
|
132
|
-
</div>
|
|
133
132
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
133
|
+
<div class="space-y-4 p-5">
|
|
134
|
+
<!-- Stats -->
|
|
135
|
+
<div class="grid grid-cols-2 gap-3">
|
|
136
|
+
<div class="rounded-xl bg-muted/40 px-3 py-2.5">
|
|
137
|
+
<div class="text-[11px] font-bold uppercase tracking-wide text-text-light">{lang[interfaceLanguage.current].totalSize}</div>
|
|
138
|
+
<div class="mt-0.5 text-sm font-semibold text-foreground">{formatFileSize(totalSize)}</div>
|
|
139
|
+
</div>
|
|
140
|
+
<div class="rounded-xl bg-muted/40 px-3 py-2.5">
|
|
141
|
+
<div class="text-[11px] font-bold uppercase tracking-wide text-text-light">{lang[interfaceLanguage.current].typesLabel}</div>
|
|
142
|
+
<div class="mt-0.5 flex gap-1.5 text-sm font-semibold text-foreground">
|
|
143
|
+
{#each Object.entries(typeBreakdown) as [type, count]}
|
|
144
|
+
<span class="text-xs">{count} {type}</span>
|
|
145
|
+
{/each}
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<!-- Shared tags -->
|
|
151
|
+
<div class="space-y-1.5">
|
|
152
|
+
<div class="text-[11px] font-bold uppercase tracking-wide text-text-light">{lang[interfaceLanguage.current].sharedTags}</div>
|
|
153
|
+
{#if sharedTags.length > 0}
|
|
154
|
+
<div class="flex flex-wrap gap-1.5">
|
|
155
|
+
{#each sharedTags as tag}
|
|
156
|
+
<span class="inline-flex items-center gap-1.5 rounded-full bg-muted/50 px-2.5 py-1 text-xs font-medium">
|
|
157
|
+
<span class="h-1.5 w-1.5 rounded-full" style="background-color: {tag.color}"></span>
|
|
158
|
+
{tag.name}
|
|
159
|
+
</span>
|
|
160
|
+
{/each}
|
|
161
|
+
</div>
|
|
162
|
+
{:else}
|
|
163
|
+
<p class="text-xs text-muted-foreground">{lang[interfaceLanguage.current].noSharedTags}</p>
|
|
164
|
+
{/if}
|
|
145
165
|
</div>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
166
|
+
|
|
167
|
+
<!-- Bulk tag -->
|
|
168
|
+
<div class="space-y-1.5">
|
|
169
|
+
<div class="text-[11px] font-bold uppercase tracking-wide text-text-light">{lang[interfaceLanguage.current].setTags}</div>
|
|
170
|
+
<TagCombobox
|
|
171
|
+
tags={allTags}
|
|
172
|
+
selectedTagIds={bulkTagIds}
|
|
173
|
+
onchange={(ids) => (bulkTagIds = ids)}
|
|
174
|
+
showLabel={false}
|
|
175
|
+
/>
|
|
176
|
+
<Button
|
|
177
|
+
size="sm"
|
|
178
|
+
variant="outline"
|
|
179
|
+
class="w-full"
|
|
180
|
+
onclick={async () => {
|
|
181
|
+
await onBulkTag(bulkTagIds);
|
|
182
|
+
}}
|
|
183
|
+
>
|
|
184
|
+
{lang[interfaceLanguage.current].apply}
|
|
185
|
+
</Button>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
149
188
|
</div>
|
|
150
189
|
|
|
151
|
-
<!--
|
|
152
|
-
<div class="
|
|
153
|
-
<div class="text-xs font-medium glass-text-muted">{lang[interfaceLanguage.current].setTags}</div>
|
|
154
|
-
<TagCombobox
|
|
155
|
-
tags={allTags}
|
|
156
|
-
selectedTagIds={bulkTagIds}
|
|
157
|
-
onchange={(ids) => (bulkTagIds = ids)}
|
|
158
|
-
showLabel={false}
|
|
159
|
-
/>
|
|
190
|
+
<!-- Delete -->
|
|
191
|
+
<div class="shrink-0 border-t px-5 py-4">
|
|
160
192
|
<Button
|
|
161
193
|
size="sm"
|
|
162
|
-
variant="
|
|
163
|
-
class="w-full"
|
|
164
|
-
onclick={
|
|
165
|
-
await onBulkTag(bulkTagIds);
|
|
166
|
-
}}
|
|
194
|
+
variant="destructive"
|
|
195
|
+
class="w-full gap-1.5"
|
|
196
|
+
onclick={() => (deleteDialogOpen = true)}
|
|
167
197
|
>
|
|
168
|
-
|
|
198
|
+
<Trash class="h-3.5 w-3.5" />
|
|
199
|
+
{lang[interfaceLanguage.current].deleteAll}
|
|
169
200
|
</Button>
|
|
170
201
|
</div>
|
|
171
202
|
</div>
|
|
172
203
|
|
|
173
|
-
<!-- Delete -->
|
|
174
|
-
<div class="border-t border-white/10 px-5 py-4">
|
|
175
|
-
<Button
|
|
176
|
-
size="sm"
|
|
177
|
-
variant="destructive"
|
|
178
|
-
class="w-full gap-1.5"
|
|
179
|
-
onclick={() => (deleteDialogOpen = true)}
|
|
180
|
-
>
|
|
181
|
-
<Trash class="h-3.5 w-3.5" />
|
|
182
|
-
{lang[interfaceLanguage.current].deleteAll}
|
|
183
|
-
</Button>
|
|
184
|
-
</div>
|
|
185
|
-
|
|
186
204
|
<AlertDialog.Root bind:open={deleteDialogOpen}>
|
|
205
|
+
|
|
187
206
|
<AlertDialog.Content>
|
|
188
207
|
<AlertDialog.Title>{lang[interfaceLanguage.current].deleteConfirmTitle}</AlertDialog.Title>
|
|
189
208
|
<AlertDialog.Description>{lang[interfaceLanguage.current].deleteConfirmDesc}</AlertDialog.Description>
|
|
@@ -200,3 +219,4 @@
|
|
|
200
219
|
</AlertDialog.Footer>
|
|
201
220
|
</AlertDialog.Content>
|
|
202
221
|
</AlertDialog.Root>
|
|
222
|
+
{/if}
|