@templatical/editor 0.16.5 → 0.17.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/dist/{AiChatSidebar-CYAbVB2G.js → AiChatSidebar-LxCHMdcj.js} +1 -1
- package/dist/{AiFeatureMenu-B1oEJebq.js → AiFeatureMenu-zwSmx9ZW.js} +3 -3
- package/dist/{BlockIssueBadge-BLytBabN.js → BlockIssueBadge-BQ1yB1me.js} +2 -2
- package/dist/{CloudEditor-D6KNL6VU.js → CloudEditor-5ahgKRX8.js} +11 -10
- package/dist/{CollaboratorBar-C_EhXQ5R.js → CollaboratorBar-6PtX-1AS.js} +2 -2
- package/dist/{ColorPicker-CppJgX_T.js → ColorPicker-DfzDyNKe.js} +4 -4
- package/dist/{CommentsSidebar-C_XLBbo3.js → CommentsSidebar-Cl93TN96.js} +3 -3
- package/dist/{CountdownBlock-173fiO5Z.js → CountdownBlock-DbXfzwae.js} +1 -1
- package/dist/{CountdownToolbar-D5GaA_lt.js → CountdownToolbar-BqaMWRyB.js} +3 -3
- package/dist/{DesignReferenceSidebar-Bh9uAZ4B.js → DesignReferenceSidebar-jVrdS8wW.js} +2 -2
- package/dist/{IssuesPanel-DltSuU6H.js → IssuesPanel-Bq3yXg6M.js} +2 -2
- package/dist/{ModuleBrowserModal-CXy8Bbv9.js → ModuleBrowserModal-B5IH3-1I.js} +7 -7
- package/dist/{ModulePreviewCanvas-CJC9kyZN.js → ModulePreviewCanvas-CYOLWoZ9.js} +2 -2
- package/dist/{NumberWithSuffix-DNi-v4l1.js → NumberWithSuffix-9FG7mNnn.js} +1 -1
- package/dist/{ParagraphEditor-nk5Vvr7M.js → ParagraphEditor-duWYA6Vv.js} +8 -8
- package/dist/{RichTextEditorContent-DBaCrvH0.js → RichTextEditorContent-DCzmVeyb.js} +5 -5
- package/dist/{SaveModuleDialog-CYu5PhBz.js → SaveModuleDialog-BPUly5h3.js} +6 -6
- package/dist/{SnapshotHistory-B38ImqMO.js → SnapshotHistory-CmwU3nlN.js} +4 -4
- package/dist/{TemplateScoringPanel-ZhObHWeb.js → TemplateScoringPanel-CMrfa9Rd.js} +3 -3
- package/dist/{TestEmailModal-DbstIzEf.js → TestEmailModal-zfomMz9i.js} +3 -3
- package/dist/{TitleEditor-CmfkOHJT.js → TitleEditor-v0gtezZE.js} +7 -7
- package/dist/{TplModal-BXnx3sLr.js → TplModal-eGFG7k-y.js} +3 -3
- package/dist/{blockTypeIcons-BVIEw0XJ.js → blockTypeIcons-Dd0w4T0I.js} +1 -1
- package/dist/bundle-stats.json +6 -6
- package/dist/{ca-DI1ViqMa.js → ca-CSl--oWR.js} +1 -1
- package/dist/cdn/chunks/{AiFeatureMenu-CuIg4yrB.js → AiFeatureMenu-CtXsam7G.js} +2 -2
- package/dist/cdn/chunks/{AiFeatureMenu-CuIg4yrB.js.map → AiFeatureMenu-CtXsam7G.js.map} +1 -1
- package/dist/cdn/chunks/{BlockIssueBadge-BHEl_Hs7.js → BlockIssueBadge-DR7cpDfQ.js} +2 -2
- package/dist/cdn/chunks/{BlockIssueBadge-BHEl_Hs7.js.map → BlockIssueBadge-DR7cpDfQ.js.map} +1 -1
- package/dist/cdn/chunks/{CloudEditor-1Ms0w691.js → CloudEditor-YC5y3AwC.js} +10 -9
- package/dist/cdn/chunks/CloudEditor-YC5y3AwC.js.map +1 -0
- package/dist/cdn/chunks/{CollaboratorBar-C0a5P64z.js → CollaboratorBar-BOD2j8Kl.js} +3 -3
- package/dist/cdn/chunks/{CollaboratorBar-C0a5P64z.js.map → CollaboratorBar-BOD2j8Kl.js.map} +1 -1
- package/dist/cdn/chunks/{ColorPicker-bsMmT-_B.js → ColorPicker-CPMWLHpa.js} +2 -2
- package/dist/cdn/chunks/{ColorPicker-bsMmT-_B.js.map → ColorPicker-CPMWLHpa.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownBlock-8053oz4k.js → CountdownBlock-BmGqb7Zi.js} +2 -2
- package/dist/cdn/chunks/{CountdownBlock-8053oz4k.js.map → CountdownBlock-BmGqb7Zi.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownToolbar-DQ_zrorh.js → CountdownToolbar-BBwsdGbV.js} +4 -4
- package/dist/cdn/chunks/{CountdownToolbar-DQ_zrorh.js.map → CountdownToolbar-BBwsdGbV.js.map} +1 -1
- package/dist/cdn/chunks/{IssuesPanel-CwQ376nf.js → IssuesPanel-G0z-j3JS.js} +3 -3
- package/dist/cdn/chunks/{IssuesPanel-CwQ376nf.js.map → IssuesPanel-G0z-j3JS.js.map} +1 -1
- package/dist/cdn/chunks/{ModuleBrowserModal-DUegB2Jk.js → ModuleBrowserModal-DiLTY0ec.js} +5 -5
- package/dist/cdn/chunks/{ModuleBrowserModal-DUegB2Jk.js.map → ModuleBrowserModal-DiLTY0ec.js.map} +1 -1
- package/dist/cdn/chunks/{ModulePreviewCanvas-f4h8r9Lh.js → ModulePreviewCanvas-CdV5mEQ6.js} +2 -2
- package/dist/cdn/chunks/{ModulePreviewCanvas-f4h8r9Lh.js.map → ModulePreviewCanvas-CdV5mEQ6.js.map} +1 -1
- package/dist/cdn/chunks/{NumberWithSuffix-Bu_nHJuD.js → NumberWithSuffix-lqQlf0Uk.js} +2 -2
- package/dist/cdn/chunks/{NumberWithSuffix-Bu_nHJuD.js.map → NumberWithSuffix-lqQlf0Uk.js.map} +1 -1
- package/dist/cdn/chunks/{ParagraphEditor-IpZsg8qo.js → ParagraphEditor-BYoZfURd.js} +6 -6
- package/dist/cdn/chunks/{ParagraphEditor-IpZsg8qo.js.map → ParagraphEditor-BYoZfURd.js.map} +1 -1
- package/dist/cdn/chunks/{RichTextEditorContent-DDnqZ9cB.js → RichTextEditorContent-BnPRnXxy.js} +3 -3
- package/dist/cdn/chunks/{RichTextEditorContent-DDnqZ9cB.js.map → RichTextEditorContent-BnPRnXxy.js.map} +1 -1
- package/dist/cdn/chunks/{SaveModuleDialog-CVA5HPCi.js → SaveModuleDialog-C9hUeWyG.js} +2 -2
- package/dist/cdn/chunks/{SaveModuleDialog-CVA5HPCi.js.map → SaveModuleDialog-C9hUeWyG.js.map} +1 -1
- package/dist/cdn/chunks/{TitleEditor-DU8wm0Rh.js → TitleEditor-wFvnU3Jr.js} +5 -5
- package/dist/cdn/chunks/{TitleEditor-DU8wm0Rh.js.map → TitleEditor-wFvnU3Jr.js.map} +1 -1
- package/dist/cdn/chunks/{blockTypeIcons-Dm5Oosjp.js → blockTypeIcons-DNMvDz5B.js} +3 -3
- package/dist/cdn/chunks/{blockTypeIcons-Dm5Oosjp.js.map → blockTypeIcons-DNMvDz5B.js.map} +1 -1
- package/dist/cdn/chunks/{ca-DI1ViqMa.js → ca-CSl--oWR.js} +2 -2
- package/dist/cdn/chunks/ca-CSl--oWR.js.map +1 -0
- package/dist/{de-q9lTCMre.js → cdn/chunks/de-ZaffrKDP.js} +3 -1
- package/dist/cdn/chunks/de-ZaffrKDP.js.map +1 -0
- package/dist/cdn/chunks/{en-CR4LItrX.js → en-CHuXeJDt.js} +2 -2
- package/dist/cdn/chunks/en-CHuXeJDt.js.map +1 -0
- package/dist/cdn/chunks/{es-CEt-lrGd.js → es-CaC8VQjO.js} +2 -2
- package/dist/cdn/chunks/es-CaC8VQjO.js.map +1 -0
- package/dist/cdn/chunks/{extensions-BGUoo2a5.js → extensions-DxcxIlwT.js} +2 -2
- package/dist/cdn/chunks/{extensions-BGUoo2a5.js.map → extensions-DxcxIlwT.js.map} +1 -1
- package/dist/cdn/chunks/{features-BSpDuFFR.js → features-B3qgDBHf.js} +702 -671
- package/dist/cdn/chunks/features-B3qgDBHf.js.map +1 -0
- package/dist/cdn/chunks/{icons-k3XVoRvc.js → icons-kiMqh99T.js} +2 -2
- package/dist/cdn/chunks/{icons-k3XVoRvc.js.map → icons-kiMqh99T.js.map} +1 -1
- package/dist/cdn/chunks/{media-library-iDq3otm6.js → media-library-C5ogiZ4f.js} +3 -3
- package/dist/cdn/chunks/{media-library-iDq3otm6.js.map → media-library-C5ogiZ4f.js.map} +1 -1
- package/dist/cdn/chunks/{pt-BR-DvBHY0AA.js → pt-BR-C74zfEWH.js} +2 -2
- package/dist/cdn/chunks/pt-BR-C74zfEWH.js.map +1 -0
- package/dist/cdn/chunks/{quality-Bb7vN32U.js → quality-BftAn_AJ.js} +2 -2
- package/dist/cdn/chunks/{quality-Bb7vN32U.js.map → quality-BftAn_AJ.js.map} +1 -1
- package/dist/cdn/chunks/{renderer-cOvtk8HM.js → renderer-Cdlo4MVX.js} +3 -3
- package/dist/cdn/chunks/{renderer-cOvtk8HM.js.map → renderer-Cdlo4MVX.js.map} +1 -1
- package/dist/cdn/chunks/{src-Ddp969zE.js → src-GBA8oUL2.js} +4 -4
- package/dist/cdn/chunks/{src-Ddp969zE.js.map → src-GBA8oUL2.js.map} +1 -1
- package/dist/cdn/chunks/{styles-CW_gRVVR.js → styles-B6rdq9JB.js} +9 -9
- package/dist/cdn/chunks/{styles-CW_gRVVR.js.map → styles-B6rdq9JB.js.map} +1 -1
- package/dist/cdn/editor.css +1 -1
- package/dist/cdn/editor.js +13 -12
- package/dist/cdn/editor.js.map +1 -1
- package/dist/{cdn/chunks/de-q9lTCMre.js → de-ZaffrKDP.js} +1 -3
- package/dist/{en-CR4LItrX.js → en-CHuXeJDt.js} +1 -1
- package/dist/{es-CEt-lrGd.js → es-CaC8VQjO.js} +1 -1
- package/dist/{extensions-Cjd-VAII.js → extensions-B4lu0KkE.js} +2 -2
- package/dist/index.d.ts +44 -0
- package/dist/keys-WVNarXg8.js +10 -0
- package/dist/{pt-BR-DvBHY0AA.js → pt-BR-C74zfEWH.js} +1 -1
- package/dist/style.css +1 -1
- package/dist/{styles-DJfTblY7.js → styles-mBSbDYeX.js} +25 -25
- package/dist/templatical-editor.js +11 -10
- package/dist/{useCloudI18n-WbfVWq5k.js → useCloudI18n-CIKI0hCd.js} +1 -1
- package/dist/{useEditorCore-DnOG2a_b.js → useEditorCore-CaaHPKjm.js} +703 -672
- package/dist/{useI18n-eR1yVW0v.js → useI18n-0EU_JVe7.js} +1 -1
- package/dist/{useMergeTag-C3GfSktg.js → useMergeTag-C7v6MVah.js} +2 -2
- package/dist/{usePopoverPosition-B3Byo68F.js → usePopoverPosition-BDqqnMeo.js} +1 -1
- package/package.json +7 -7
- package/dist/cdn/chunks/CloudEditor-1Ms0w691.js.map +0 -1
- package/dist/cdn/chunks/ca-DI1ViqMa.js.map +0 -1
- package/dist/cdn/chunks/de-q9lTCMre.js.map +0 -1
- package/dist/cdn/chunks/en-CR4LItrX.js.map +0 -1
- package/dist/cdn/chunks/es-CEt-lrGd.js.map +0 -1
- package/dist/cdn/chunks/features-BSpDuFFR.js.map +0 -1
- package/dist/cdn/chunks/pt-BR-DvBHY0AA.js.map +0 -1
- package/dist/keys-BbDgCU6K.js +0 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src-Ddp969zE.js","names":[],"sources":["../../../../media-library/src/standalone/MediaLibrary.vue","../../../../media-library/src/standalone/MediaLibrary.vue","../../../../media-library/src/i18n/index.ts","../../../../media-library/src/standalone/visual.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport MediaBreadcrumb from \"../components/media/MediaBreadcrumb.vue\";\nimport MediaEditModal from \"../components/media/MediaEditModal.vue\";\nimport MediaFolderTree from \"../components/media/MediaFolderTree.vue\";\nimport MediaGrid from \"../components/media/MediaGrid.vue\";\nimport MediaImportUrlModal from \"../components/media/MediaImportUrlModal.vue\";\nimport MediaMovePicker from \"../components/media/MediaMovePicker.vue\";\nimport MediaPreviewPanel from \"../components/media/MediaPreviewPanel.vue\";\nimport MediaReplaceModal from \"../components/media/MediaReplaceModal.vue\";\nimport MediaUploadZone from \"../components/media/MediaUploadZone.vue\";\nimport StorageProgressRing from \"../components/media/StorageProgressRing.vue\";\nimport { useMediaLibrary } from \"../composable\";\nimport { useMediaCategories } from \"../composables/useMediaCategories\";\nimport { useMediaLibraryUI } from \"../composables/useMediaLibraryUI\";\nimport type { PlanConfig, PlanFeatures } from \"@templatical/types\";\nimport type { MediaItem } from \"../types\";\nimport type { AuthManager } from \"@templatical/core/cloud\";\nimport type { MediaTranslations } from \"../i18n\";\nimport {\n Check,\n Copy,\n Grid2x2,\n Link,\n List,\n PanelLeft,\n Search,\n} from \"@lucide/vue\";\nimport { computed, onMounted, provide, ref } from \"vue\";\n\nconst props = defineProps<{\n authManager: AuthManager;\n projectId: string;\n planConfig: PlanConfig;\n translations: MediaTranslations;\n onSelect?: (item: MediaItem) => void;\n onError?: (error: Error) => void;\n}>();\n\nconst emit = defineEmits<{\n (e: \"ready\"): void;\n}>();\n\nconst t = computed(() => props.translations);\n\n// Provide translations for sub-components that use inject('translations')\nprovide(\"translations\", props.translations);\nprovide(\"authManager\", props.authManager);\nprovide(\n \"projectId\",\n computed(() => props.projectId),\n);\n\n// Provide planConfig in the format that sub-components expect\nconst planConfigRef = ref<PlanConfig | null>(props.planConfig);\nprovide(\"planConfig\", {\n config: planConfigRef,\n isLoading: ref(false),\n hasFeature: (feature: keyof PlanFeatures) =>\n props.planConfig.features[feature] ?? false,\n features: computed(() => props.planConfig.features),\n fetchConfig: async () => {},\n});\n\n// Feature flags\nconst canUseMediaFolders = computed(\n () => props.planConfig.features.media_folders ?? false,\n);\nconst canImportFromUrl = computed(\n () => props.planConfig.features.import_from_url ?? false,\n);\n\n// Storage info\nconst storageUsedBytes = computed(\n () => props.planConfig.storage.used_bytes ?? 0,\n);\nconst storageLimitBytes = computed(\n () => props.planConfig.storage.limit_bytes ?? 0,\n);\n\nconst { availableCategories } = useMediaCategories();\n\nconst library = useMediaLibrary({\n projectId: props.projectId,\n authManager: props.authManager,\n onError: props.onError,\n});\n\nconst ui = useMediaLibraryUI({\n library,\n canUseMediaFolders,\n translations: t,\n});\n\n// Standalone-specific: confirm selection via callback\nfunction confirmSelection(): void {\n if (!library.previewItem.value) {\n return;\n }\n\n const item = library.previewItem.value;\n const itemWithSelectedUrl: MediaItem = {\n ...item,\n url: ui.selectedUrl.value || item.url,\n };\n props.onSelect?.(itemWithSelectedUrl);\n}\n\nonMounted(() => {\n library.loadItems();\n library.loadFrequentlyUsed();\n emit(\"ready\");\n});\n</script>\n\n<template>\n <div\n class=\"tpl tpl:flex tpl:flex-col tpl:overflow-hidden tpl:rounded-[var(--tpl-radius-lg)]\"\n style=\"\n width: 100%;\n height: 100%;\n background-color: var(--tpl-bg-elevated);\n border: 1px solid var(--tpl-border);\n \"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-b tpl:px-5 tpl:py-3.5\"\n style=\"border-color: var(--tpl-border)\"\n >\n <h2 class=\"tpl:text-sm tpl:font-semibold\" style=\"color: var(--tpl-text)\">\n {{ t.mediaLibrary.title }}\n </h2>\n <div class=\"tpl:flex tpl:items-center tpl:gap-3\">\n <StorageProgressRing\n :used-bytes=\"storageUsedBytes\"\n :limit-bytes=\"storageLimitBytes\"\n :size=\"22\"\n />\n <div class=\"tpl:relative\">\n <input\n :value=\"ui.searchInput.value\"\n type=\"text\"\n class=\"tpl:w-52 tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-3 tpl:pl-8 tpl:text-xs tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:outline-none tpl:focus:shadow-[var(--tpl-ring)]\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :placeholder=\"t.mediaLibrary.searchPlaceholder\"\n @input=\"\n ui.handleSearchInput(($event.target as HTMLInputElement).value)\n \"\n />\n <Search\n class=\"tpl:absolute tpl:top-1/2 tpl:left-2.5 tpl:-translate-y-1/2\"\n :size=\"13\"\n :stroke-width=\"2\"\n style=\"color: var(--tpl-text-dim)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"tpl:flex tpl:min-h-0 tpl:flex-1 tpl:overflow-hidden\">\n <!-- Sidebar (only when media folders feature is enabled and toggled on) -->\n <Transition\n enter-active-class=\"tpl:transition-all tpl:duration-200 tpl:ease-out\"\n enter-from-class=\"tpl:-ml-48 tpl:opacity-0\"\n enter-to-class=\"tpl:ml-0 tpl:opacity-100\"\n leave-active-class=\"tpl:transition-all tpl:duration-150 tpl:ease-in\"\n leave-from-class=\"tpl:ml-0 tpl:opacity-100\"\n leave-to-class=\"tpl:-ml-48 tpl:opacity-0\"\n >\n <div\n v-if=\"canUseMediaFolders && ui.showSidebar.value\"\n class=\"tpl:flex tpl:w-48 tpl:shrink-0 tpl:flex-col tpl:border-r\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n \"\n >\n <MediaFolderTree\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n :view-mode=\"library.viewMode.value\"\n :has-frequently-used=\"ui.hasFrequentlyUsed.value\"\n @navigate=\"library.navigateToFolder\"\n @create-folder=\"ui.handleCreateFolder\"\n @rename-folder=\"ui.handleRenameFolder\"\n @delete-folder=\"ui.handleDeleteFolder\"\n @show-frequently-used=\"library.showFrequentlyUsed\"\n />\n </div>\n </Transition>\n\n <!-- Content area -->\n <div class=\"tpl:flex tpl:min-w-0 tpl:flex-1 tpl:flex-col\">\n <!-- Breadcrumb + Upload -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-b tpl:px-4 tpl:py-2.5\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <!-- Sidebar toggle (only when media folders feature is enabled) -->\n <button\n v-if=\"canUseMediaFolders\"\n class=\"tpl:flex tpl:size-7 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-md tpl:transition-all tpl:duration-150\"\n :style=\"{\n color: ui.showSidebar.value\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor: ui.showSidebar.value\n ? 'var(--tpl-bg)'\n : 'transparent',\n border: ui.showSidebar.value\n ? '1px solid var(--tpl-border)'\n : '1px solid transparent',\n }\"\n :title=\"\n ui.showSidebar.value\n ? t.mediaLibrary.hideFolders\n : t.mediaLibrary.showFolders\n \"\n @click=\"ui.showSidebar.value = !ui.showSidebar.value\"\n >\n <PanelLeft :size=\"16\" :stroke-width=\"2\" />\n </button>\n\n <template v-if=\"library.viewMode.value === 'frequently-used'\">\n <span\n class=\"tpl:text-xs tpl:font-medium\"\n style=\"color: var(--tpl-text)\"\n >\n {{ t.mediaLibrary.frequentlyUsed }}\n </span>\n </template>\n <template v-else>\n <MediaBreadcrumb\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n @navigate=\"library.navigateToFolder\"\n />\n </template>\n\n <!-- Layout toggle -->\n <div\n class=\"tpl:flex tpl:rounded-md tpl:p-0.5\"\n style=\"\n border: 1px solid var(--tpl-border);\n background-color: var(--tpl-bg);\n \"\n >\n <button\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:transition-all tpl:duration-150\"\n :style=\"{\n color:\n ui.layoutMode.value === 'grid'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor:\n ui.layoutMode.value === 'grid'\n ? 'var(--tpl-bg-elevated)'\n : 'transparent',\n }\"\n :title=\"t.mediaLibrary.viewGrid\"\n @click=\"ui.layoutMode.value = 'grid'\"\n >\n <Grid2x2 :size=\"14\" :stroke-width=\"2\" />\n </button>\n <button\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:transition-all tpl:duration-150\"\n :style=\"{\n color:\n ui.layoutMode.value === 'list'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor:\n ui.layoutMode.value === 'list'\n ? 'var(--tpl-bg-elevated)'\n : 'transparent',\n }\"\n :title=\"t.mediaLibrary.viewList\"\n @click=\"ui.layoutMode.value = 'list'\"\n >\n <List :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <select\n v-if=\"availableCategories.length > 1\"\n class=\"tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-7 tpl:pl-2.5 tpl:text-xs tpl:transition-all tpl:duration-150 tpl:outline-none\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :value=\"library.categoryFilter.value ?? ''\"\n @change=\"\n library.filterByCategory(\n ($event.target as HTMLSelectElement).value || null,\n )\n \"\n >\n <option value=\"\">\n {{ t.mediaLibrary.filterAll }}\n </option>\n <option\n v-for=\"category in availableCategories\"\n :key=\"category\"\n :value=\"category\"\n >\n {{ ui.getCategoryLabel(category) }}\n </option>\n </select>\n <select\n class=\"tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-7 tpl:pl-2.5 tpl:text-xs tpl:transition-all tpl:duration-150 tpl:outline-none\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :value=\"library.sortOption.value\"\n @change=\"\n library.sortBy(($event.target as HTMLSelectElement).value)\n \"\n >\n <option value=\"newest\">\n {{ t.mediaLibrary.sortNewest }}\n </option>\n <option value=\"oldest\">\n {{ t.mediaLibrary.sortOldest }}\n </option>\n <option value=\"name_asc\">\n {{ t.mediaLibrary.sortNameAsc }}\n </option>\n <option value=\"name_desc\">\n {{ t.mediaLibrary.sortNameDesc }}\n </option>\n <option value=\"size_asc\">\n {{ t.mediaLibrary.sortSizeAsc }}\n </option>\n <option value=\"size_desc\">\n {{ t.mediaLibrary.sortSizeDesc }}\n </option>\n </select>\n </div>\n </div>\n\n <!-- Scrollable content area -->\n <div class=\"tpl:min-h-0 tpl:flex-1 tpl:overflow-y-auto\">\n <!-- Upload zone (only in files mode) -->\n <div\n v-if=\"library.viewMode.value === 'files'\"\n class=\"tpl:px-4 tpl:pt-3\"\n >\n <MediaUploadZone\n :is-uploading=\"library.isUploading.value\"\n :upload-progress=\"library.uploadProgress.value\"\n @upload=\"ui.handleUpload\"\n />\n <button\n v-if=\"canImportFromUrl\"\n class=\"tpl:mt-2 tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-md tpl:border tpl:border-dashed tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text-muted);\n background-color: var(--tpl-bg);\n \"\n @click=\"ui.showImportUrlModal.value = true\"\n >\n <Link :size=\"14\" :stroke-width=\"2\" />\n {{ t.mediaLibrary.importFromUrl }}\n </button>\n </div>\n\n <!-- Image grid -->\n <MediaGrid\n :items=\"ui.displayItems.value\"\n :selected-ids=\"library.selectedItems.value\"\n :is-loading=\"library.isLoading.value\"\n :has-more=\"\n library.viewMode.value === 'files' && library.hasMore.value\n \"\n :layout=\"ui.layoutMode.value\"\n @select=\"ui.handleSelect\"\n @toggle=\"library.toggleSelection\"\n @load-more=\"library.loadMore\"\n @edit=\"ui.handleEditItem\"\n @replace=\"ui.handleReplaceItem\"\n />\n </div>\n </div>\n </div>\n\n <!-- Import from URL Modal -->\n <MediaImportUrlModal\n :visible=\"ui.showImportUrlModal.value\"\n :is-importing=\"library.isImportingFromUrl.value\"\n :error=\"library.importFromUrlError.value\"\n @import=\"ui.handleImportFromUrl\"\n @close=\"ui.showImportUrlModal.value = false\"\n />\n\n <!-- Edit Modal -->\n <MediaEditModal\n :visible=\"!!ui.editingItem.value\"\n :item=\"ui.editingItem.value\"\n @save=\"ui.handleEditSave\"\n @close=\"ui.editingItem.value = null\"\n />\n\n <!-- Replace Modal -->\n <MediaReplaceModal\n :visible=\"library.showReplaceWarning.value\"\n :item=\"library.pendingReplaceItem.value\"\n :usage-info=\"library.replaceUsageInfo.value\"\n :is-replacing=\"library.isReplacing.value\"\n :error=\"library.replaceError.value\"\n @replace=\"ui.handleReplaceFile\"\n @close=\"library.cancelReplace\"\n />\n\n <!-- Delete Warning Dialog -->\n <Transition\n enter-active-class=\"tpl:transition tpl:ease-out tpl:duration-150\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:ease-in tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <div\n v-if=\"library.showDeleteWarning.value\"\n class=\"tpl:absolute tpl:inset-0 tpl:z-10 tpl:flex tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-lg)]\"\n style=\"\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n @click.self=\"library.cancelDelete\"\n >\n <div\n class=\"tpl-scale-in tpl:mx-4 tpl:w-full tpl:max-w-sm tpl:rounded-[var(--tpl-radius-lg)] tpl:p-5\"\n style=\"\n background-color: var(--tpl-bg-elevated);\n box-shadow: var(--tpl-shadow-xl);\n \"\n >\n <h3\n class=\"tpl:mb-2 tpl:text-sm tpl:font-semibold\"\n style=\"color: var(--tpl-text)\"\n >\n {{ t.mediaLibrary.deleteWarningTitle }}\n </h3>\n <p\n class=\"tpl:text-xs\"\n :class=\"ui.hasUsedFiles.value ? 'tpl:mb-2' : 'tpl:mb-4'\"\n style=\"color: var(--tpl-text-muted)\"\n >\n {{ t.mediaLibrary.deleteWarningMessage }}\n </p>\n <p\n v-if=\"ui.hasUsedFiles.value\"\n class=\"tpl:mb-4 tpl:text-xs\"\n style=\"color: var(--tpl-text-muted)\"\n >\n {{ t.mediaLibrary.deleteWarningUsageNote }}\n </p>\n\n <div\n v-if=\"ui.hasUsedFiles.value\"\n class=\"tpl:mb-4 tpl:max-h-32 tpl:overflow-y-auto tpl:rounded tpl:border tpl:p-2\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div\n v-for=\"(info, mediaId) in library.deleteUsageInfo.value\"\n :key=\"mediaId\"\n class=\"tpl:text-xs\"\n style=\"color: var(--tpl-text)\"\n >\n <template v-if=\"info.template_count > 0\">\n <span class=\"tpl:font-medium\">\n {{\n ui.displayItems.value.find((i) => i.id === mediaId)\n ?.filename || mediaId\n }}\n </span>\n <span style=\"color: var(--tpl-text-muted)\">\n -\n {{\n t.mediaLibrary.usedInTemplates.replace(\n \"{count}\",\n info.template_count.toString(),\n )\n }}\n </span>\n </template>\n </div>\n </div>\n\n <div class=\"tpl:flex tpl:justify-end tpl:gap-2\">\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text);\n background-color: var(--tpl-bg);\n \"\n @click=\"library.cancelDelete\"\n >\n {{ t.mediaLibrary.cancel }}\n </button>\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-danger);\n color: var(--tpl-danger);\n background-color: var(--tpl-danger-light);\n \"\n @click=\"library.confirmDelete\"\n >\n {{\n ui.hasUsedFiles.value\n ? t.mediaLibrary.deleteAnyway\n : t.mediaLibrary.confirmDelete\n }}\n </button>\n </div>\n </div>\n </div>\n </Transition>\n\n <!-- Footer -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-t tpl:px-5 tpl:py-3\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div class=\"tpl:flex tpl:min-w-0 tpl:flex-1 tpl:items-center tpl:gap-3\">\n <MediaPreviewPanel\n v-if=\"library.previewItem.value\"\n v-model:selected-conversion=\"ui.selectedConversion.value\"\n :item=\"library.previewItem.value\"\n :folders=\"library.folders.value\"\n />\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-5\">\n <!-- Copy URL + Move group -->\n <div\n v-if=\"library.selectedItems.value.size > 0\"\n class=\"tpl:flex tpl:items-center tpl:gap-2\"\n >\n <button\n v-if=\"library.previewItem.value\"\n class=\"tpl:flex tpl:cursor-pointer tpl:items-center tpl:gap-1 tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n borderColor: ui.copied.value\n ? 'var(--tpl-success)'\n : 'var(--tpl-border)',\n color: ui.copied.value ? 'var(--tpl-success)' : 'var(--tpl-text)',\n backgroundColor: 'var(--tpl-bg)',\n }\"\n @click=\"ui.copy(ui.selectedUrl.value!)\"\n >\n <Copy v-if=\"!ui.copied.value\" :size=\"12\" :stroke-width=\"2\" />\n <Check v-else :size=\"12\" :stroke-width=\"2\" />\n {{\n ui.copied.value ? t.mediaLibrary.copied : t.mediaLibrary.copyUrl\n }}\n </button>\n <div v-if=\"canUseMediaFolders\" class=\"tpl:relative\">\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text);\n background-color: var(--tpl-bg);\n \"\n @click=\"ui.showMovePicker.value = !ui.showMovePicker.value\"\n >\n {{ t.mediaLibrary.moveSelected }}\n </button>\n <MediaMovePicker\n v-if=\"ui.showMovePicker.value\"\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n @select=\"ui.handleMoveToFolder\"\n @close=\"ui.showMovePicker.value = false\"\n />\n </div>\n </div>\n <!-- Delete + Select group -->\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <button\n v-if=\"library.selectedItems.value.size > 0\"\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-danger);\n color: var(--tpl-danger);\n background-color: var(--tpl-danger-light);\n \"\n @click=\"ui.handleDeleteClick\"\n >\n {{ t.mediaLibrary.deleteSelected }}\n </button>\n <button\n v-if=\"onSelect\"\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:px-4 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50\"\n style=\"background-color: var(--tpl-primary); color: var(--tpl-bg)\"\n :disabled=\"!library.previewItem.value\"\n @click=\"confirmSelection\"\n >\n {{ t.mediaLibrary.selectFile }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport MediaBreadcrumb from \"../components/media/MediaBreadcrumb.vue\";\nimport MediaEditModal from \"../components/media/MediaEditModal.vue\";\nimport MediaFolderTree from \"../components/media/MediaFolderTree.vue\";\nimport MediaGrid from \"../components/media/MediaGrid.vue\";\nimport MediaImportUrlModal from \"../components/media/MediaImportUrlModal.vue\";\nimport MediaMovePicker from \"../components/media/MediaMovePicker.vue\";\nimport MediaPreviewPanel from \"../components/media/MediaPreviewPanel.vue\";\nimport MediaReplaceModal from \"../components/media/MediaReplaceModal.vue\";\nimport MediaUploadZone from \"../components/media/MediaUploadZone.vue\";\nimport StorageProgressRing from \"../components/media/StorageProgressRing.vue\";\nimport { useMediaLibrary } from \"../composable\";\nimport { useMediaCategories } from \"../composables/useMediaCategories\";\nimport { useMediaLibraryUI } from \"../composables/useMediaLibraryUI\";\nimport type { PlanConfig, PlanFeatures } from \"@templatical/types\";\nimport type { MediaItem } from \"../types\";\nimport type { AuthManager } from \"@templatical/core/cloud\";\nimport type { MediaTranslations } from \"../i18n\";\nimport {\n Check,\n Copy,\n Grid2x2,\n Link,\n List,\n PanelLeft,\n Search,\n} from \"@lucide/vue\";\nimport { computed, onMounted, provide, ref } from \"vue\";\n\nconst props = defineProps<{\n authManager: AuthManager;\n projectId: string;\n planConfig: PlanConfig;\n translations: MediaTranslations;\n onSelect?: (item: MediaItem) => void;\n onError?: (error: Error) => void;\n}>();\n\nconst emit = defineEmits<{\n (e: \"ready\"): void;\n}>();\n\nconst t = computed(() => props.translations);\n\n// Provide translations for sub-components that use inject('translations')\nprovide(\"translations\", props.translations);\nprovide(\"authManager\", props.authManager);\nprovide(\n \"projectId\",\n computed(() => props.projectId),\n);\n\n// Provide planConfig in the format that sub-components expect\nconst planConfigRef = ref<PlanConfig | null>(props.planConfig);\nprovide(\"planConfig\", {\n config: planConfigRef,\n isLoading: ref(false),\n hasFeature: (feature: keyof PlanFeatures) =>\n props.planConfig.features[feature] ?? false,\n features: computed(() => props.planConfig.features),\n fetchConfig: async () => {},\n});\n\n// Feature flags\nconst canUseMediaFolders = computed(\n () => props.planConfig.features.media_folders ?? false,\n);\nconst canImportFromUrl = computed(\n () => props.planConfig.features.import_from_url ?? false,\n);\n\n// Storage info\nconst storageUsedBytes = computed(\n () => props.planConfig.storage.used_bytes ?? 0,\n);\nconst storageLimitBytes = computed(\n () => props.planConfig.storage.limit_bytes ?? 0,\n);\n\nconst { availableCategories } = useMediaCategories();\n\nconst library = useMediaLibrary({\n projectId: props.projectId,\n authManager: props.authManager,\n onError: props.onError,\n});\n\nconst ui = useMediaLibraryUI({\n library,\n canUseMediaFolders,\n translations: t,\n});\n\n// Standalone-specific: confirm selection via callback\nfunction confirmSelection(): void {\n if (!library.previewItem.value) {\n return;\n }\n\n const item = library.previewItem.value;\n const itemWithSelectedUrl: MediaItem = {\n ...item,\n url: ui.selectedUrl.value || item.url,\n };\n props.onSelect?.(itemWithSelectedUrl);\n}\n\nonMounted(() => {\n library.loadItems();\n library.loadFrequentlyUsed();\n emit(\"ready\");\n});\n</script>\n\n<template>\n <div\n class=\"tpl tpl:flex tpl:flex-col tpl:overflow-hidden tpl:rounded-[var(--tpl-radius-lg)]\"\n style=\"\n width: 100%;\n height: 100%;\n background-color: var(--tpl-bg-elevated);\n border: 1px solid var(--tpl-border);\n \"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-b tpl:px-5 tpl:py-3.5\"\n style=\"border-color: var(--tpl-border)\"\n >\n <h2 class=\"tpl:text-sm tpl:font-semibold\" style=\"color: var(--tpl-text)\">\n {{ t.mediaLibrary.title }}\n </h2>\n <div class=\"tpl:flex tpl:items-center tpl:gap-3\">\n <StorageProgressRing\n :used-bytes=\"storageUsedBytes\"\n :limit-bytes=\"storageLimitBytes\"\n :size=\"22\"\n />\n <div class=\"tpl:relative\">\n <input\n :value=\"ui.searchInput.value\"\n type=\"text\"\n class=\"tpl:w-52 tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-3 tpl:pl-8 tpl:text-xs tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:outline-none tpl:focus:shadow-[var(--tpl-ring)]\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :placeholder=\"t.mediaLibrary.searchPlaceholder\"\n @input=\"\n ui.handleSearchInput(($event.target as HTMLInputElement).value)\n \"\n />\n <Search\n class=\"tpl:absolute tpl:top-1/2 tpl:left-2.5 tpl:-translate-y-1/2\"\n :size=\"13\"\n :stroke-width=\"2\"\n style=\"color: var(--tpl-text-dim)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"tpl:flex tpl:min-h-0 tpl:flex-1 tpl:overflow-hidden\">\n <!-- Sidebar (only when media folders feature is enabled and toggled on) -->\n <Transition\n enter-active-class=\"tpl:transition-all tpl:duration-200 tpl:ease-out\"\n enter-from-class=\"tpl:-ml-48 tpl:opacity-0\"\n enter-to-class=\"tpl:ml-0 tpl:opacity-100\"\n leave-active-class=\"tpl:transition-all tpl:duration-150 tpl:ease-in\"\n leave-from-class=\"tpl:ml-0 tpl:opacity-100\"\n leave-to-class=\"tpl:-ml-48 tpl:opacity-0\"\n >\n <div\n v-if=\"canUseMediaFolders && ui.showSidebar.value\"\n class=\"tpl:flex tpl:w-48 tpl:shrink-0 tpl:flex-col tpl:border-r\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n \"\n >\n <MediaFolderTree\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n :view-mode=\"library.viewMode.value\"\n :has-frequently-used=\"ui.hasFrequentlyUsed.value\"\n @navigate=\"library.navigateToFolder\"\n @create-folder=\"ui.handleCreateFolder\"\n @rename-folder=\"ui.handleRenameFolder\"\n @delete-folder=\"ui.handleDeleteFolder\"\n @show-frequently-used=\"library.showFrequentlyUsed\"\n />\n </div>\n </Transition>\n\n <!-- Content area -->\n <div class=\"tpl:flex tpl:min-w-0 tpl:flex-1 tpl:flex-col\">\n <!-- Breadcrumb + Upload -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-b tpl:px-4 tpl:py-2.5\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <!-- Sidebar toggle (only when media folders feature is enabled) -->\n <button\n v-if=\"canUseMediaFolders\"\n class=\"tpl:flex tpl:size-7 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-md tpl:transition-all tpl:duration-150\"\n :style=\"{\n color: ui.showSidebar.value\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor: ui.showSidebar.value\n ? 'var(--tpl-bg)'\n : 'transparent',\n border: ui.showSidebar.value\n ? '1px solid var(--tpl-border)'\n : '1px solid transparent',\n }\"\n :title=\"\n ui.showSidebar.value\n ? t.mediaLibrary.hideFolders\n : t.mediaLibrary.showFolders\n \"\n @click=\"ui.showSidebar.value = !ui.showSidebar.value\"\n >\n <PanelLeft :size=\"16\" :stroke-width=\"2\" />\n </button>\n\n <template v-if=\"library.viewMode.value === 'frequently-used'\">\n <span\n class=\"tpl:text-xs tpl:font-medium\"\n style=\"color: var(--tpl-text)\"\n >\n {{ t.mediaLibrary.frequentlyUsed }}\n </span>\n </template>\n <template v-else>\n <MediaBreadcrumb\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n @navigate=\"library.navigateToFolder\"\n />\n </template>\n\n <!-- Layout toggle -->\n <div\n class=\"tpl:flex tpl:rounded-md tpl:p-0.5\"\n style=\"\n border: 1px solid var(--tpl-border);\n background-color: var(--tpl-bg);\n \"\n >\n <button\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:transition-all tpl:duration-150\"\n :style=\"{\n color:\n ui.layoutMode.value === 'grid'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor:\n ui.layoutMode.value === 'grid'\n ? 'var(--tpl-bg-elevated)'\n : 'transparent',\n }\"\n :title=\"t.mediaLibrary.viewGrid\"\n @click=\"ui.layoutMode.value = 'grid'\"\n >\n <Grid2x2 :size=\"14\" :stroke-width=\"2\" />\n </button>\n <button\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:transition-all tpl:duration-150\"\n :style=\"{\n color:\n ui.layoutMode.value === 'list'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor:\n ui.layoutMode.value === 'list'\n ? 'var(--tpl-bg-elevated)'\n : 'transparent',\n }\"\n :title=\"t.mediaLibrary.viewList\"\n @click=\"ui.layoutMode.value = 'list'\"\n >\n <List :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <select\n v-if=\"availableCategories.length > 1\"\n class=\"tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-7 tpl:pl-2.5 tpl:text-xs tpl:transition-all tpl:duration-150 tpl:outline-none\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :value=\"library.categoryFilter.value ?? ''\"\n @change=\"\n library.filterByCategory(\n ($event.target as HTMLSelectElement).value || null,\n )\n \"\n >\n <option value=\"\">\n {{ t.mediaLibrary.filterAll }}\n </option>\n <option\n v-for=\"category in availableCategories\"\n :key=\"category\"\n :value=\"category\"\n >\n {{ ui.getCategoryLabel(category) }}\n </option>\n </select>\n <select\n class=\"tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-7 tpl:pl-2.5 tpl:text-xs tpl:transition-all tpl:duration-150 tpl:outline-none\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :value=\"library.sortOption.value\"\n @change=\"\n library.sortBy(($event.target as HTMLSelectElement).value)\n \"\n >\n <option value=\"newest\">\n {{ t.mediaLibrary.sortNewest }}\n </option>\n <option value=\"oldest\">\n {{ t.mediaLibrary.sortOldest }}\n </option>\n <option value=\"name_asc\">\n {{ t.mediaLibrary.sortNameAsc }}\n </option>\n <option value=\"name_desc\">\n {{ t.mediaLibrary.sortNameDesc }}\n </option>\n <option value=\"size_asc\">\n {{ t.mediaLibrary.sortSizeAsc }}\n </option>\n <option value=\"size_desc\">\n {{ t.mediaLibrary.sortSizeDesc }}\n </option>\n </select>\n </div>\n </div>\n\n <!-- Scrollable content area -->\n <div class=\"tpl:min-h-0 tpl:flex-1 tpl:overflow-y-auto\">\n <!-- Upload zone (only in files mode) -->\n <div\n v-if=\"library.viewMode.value === 'files'\"\n class=\"tpl:px-4 tpl:pt-3\"\n >\n <MediaUploadZone\n :is-uploading=\"library.isUploading.value\"\n :upload-progress=\"library.uploadProgress.value\"\n @upload=\"ui.handleUpload\"\n />\n <button\n v-if=\"canImportFromUrl\"\n class=\"tpl:mt-2 tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-md tpl:border tpl:border-dashed tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text-muted);\n background-color: var(--tpl-bg);\n \"\n @click=\"ui.showImportUrlModal.value = true\"\n >\n <Link :size=\"14\" :stroke-width=\"2\" />\n {{ t.mediaLibrary.importFromUrl }}\n </button>\n </div>\n\n <!-- Image grid -->\n <MediaGrid\n :items=\"ui.displayItems.value\"\n :selected-ids=\"library.selectedItems.value\"\n :is-loading=\"library.isLoading.value\"\n :has-more=\"\n library.viewMode.value === 'files' && library.hasMore.value\n \"\n :layout=\"ui.layoutMode.value\"\n @select=\"ui.handleSelect\"\n @toggle=\"library.toggleSelection\"\n @load-more=\"library.loadMore\"\n @edit=\"ui.handleEditItem\"\n @replace=\"ui.handleReplaceItem\"\n />\n </div>\n </div>\n </div>\n\n <!-- Import from URL Modal -->\n <MediaImportUrlModal\n :visible=\"ui.showImportUrlModal.value\"\n :is-importing=\"library.isImportingFromUrl.value\"\n :error=\"library.importFromUrlError.value\"\n @import=\"ui.handleImportFromUrl\"\n @close=\"ui.showImportUrlModal.value = false\"\n />\n\n <!-- Edit Modal -->\n <MediaEditModal\n :visible=\"!!ui.editingItem.value\"\n :item=\"ui.editingItem.value\"\n @save=\"ui.handleEditSave\"\n @close=\"ui.editingItem.value = null\"\n />\n\n <!-- Replace Modal -->\n <MediaReplaceModal\n :visible=\"library.showReplaceWarning.value\"\n :item=\"library.pendingReplaceItem.value\"\n :usage-info=\"library.replaceUsageInfo.value\"\n :is-replacing=\"library.isReplacing.value\"\n :error=\"library.replaceError.value\"\n @replace=\"ui.handleReplaceFile\"\n @close=\"library.cancelReplace\"\n />\n\n <!-- Delete Warning Dialog -->\n <Transition\n enter-active-class=\"tpl:transition tpl:ease-out tpl:duration-150\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:ease-in tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <div\n v-if=\"library.showDeleteWarning.value\"\n class=\"tpl:absolute tpl:inset-0 tpl:z-10 tpl:flex tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-lg)]\"\n style=\"\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n @click.self=\"library.cancelDelete\"\n >\n <div\n class=\"tpl-scale-in tpl:mx-4 tpl:w-full tpl:max-w-sm tpl:rounded-[var(--tpl-radius-lg)] tpl:p-5\"\n style=\"\n background-color: var(--tpl-bg-elevated);\n box-shadow: var(--tpl-shadow-xl);\n \"\n >\n <h3\n class=\"tpl:mb-2 tpl:text-sm tpl:font-semibold\"\n style=\"color: var(--tpl-text)\"\n >\n {{ t.mediaLibrary.deleteWarningTitle }}\n </h3>\n <p\n class=\"tpl:text-xs\"\n :class=\"ui.hasUsedFiles.value ? 'tpl:mb-2' : 'tpl:mb-4'\"\n style=\"color: var(--tpl-text-muted)\"\n >\n {{ t.mediaLibrary.deleteWarningMessage }}\n </p>\n <p\n v-if=\"ui.hasUsedFiles.value\"\n class=\"tpl:mb-4 tpl:text-xs\"\n style=\"color: var(--tpl-text-muted)\"\n >\n {{ t.mediaLibrary.deleteWarningUsageNote }}\n </p>\n\n <div\n v-if=\"ui.hasUsedFiles.value\"\n class=\"tpl:mb-4 tpl:max-h-32 tpl:overflow-y-auto tpl:rounded tpl:border tpl:p-2\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div\n v-for=\"(info, mediaId) in library.deleteUsageInfo.value\"\n :key=\"mediaId\"\n class=\"tpl:text-xs\"\n style=\"color: var(--tpl-text)\"\n >\n <template v-if=\"info.template_count > 0\">\n <span class=\"tpl:font-medium\">\n {{\n ui.displayItems.value.find((i) => i.id === mediaId)\n ?.filename || mediaId\n }}\n </span>\n <span style=\"color: var(--tpl-text-muted)\">\n -\n {{\n t.mediaLibrary.usedInTemplates.replace(\n \"{count}\",\n info.template_count.toString(),\n )\n }}\n </span>\n </template>\n </div>\n </div>\n\n <div class=\"tpl:flex tpl:justify-end tpl:gap-2\">\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text);\n background-color: var(--tpl-bg);\n \"\n @click=\"library.cancelDelete\"\n >\n {{ t.mediaLibrary.cancel }}\n </button>\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-danger);\n color: var(--tpl-danger);\n background-color: var(--tpl-danger-light);\n \"\n @click=\"library.confirmDelete\"\n >\n {{\n ui.hasUsedFiles.value\n ? t.mediaLibrary.deleteAnyway\n : t.mediaLibrary.confirmDelete\n }}\n </button>\n </div>\n </div>\n </div>\n </Transition>\n\n <!-- Footer -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-t tpl:px-5 tpl:py-3\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div class=\"tpl:flex tpl:min-w-0 tpl:flex-1 tpl:items-center tpl:gap-3\">\n <MediaPreviewPanel\n v-if=\"library.previewItem.value\"\n v-model:selected-conversion=\"ui.selectedConversion.value\"\n :item=\"library.previewItem.value\"\n :folders=\"library.folders.value\"\n />\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-5\">\n <!-- Copy URL + Move group -->\n <div\n v-if=\"library.selectedItems.value.size > 0\"\n class=\"tpl:flex tpl:items-center tpl:gap-2\"\n >\n <button\n v-if=\"library.previewItem.value\"\n class=\"tpl:flex tpl:cursor-pointer tpl:items-center tpl:gap-1 tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n borderColor: ui.copied.value\n ? 'var(--tpl-success)'\n : 'var(--tpl-border)',\n color: ui.copied.value ? 'var(--tpl-success)' : 'var(--tpl-text)',\n backgroundColor: 'var(--tpl-bg)',\n }\"\n @click=\"ui.copy(ui.selectedUrl.value!)\"\n >\n <Copy v-if=\"!ui.copied.value\" :size=\"12\" :stroke-width=\"2\" />\n <Check v-else :size=\"12\" :stroke-width=\"2\" />\n {{\n ui.copied.value ? t.mediaLibrary.copied : t.mediaLibrary.copyUrl\n }}\n </button>\n <div v-if=\"canUseMediaFolders\" class=\"tpl:relative\">\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text);\n background-color: var(--tpl-bg);\n \"\n @click=\"ui.showMovePicker.value = !ui.showMovePicker.value\"\n >\n {{ t.mediaLibrary.moveSelected }}\n </button>\n <MediaMovePicker\n v-if=\"ui.showMovePicker.value\"\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n @select=\"ui.handleMoveToFolder\"\n @close=\"ui.showMovePicker.value = false\"\n />\n </div>\n </div>\n <!-- Delete + Select group -->\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <button\n v-if=\"library.selectedItems.value.size > 0\"\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-danger);\n color: var(--tpl-danger);\n background-color: var(--tpl-danger-light);\n \"\n @click=\"ui.handleDeleteClick\"\n >\n {{ t.mediaLibrary.deleteSelected }}\n </button>\n <button\n v-if=\"onSelect\"\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:px-4 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50\"\n style=\"background-color: var(--tpl-primary); color: var(--tpl-bg)\"\n :disabled=\"!library.previewItem.value\"\n @click=\"confirmSelection\"\n >\n {{ t.mediaLibrary.selectFile }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n","/// <reference types=\"vite/client\" />\n\nimport type en from \"./locales/en\";\n\nexport type MediaTranslations = typeof en;\n\n// Vite resolves this glob at build time. Adding a new locale file\n// automatically registers it — no array to keep in sync.\nconst localeModules = import.meta.glob<{ default: MediaTranslations }>(\n \"./locales/*.ts\",\n);\n\nfunction localesFromGlob(modules: Record<string, unknown>): string[] {\n return Object.keys(modules)\n .map((path) => path.match(/\\/([^/]+)\\.ts$/)?.[1])\n .filter((locale): locale is string => Boolean(locale));\n}\n\nconst supportedLocales = localesFromGlob(localeModules);\n\nfunction canonicalize(locale: string): string {\n return locale.trim().replace(/_/g, \"-\").toLowerCase();\n}\n\nfunction findSupportedLocale(locale: string): string | undefined {\n const canonical = canonicalize(locale);\n return supportedLocales.find((s) => canonicalize(s) === canonical);\n}\n\nfunction getBaseLocale(locale: string): string {\n return canonicalize(locale).split(\"-\")[0];\n}\n\nfunction resolveLocale(locale: string): string {\n return (\n findSupportedLocale(locale) ??\n findSupportedLocale(getBaseLocale(locale)) ??\n \"en\"\n );\n}\n\nexport async function loadMediaTranslations(\n locale: string,\n): Promise<MediaTranslations> {\n const target = resolveLocale(locale);\n const loader = localeModules[`./locales/${target}.ts`];\n const module = await loader();\n return module.default;\n}\n","import { createSdkAuthManager } from \"@templatical/core/cloud\";\nimport type { PlanConfig } from \"@templatical/types\";\nimport { ApiClient } from \"@templatical/core/cloud\";\nimport MediaLibrary from \"./MediaLibrary.vue\";\nimport { loadMediaTranslations, type MediaTranslations } from \"../i18n\";\nimport type { MediaLibraryConfig, MediaLibraryInstance } from \"./types\";\nimport { createApp, h, ref, type App, type Ref } from \"vue\";\n\n// Import SDK styles\nimport \"../styles/index.css\";\n\n// Re-export types for consumers\nexport type { MediaFolder, MediaItem } from \"../types\";\nexport type { MediaLibraryConfig, MediaLibraryInstance } from \"./types\";\n\nlet appInstance: App | null = null;\nconst mediaLibraryRef: Ref<InstanceType<typeof MediaLibrary> | null> =\n ref(null);\n\nasync function init(config: MediaLibraryConfig): Promise<MediaLibraryInstance> {\n const container =\n typeof config.container === \"string\"\n ? document.querySelector(config.container)\n : config.container;\n\n if (!container) {\n throw new Error(`Container element not found: ${config.container}`);\n }\n\n // Initialize auth\n const authManager = createSdkAuthManager(config.auth, config.onError);\n await authManager.initialize();\n\n // Fetch plan config\n const apiClient = new ApiClient(authManager);\n const planConfig: PlanConfig = await apiClient.fetchConfig();\n\n // Load translations\n const translations: MediaTranslations = await loadMediaTranslations(\n config.locale ?? \"en\",\n );\n\n // Apply theme overrides to container\n applyTheme(container as HTMLElement, config.theme);\n\n // Unmount any prior app *after* awaits so concurrent init() calls don't\n // both pass an early check while appInstance is still null and orphan\n // the first-mounted app.\n if (appInstance) {\n unmount();\n }\n\n return new Promise((resolve, reject) => {\n try {\n appInstance = createApp({\n setup() {\n const onReady = () => {\n const instance: MediaLibraryInstance = {\n setTheme: (theme) => applyTheme(container as HTMLElement, theme),\n unmount,\n };\n\n resolve(instance);\n };\n\n return () =>\n h(MediaLibrary, {\n authManager,\n projectId: authManager.projectId,\n planConfig,\n translations,\n onSelect: config.onSelect,\n onError: config.onError,\n ref: mediaLibraryRef,\n onReady,\n });\n },\n });\n\n appInstance.mount(container);\n } catch (error) {\n reject(error);\n }\n });\n}\n\nfunction unmount(): void {\n if (appInstance) {\n appInstance.unmount();\n appInstance = null;\n mediaLibraryRef.value = null;\n }\n}\n\nfunction applyTheme(\n container: HTMLElement,\n theme?: { primaryColor?: string; borderRadius?: number },\n): void {\n if (!theme) {\n return;\n }\n\n if (theme.primaryColor) {\n container.style.setProperty(\"--tpl-primary\", theme.primaryColor);\n }\n\n if (theme.borderRadius !== undefined) {\n container.style.setProperty(\"--tpl-radius\", `${theme.borderRadius}px`);\n container.style.setProperty(\n \"--tpl-radius-sm\",\n `${Math.max(0, theme.borderRadius - 3)}px`,\n );\n container.style.setProperty(\n \"--tpl-radius-lg\",\n `${theme.borderRadius + 4}px`,\n );\n }\n}\n\nconst TemplaticalMedia = {\n init,\n unmount,\n};\n\n// Assign to window for IIFE usage\nif (typeof window !== \"undefined\") {\n (\n window as unknown as Window & { TemplaticalMedia: typeof TemplaticalMedia }\n ).TemplaticalMedia = TemplaticalMedia;\n}\n\n// Named exports for destructured imports\nexport { init, unmount };\n\n// Default export for library mode\nexport default TemplaticalMedia;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"src-GBA8oUL2.js","names":[],"sources":["../../../../media-library/src/standalone/MediaLibrary.vue","../../../../media-library/src/standalone/MediaLibrary.vue","../../../../media-library/src/i18n/index.ts","../../../../media-library/src/standalone/visual.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport MediaBreadcrumb from \"../components/media/MediaBreadcrumb.vue\";\nimport MediaEditModal from \"../components/media/MediaEditModal.vue\";\nimport MediaFolderTree from \"../components/media/MediaFolderTree.vue\";\nimport MediaGrid from \"../components/media/MediaGrid.vue\";\nimport MediaImportUrlModal from \"../components/media/MediaImportUrlModal.vue\";\nimport MediaMovePicker from \"../components/media/MediaMovePicker.vue\";\nimport MediaPreviewPanel from \"../components/media/MediaPreviewPanel.vue\";\nimport MediaReplaceModal from \"../components/media/MediaReplaceModal.vue\";\nimport MediaUploadZone from \"../components/media/MediaUploadZone.vue\";\nimport StorageProgressRing from \"../components/media/StorageProgressRing.vue\";\nimport { useMediaLibrary } from \"../composable\";\nimport { useMediaCategories } from \"../composables/useMediaCategories\";\nimport { useMediaLibraryUI } from \"../composables/useMediaLibraryUI\";\nimport type { PlanConfig, PlanFeatures } from \"@templatical/types\";\nimport type { MediaItem } from \"../types\";\nimport type { AuthManager } from \"@templatical/core/cloud\";\nimport type { MediaTranslations } from \"../i18n\";\nimport {\n Check,\n Copy,\n Grid2x2,\n Link,\n List,\n PanelLeft,\n Search,\n} from \"@lucide/vue\";\nimport { computed, onMounted, provide, ref } from \"vue\";\n\nconst props = defineProps<{\n authManager: AuthManager;\n projectId: string;\n planConfig: PlanConfig;\n translations: MediaTranslations;\n onSelect?: (item: MediaItem) => void;\n onError?: (error: Error) => void;\n}>();\n\nconst emit = defineEmits<{\n (e: \"ready\"): void;\n}>();\n\nconst t = computed(() => props.translations);\n\n// Provide translations for sub-components that use inject('translations')\nprovide(\"translations\", props.translations);\nprovide(\"authManager\", props.authManager);\nprovide(\n \"projectId\",\n computed(() => props.projectId),\n);\n\n// Provide planConfig in the format that sub-components expect\nconst planConfigRef = ref<PlanConfig | null>(props.planConfig);\nprovide(\"planConfig\", {\n config: planConfigRef,\n isLoading: ref(false),\n hasFeature: (feature: keyof PlanFeatures) =>\n props.planConfig.features[feature] ?? false,\n features: computed(() => props.planConfig.features),\n fetchConfig: async () => {},\n});\n\n// Feature flags\nconst canUseMediaFolders = computed(\n () => props.planConfig.features.media_folders ?? false,\n);\nconst canImportFromUrl = computed(\n () => props.planConfig.features.import_from_url ?? false,\n);\n\n// Storage info\nconst storageUsedBytes = computed(\n () => props.planConfig.storage.used_bytes ?? 0,\n);\nconst storageLimitBytes = computed(\n () => props.planConfig.storage.limit_bytes ?? 0,\n);\n\nconst { availableCategories } = useMediaCategories();\n\nconst library = useMediaLibrary({\n projectId: props.projectId,\n authManager: props.authManager,\n onError: props.onError,\n});\n\nconst ui = useMediaLibraryUI({\n library,\n canUseMediaFolders,\n translations: t,\n});\n\n// Standalone-specific: confirm selection via callback\nfunction confirmSelection(): void {\n if (!library.previewItem.value) {\n return;\n }\n\n const item = library.previewItem.value;\n const itemWithSelectedUrl: MediaItem = {\n ...item,\n url: ui.selectedUrl.value || item.url,\n };\n props.onSelect?.(itemWithSelectedUrl);\n}\n\nonMounted(() => {\n library.loadItems();\n library.loadFrequentlyUsed();\n emit(\"ready\");\n});\n</script>\n\n<template>\n <div\n class=\"tpl tpl:flex tpl:flex-col tpl:overflow-hidden tpl:rounded-[var(--tpl-radius-lg)]\"\n style=\"\n width: 100%;\n height: 100%;\n background-color: var(--tpl-bg-elevated);\n border: 1px solid var(--tpl-border);\n \"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-b tpl:px-5 tpl:py-3.5\"\n style=\"border-color: var(--tpl-border)\"\n >\n <h2 class=\"tpl:text-sm tpl:font-semibold\" style=\"color: var(--tpl-text)\">\n {{ t.mediaLibrary.title }}\n </h2>\n <div class=\"tpl:flex tpl:items-center tpl:gap-3\">\n <StorageProgressRing\n :used-bytes=\"storageUsedBytes\"\n :limit-bytes=\"storageLimitBytes\"\n :size=\"22\"\n />\n <div class=\"tpl:relative\">\n <input\n :value=\"ui.searchInput.value\"\n type=\"text\"\n class=\"tpl:w-52 tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-3 tpl:pl-8 tpl:text-xs tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:outline-none tpl:focus:shadow-[var(--tpl-ring)]\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :placeholder=\"t.mediaLibrary.searchPlaceholder\"\n @input=\"\n ui.handleSearchInput(($event.target as HTMLInputElement).value)\n \"\n />\n <Search\n class=\"tpl:absolute tpl:top-1/2 tpl:left-2.5 tpl:-translate-y-1/2\"\n :size=\"13\"\n :stroke-width=\"2\"\n style=\"color: var(--tpl-text-dim)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"tpl:flex tpl:min-h-0 tpl:flex-1 tpl:overflow-hidden\">\n <!-- Sidebar (only when media folders feature is enabled and toggled on) -->\n <Transition\n enter-active-class=\"tpl:transition-all tpl:duration-200 tpl:ease-out\"\n enter-from-class=\"tpl:-ml-48 tpl:opacity-0\"\n enter-to-class=\"tpl:ml-0 tpl:opacity-100\"\n leave-active-class=\"tpl:transition-all tpl:duration-150 tpl:ease-in\"\n leave-from-class=\"tpl:ml-0 tpl:opacity-100\"\n leave-to-class=\"tpl:-ml-48 tpl:opacity-0\"\n >\n <div\n v-if=\"canUseMediaFolders && ui.showSidebar.value\"\n class=\"tpl:flex tpl:w-48 tpl:shrink-0 tpl:flex-col tpl:border-r\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n \"\n >\n <MediaFolderTree\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n :view-mode=\"library.viewMode.value\"\n :has-frequently-used=\"ui.hasFrequentlyUsed.value\"\n @navigate=\"library.navigateToFolder\"\n @create-folder=\"ui.handleCreateFolder\"\n @rename-folder=\"ui.handleRenameFolder\"\n @delete-folder=\"ui.handleDeleteFolder\"\n @show-frequently-used=\"library.showFrequentlyUsed\"\n />\n </div>\n </Transition>\n\n <!-- Content area -->\n <div class=\"tpl:flex tpl:min-w-0 tpl:flex-1 tpl:flex-col\">\n <!-- Breadcrumb + Upload -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-b tpl:px-4 tpl:py-2.5\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <!-- Sidebar toggle (only when media folders feature is enabled) -->\n <button\n v-if=\"canUseMediaFolders\"\n class=\"tpl:flex tpl:size-7 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-md tpl:transition-all tpl:duration-150\"\n :style=\"{\n color: ui.showSidebar.value\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor: ui.showSidebar.value\n ? 'var(--tpl-bg)'\n : 'transparent',\n border: ui.showSidebar.value\n ? '1px solid var(--tpl-border)'\n : '1px solid transparent',\n }\"\n :title=\"\n ui.showSidebar.value\n ? t.mediaLibrary.hideFolders\n : t.mediaLibrary.showFolders\n \"\n @click=\"ui.showSidebar.value = !ui.showSidebar.value\"\n >\n <PanelLeft :size=\"16\" :stroke-width=\"2\" />\n </button>\n\n <template v-if=\"library.viewMode.value === 'frequently-used'\">\n <span\n class=\"tpl:text-xs tpl:font-medium\"\n style=\"color: var(--tpl-text)\"\n >\n {{ t.mediaLibrary.frequentlyUsed }}\n </span>\n </template>\n <template v-else>\n <MediaBreadcrumb\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n @navigate=\"library.navigateToFolder\"\n />\n </template>\n\n <!-- Layout toggle -->\n <div\n class=\"tpl:flex tpl:rounded-md tpl:p-0.5\"\n style=\"\n border: 1px solid var(--tpl-border);\n background-color: var(--tpl-bg);\n \"\n >\n <button\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:transition-all tpl:duration-150\"\n :style=\"{\n color:\n ui.layoutMode.value === 'grid'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor:\n ui.layoutMode.value === 'grid'\n ? 'var(--tpl-bg-elevated)'\n : 'transparent',\n }\"\n :title=\"t.mediaLibrary.viewGrid\"\n @click=\"ui.layoutMode.value = 'grid'\"\n >\n <Grid2x2 :size=\"14\" :stroke-width=\"2\" />\n </button>\n <button\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:transition-all tpl:duration-150\"\n :style=\"{\n color:\n ui.layoutMode.value === 'list'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor:\n ui.layoutMode.value === 'list'\n ? 'var(--tpl-bg-elevated)'\n : 'transparent',\n }\"\n :title=\"t.mediaLibrary.viewList\"\n @click=\"ui.layoutMode.value = 'list'\"\n >\n <List :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <select\n v-if=\"availableCategories.length > 1\"\n class=\"tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-7 tpl:pl-2.5 tpl:text-xs tpl:transition-all tpl:duration-150 tpl:outline-none\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :value=\"library.categoryFilter.value ?? ''\"\n @change=\"\n library.filterByCategory(\n ($event.target as HTMLSelectElement).value || null,\n )\n \"\n >\n <option value=\"\">\n {{ t.mediaLibrary.filterAll }}\n </option>\n <option\n v-for=\"category in availableCategories\"\n :key=\"category\"\n :value=\"category\"\n >\n {{ ui.getCategoryLabel(category) }}\n </option>\n </select>\n <select\n class=\"tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-7 tpl:pl-2.5 tpl:text-xs tpl:transition-all tpl:duration-150 tpl:outline-none\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :value=\"library.sortOption.value\"\n @change=\"\n library.sortBy(($event.target as HTMLSelectElement).value)\n \"\n >\n <option value=\"newest\">\n {{ t.mediaLibrary.sortNewest }}\n </option>\n <option value=\"oldest\">\n {{ t.mediaLibrary.sortOldest }}\n </option>\n <option value=\"name_asc\">\n {{ t.mediaLibrary.sortNameAsc }}\n </option>\n <option value=\"name_desc\">\n {{ t.mediaLibrary.sortNameDesc }}\n </option>\n <option value=\"size_asc\">\n {{ t.mediaLibrary.sortSizeAsc }}\n </option>\n <option value=\"size_desc\">\n {{ t.mediaLibrary.sortSizeDesc }}\n </option>\n </select>\n </div>\n </div>\n\n <!-- Scrollable content area -->\n <div class=\"tpl:min-h-0 tpl:flex-1 tpl:overflow-y-auto\">\n <!-- Upload zone (only in files mode) -->\n <div\n v-if=\"library.viewMode.value === 'files'\"\n class=\"tpl:px-4 tpl:pt-3\"\n >\n <MediaUploadZone\n :is-uploading=\"library.isUploading.value\"\n :upload-progress=\"library.uploadProgress.value\"\n @upload=\"ui.handleUpload\"\n />\n <button\n v-if=\"canImportFromUrl\"\n class=\"tpl:mt-2 tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-md tpl:border tpl:border-dashed tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text-muted);\n background-color: var(--tpl-bg);\n \"\n @click=\"ui.showImportUrlModal.value = true\"\n >\n <Link :size=\"14\" :stroke-width=\"2\" />\n {{ t.mediaLibrary.importFromUrl }}\n </button>\n </div>\n\n <!-- Image grid -->\n <MediaGrid\n :items=\"ui.displayItems.value\"\n :selected-ids=\"library.selectedItems.value\"\n :is-loading=\"library.isLoading.value\"\n :has-more=\"\n library.viewMode.value === 'files' && library.hasMore.value\n \"\n :layout=\"ui.layoutMode.value\"\n @select=\"ui.handleSelect\"\n @toggle=\"library.toggleSelection\"\n @load-more=\"library.loadMore\"\n @edit=\"ui.handleEditItem\"\n @replace=\"ui.handleReplaceItem\"\n />\n </div>\n </div>\n </div>\n\n <!-- Import from URL Modal -->\n <MediaImportUrlModal\n :visible=\"ui.showImportUrlModal.value\"\n :is-importing=\"library.isImportingFromUrl.value\"\n :error=\"library.importFromUrlError.value\"\n @import=\"ui.handleImportFromUrl\"\n @close=\"ui.showImportUrlModal.value = false\"\n />\n\n <!-- Edit Modal -->\n <MediaEditModal\n :visible=\"!!ui.editingItem.value\"\n :item=\"ui.editingItem.value\"\n @save=\"ui.handleEditSave\"\n @close=\"ui.editingItem.value = null\"\n />\n\n <!-- Replace Modal -->\n <MediaReplaceModal\n :visible=\"library.showReplaceWarning.value\"\n :item=\"library.pendingReplaceItem.value\"\n :usage-info=\"library.replaceUsageInfo.value\"\n :is-replacing=\"library.isReplacing.value\"\n :error=\"library.replaceError.value\"\n @replace=\"ui.handleReplaceFile\"\n @close=\"library.cancelReplace\"\n />\n\n <!-- Delete Warning Dialog -->\n <Transition\n enter-active-class=\"tpl:transition tpl:ease-out tpl:duration-150\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:ease-in tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <div\n v-if=\"library.showDeleteWarning.value\"\n class=\"tpl:absolute tpl:inset-0 tpl:z-10 tpl:flex tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-lg)]\"\n style=\"\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n @click.self=\"library.cancelDelete\"\n >\n <div\n class=\"tpl-scale-in tpl:mx-4 tpl:w-full tpl:max-w-sm tpl:rounded-[var(--tpl-radius-lg)] tpl:p-5\"\n style=\"\n background-color: var(--tpl-bg-elevated);\n box-shadow: var(--tpl-shadow-xl);\n \"\n >\n <h3\n class=\"tpl:mb-2 tpl:text-sm tpl:font-semibold\"\n style=\"color: var(--tpl-text)\"\n >\n {{ t.mediaLibrary.deleteWarningTitle }}\n </h3>\n <p\n class=\"tpl:text-xs\"\n :class=\"ui.hasUsedFiles.value ? 'tpl:mb-2' : 'tpl:mb-4'\"\n style=\"color: var(--tpl-text-muted)\"\n >\n {{ t.mediaLibrary.deleteWarningMessage }}\n </p>\n <p\n v-if=\"ui.hasUsedFiles.value\"\n class=\"tpl:mb-4 tpl:text-xs\"\n style=\"color: var(--tpl-text-muted)\"\n >\n {{ t.mediaLibrary.deleteWarningUsageNote }}\n </p>\n\n <div\n v-if=\"ui.hasUsedFiles.value\"\n class=\"tpl:mb-4 tpl:max-h-32 tpl:overflow-y-auto tpl:rounded tpl:border tpl:p-2\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div\n v-for=\"(info, mediaId) in library.deleteUsageInfo.value\"\n :key=\"mediaId\"\n class=\"tpl:text-xs\"\n style=\"color: var(--tpl-text)\"\n >\n <template v-if=\"info.template_count > 0\">\n <span class=\"tpl:font-medium\">\n {{\n ui.displayItems.value.find((i) => i.id === mediaId)\n ?.filename || mediaId\n }}\n </span>\n <span style=\"color: var(--tpl-text-muted)\">\n -\n {{\n t.mediaLibrary.usedInTemplates.replace(\n \"{count}\",\n info.template_count.toString(),\n )\n }}\n </span>\n </template>\n </div>\n </div>\n\n <div class=\"tpl:flex tpl:justify-end tpl:gap-2\">\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text);\n background-color: var(--tpl-bg);\n \"\n @click=\"library.cancelDelete\"\n >\n {{ t.mediaLibrary.cancel }}\n </button>\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-danger);\n color: var(--tpl-danger);\n background-color: var(--tpl-danger-light);\n \"\n @click=\"library.confirmDelete\"\n >\n {{\n ui.hasUsedFiles.value\n ? t.mediaLibrary.deleteAnyway\n : t.mediaLibrary.confirmDelete\n }}\n </button>\n </div>\n </div>\n </div>\n </Transition>\n\n <!-- Footer -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-t tpl:px-5 tpl:py-3\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div class=\"tpl:flex tpl:min-w-0 tpl:flex-1 tpl:items-center tpl:gap-3\">\n <MediaPreviewPanel\n v-if=\"library.previewItem.value\"\n v-model:selected-conversion=\"ui.selectedConversion.value\"\n :item=\"library.previewItem.value\"\n :folders=\"library.folders.value\"\n />\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-5\">\n <!-- Copy URL + Move group -->\n <div\n v-if=\"library.selectedItems.value.size > 0\"\n class=\"tpl:flex tpl:items-center tpl:gap-2\"\n >\n <button\n v-if=\"library.previewItem.value\"\n class=\"tpl:flex tpl:cursor-pointer tpl:items-center tpl:gap-1 tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n borderColor: ui.copied.value\n ? 'var(--tpl-success)'\n : 'var(--tpl-border)',\n color: ui.copied.value ? 'var(--tpl-success)' : 'var(--tpl-text)',\n backgroundColor: 'var(--tpl-bg)',\n }\"\n @click=\"ui.copy(ui.selectedUrl.value!)\"\n >\n <Copy v-if=\"!ui.copied.value\" :size=\"12\" :stroke-width=\"2\" />\n <Check v-else :size=\"12\" :stroke-width=\"2\" />\n {{\n ui.copied.value ? t.mediaLibrary.copied : t.mediaLibrary.copyUrl\n }}\n </button>\n <div v-if=\"canUseMediaFolders\" class=\"tpl:relative\">\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text);\n background-color: var(--tpl-bg);\n \"\n @click=\"ui.showMovePicker.value = !ui.showMovePicker.value\"\n >\n {{ t.mediaLibrary.moveSelected }}\n </button>\n <MediaMovePicker\n v-if=\"ui.showMovePicker.value\"\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n @select=\"ui.handleMoveToFolder\"\n @close=\"ui.showMovePicker.value = false\"\n />\n </div>\n </div>\n <!-- Delete + Select group -->\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <button\n v-if=\"library.selectedItems.value.size > 0\"\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-danger);\n color: var(--tpl-danger);\n background-color: var(--tpl-danger-light);\n \"\n @click=\"ui.handleDeleteClick\"\n >\n {{ t.mediaLibrary.deleteSelected }}\n </button>\n <button\n v-if=\"onSelect\"\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:px-4 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50\"\n style=\"background-color: var(--tpl-primary); color: var(--tpl-bg)\"\n :disabled=\"!library.previewItem.value\"\n @click=\"confirmSelection\"\n >\n {{ t.mediaLibrary.selectFile }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport MediaBreadcrumb from \"../components/media/MediaBreadcrumb.vue\";\nimport MediaEditModal from \"../components/media/MediaEditModal.vue\";\nimport MediaFolderTree from \"../components/media/MediaFolderTree.vue\";\nimport MediaGrid from \"../components/media/MediaGrid.vue\";\nimport MediaImportUrlModal from \"../components/media/MediaImportUrlModal.vue\";\nimport MediaMovePicker from \"../components/media/MediaMovePicker.vue\";\nimport MediaPreviewPanel from \"../components/media/MediaPreviewPanel.vue\";\nimport MediaReplaceModal from \"../components/media/MediaReplaceModal.vue\";\nimport MediaUploadZone from \"../components/media/MediaUploadZone.vue\";\nimport StorageProgressRing from \"../components/media/StorageProgressRing.vue\";\nimport { useMediaLibrary } from \"../composable\";\nimport { useMediaCategories } from \"../composables/useMediaCategories\";\nimport { useMediaLibraryUI } from \"../composables/useMediaLibraryUI\";\nimport type { PlanConfig, PlanFeatures } from \"@templatical/types\";\nimport type { MediaItem } from \"../types\";\nimport type { AuthManager } from \"@templatical/core/cloud\";\nimport type { MediaTranslations } from \"../i18n\";\nimport {\n Check,\n Copy,\n Grid2x2,\n Link,\n List,\n PanelLeft,\n Search,\n} from \"@lucide/vue\";\nimport { computed, onMounted, provide, ref } from \"vue\";\n\nconst props = defineProps<{\n authManager: AuthManager;\n projectId: string;\n planConfig: PlanConfig;\n translations: MediaTranslations;\n onSelect?: (item: MediaItem) => void;\n onError?: (error: Error) => void;\n}>();\n\nconst emit = defineEmits<{\n (e: \"ready\"): void;\n}>();\n\nconst t = computed(() => props.translations);\n\n// Provide translations for sub-components that use inject('translations')\nprovide(\"translations\", props.translations);\nprovide(\"authManager\", props.authManager);\nprovide(\n \"projectId\",\n computed(() => props.projectId),\n);\n\n// Provide planConfig in the format that sub-components expect\nconst planConfigRef = ref<PlanConfig | null>(props.planConfig);\nprovide(\"planConfig\", {\n config: planConfigRef,\n isLoading: ref(false),\n hasFeature: (feature: keyof PlanFeatures) =>\n props.planConfig.features[feature] ?? false,\n features: computed(() => props.planConfig.features),\n fetchConfig: async () => {},\n});\n\n// Feature flags\nconst canUseMediaFolders = computed(\n () => props.planConfig.features.media_folders ?? false,\n);\nconst canImportFromUrl = computed(\n () => props.planConfig.features.import_from_url ?? false,\n);\n\n// Storage info\nconst storageUsedBytes = computed(\n () => props.planConfig.storage.used_bytes ?? 0,\n);\nconst storageLimitBytes = computed(\n () => props.planConfig.storage.limit_bytes ?? 0,\n);\n\nconst { availableCategories } = useMediaCategories();\n\nconst library = useMediaLibrary({\n projectId: props.projectId,\n authManager: props.authManager,\n onError: props.onError,\n});\n\nconst ui = useMediaLibraryUI({\n library,\n canUseMediaFolders,\n translations: t,\n});\n\n// Standalone-specific: confirm selection via callback\nfunction confirmSelection(): void {\n if (!library.previewItem.value) {\n return;\n }\n\n const item = library.previewItem.value;\n const itemWithSelectedUrl: MediaItem = {\n ...item,\n url: ui.selectedUrl.value || item.url,\n };\n props.onSelect?.(itemWithSelectedUrl);\n}\n\nonMounted(() => {\n library.loadItems();\n library.loadFrequentlyUsed();\n emit(\"ready\");\n});\n</script>\n\n<template>\n <div\n class=\"tpl tpl:flex tpl:flex-col tpl:overflow-hidden tpl:rounded-[var(--tpl-radius-lg)]\"\n style=\"\n width: 100%;\n height: 100%;\n background-color: var(--tpl-bg-elevated);\n border: 1px solid var(--tpl-border);\n \"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-b tpl:px-5 tpl:py-3.5\"\n style=\"border-color: var(--tpl-border)\"\n >\n <h2 class=\"tpl:text-sm tpl:font-semibold\" style=\"color: var(--tpl-text)\">\n {{ t.mediaLibrary.title }}\n </h2>\n <div class=\"tpl:flex tpl:items-center tpl:gap-3\">\n <StorageProgressRing\n :used-bytes=\"storageUsedBytes\"\n :limit-bytes=\"storageLimitBytes\"\n :size=\"22\"\n />\n <div class=\"tpl:relative\">\n <input\n :value=\"ui.searchInput.value\"\n type=\"text\"\n class=\"tpl:w-52 tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-3 tpl:pl-8 tpl:text-xs tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:outline-none tpl:focus:shadow-[var(--tpl-ring)]\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :placeholder=\"t.mediaLibrary.searchPlaceholder\"\n @input=\"\n ui.handleSearchInput(($event.target as HTMLInputElement).value)\n \"\n />\n <Search\n class=\"tpl:absolute tpl:top-1/2 tpl:left-2.5 tpl:-translate-y-1/2\"\n :size=\"13\"\n :stroke-width=\"2\"\n style=\"color: var(--tpl-text-dim)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"tpl:flex tpl:min-h-0 tpl:flex-1 tpl:overflow-hidden\">\n <!-- Sidebar (only when media folders feature is enabled and toggled on) -->\n <Transition\n enter-active-class=\"tpl:transition-all tpl:duration-200 tpl:ease-out\"\n enter-from-class=\"tpl:-ml-48 tpl:opacity-0\"\n enter-to-class=\"tpl:ml-0 tpl:opacity-100\"\n leave-active-class=\"tpl:transition-all tpl:duration-150 tpl:ease-in\"\n leave-from-class=\"tpl:ml-0 tpl:opacity-100\"\n leave-to-class=\"tpl:-ml-48 tpl:opacity-0\"\n >\n <div\n v-if=\"canUseMediaFolders && ui.showSidebar.value\"\n class=\"tpl:flex tpl:w-48 tpl:shrink-0 tpl:flex-col tpl:border-r\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n \"\n >\n <MediaFolderTree\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n :view-mode=\"library.viewMode.value\"\n :has-frequently-used=\"ui.hasFrequentlyUsed.value\"\n @navigate=\"library.navigateToFolder\"\n @create-folder=\"ui.handleCreateFolder\"\n @rename-folder=\"ui.handleRenameFolder\"\n @delete-folder=\"ui.handleDeleteFolder\"\n @show-frequently-used=\"library.showFrequentlyUsed\"\n />\n </div>\n </Transition>\n\n <!-- Content area -->\n <div class=\"tpl:flex tpl:min-w-0 tpl:flex-1 tpl:flex-col\">\n <!-- Breadcrumb + Upload -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-b tpl:px-4 tpl:py-2.5\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <!-- Sidebar toggle (only when media folders feature is enabled) -->\n <button\n v-if=\"canUseMediaFolders\"\n class=\"tpl:flex tpl:size-7 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-md tpl:transition-all tpl:duration-150\"\n :style=\"{\n color: ui.showSidebar.value\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor: ui.showSidebar.value\n ? 'var(--tpl-bg)'\n : 'transparent',\n border: ui.showSidebar.value\n ? '1px solid var(--tpl-border)'\n : '1px solid transparent',\n }\"\n :title=\"\n ui.showSidebar.value\n ? t.mediaLibrary.hideFolders\n : t.mediaLibrary.showFolders\n \"\n @click=\"ui.showSidebar.value = !ui.showSidebar.value\"\n >\n <PanelLeft :size=\"16\" :stroke-width=\"2\" />\n </button>\n\n <template v-if=\"library.viewMode.value === 'frequently-used'\">\n <span\n class=\"tpl:text-xs tpl:font-medium\"\n style=\"color: var(--tpl-text)\"\n >\n {{ t.mediaLibrary.frequentlyUsed }}\n </span>\n </template>\n <template v-else>\n <MediaBreadcrumb\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n @navigate=\"library.navigateToFolder\"\n />\n </template>\n\n <!-- Layout toggle -->\n <div\n class=\"tpl:flex tpl:rounded-md tpl:p-0.5\"\n style=\"\n border: 1px solid var(--tpl-border);\n background-color: var(--tpl-bg);\n \"\n >\n <button\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:transition-all tpl:duration-150\"\n :style=\"{\n color:\n ui.layoutMode.value === 'grid'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor:\n ui.layoutMode.value === 'grid'\n ? 'var(--tpl-bg-elevated)'\n : 'transparent',\n }\"\n :title=\"t.mediaLibrary.viewGrid\"\n @click=\"ui.layoutMode.value = 'grid'\"\n >\n <Grid2x2 :size=\"14\" :stroke-width=\"2\" />\n </button>\n <button\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:transition-all tpl:duration-150\"\n :style=\"{\n color:\n ui.layoutMode.value === 'list'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n backgroundColor:\n ui.layoutMode.value === 'list'\n ? 'var(--tpl-bg-elevated)'\n : 'transparent',\n }\"\n :title=\"t.mediaLibrary.viewList\"\n @click=\"ui.layoutMode.value = 'list'\"\n >\n <List :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <select\n v-if=\"availableCategories.length > 1\"\n class=\"tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-7 tpl:pl-2.5 tpl:text-xs tpl:transition-all tpl:duration-150 tpl:outline-none\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :value=\"library.categoryFilter.value ?? ''\"\n @change=\"\n library.filterByCategory(\n ($event.target as HTMLSelectElement).value || null,\n )\n \"\n >\n <option value=\"\">\n {{ t.mediaLibrary.filterAll }}\n </option>\n <option\n v-for=\"category in availableCategories\"\n :key=\"category\"\n :value=\"category\"\n >\n {{ ui.getCategoryLabel(category) }}\n </option>\n </select>\n <select\n class=\"tpl:rounded-md tpl:border tpl:py-1.5 tpl:pr-7 tpl:pl-2.5 tpl:text-xs tpl:transition-all tpl:duration-150 tpl:outline-none\"\n style=\"\n border-color: var(--tpl-border);\n background-color: var(--tpl-bg);\n color: var(--tpl-text);\n \"\n :value=\"library.sortOption.value\"\n @change=\"\n library.sortBy(($event.target as HTMLSelectElement).value)\n \"\n >\n <option value=\"newest\">\n {{ t.mediaLibrary.sortNewest }}\n </option>\n <option value=\"oldest\">\n {{ t.mediaLibrary.sortOldest }}\n </option>\n <option value=\"name_asc\">\n {{ t.mediaLibrary.sortNameAsc }}\n </option>\n <option value=\"name_desc\">\n {{ t.mediaLibrary.sortNameDesc }}\n </option>\n <option value=\"size_asc\">\n {{ t.mediaLibrary.sortSizeAsc }}\n </option>\n <option value=\"size_desc\">\n {{ t.mediaLibrary.sortSizeDesc }}\n </option>\n </select>\n </div>\n </div>\n\n <!-- Scrollable content area -->\n <div class=\"tpl:min-h-0 tpl:flex-1 tpl:overflow-y-auto\">\n <!-- Upload zone (only in files mode) -->\n <div\n v-if=\"library.viewMode.value === 'files'\"\n class=\"tpl:px-4 tpl:pt-3\"\n >\n <MediaUploadZone\n :is-uploading=\"library.isUploading.value\"\n :upload-progress=\"library.uploadProgress.value\"\n @upload=\"ui.handleUpload\"\n />\n <button\n v-if=\"canImportFromUrl\"\n class=\"tpl:mt-2 tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-md tpl:border tpl:border-dashed tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text-muted);\n background-color: var(--tpl-bg);\n \"\n @click=\"ui.showImportUrlModal.value = true\"\n >\n <Link :size=\"14\" :stroke-width=\"2\" />\n {{ t.mediaLibrary.importFromUrl }}\n </button>\n </div>\n\n <!-- Image grid -->\n <MediaGrid\n :items=\"ui.displayItems.value\"\n :selected-ids=\"library.selectedItems.value\"\n :is-loading=\"library.isLoading.value\"\n :has-more=\"\n library.viewMode.value === 'files' && library.hasMore.value\n \"\n :layout=\"ui.layoutMode.value\"\n @select=\"ui.handleSelect\"\n @toggle=\"library.toggleSelection\"\n @load-more=\"library.loadMore\"\n @edit=\"ui.handleEditItem\"\n @replace=\"ui.handleReplaceItem\"\n />\n </div>\n </div>\n </div>\n\n <!-- Import from URL Modal -->\n <MediaImportUrlModal\n :visible=\"ui.showImportUrlModal.value\"\n :is-importing=\"library.isImportingFromUrl.value\"\n :error=\"library.importFromUrlError.value\"\n @import=\"ui.handleImportFromUrl\"\n @close=\"ui.showImportUrlModal.value = false\"\n />\n\n <!-- Edit Modal -->\n <MediaEditModal\n :visible=\"!!ui.editingItem.value\"\n :item=\"ui.editingItem.value\"\n @save=\"ui.handleEditSave\"\n @close=\"ui.editingItem.value = null\"\n />\n\n <!-- Replace Modal -->\n <MediaReplaceModal\n :visible=\"library.showReplaceWarning.value\"\n :item=\"library.pendingReplaceItem.value\"\n :usage-info=\"library.replaceUsageInfo.value\"\n :is-replacing=\"library.isReplacing.value\"\n :error=\"library.replaceError.value\"\n @replace=\"ui.handleReplaceFile\"\n @close=\"library.cancelReplace\"\n />\n\n <!-- Delete Warning Dialog -->\n <Transition\n enter-active-class=\"tpl:transition tpl:ease-out tpl:duration-150\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:ease-in tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <div\n v-if=\"library.showDeleteWarning.value\"\n class=\"tpl:absolute tpl:inset-0 tpl:z-10 tpl:flex tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-lg)]\"\n style=\"\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n @click.self=\"library.cancelDelete\"\n >\n <div\n class=\"tpl-scale-in tpl:mx-4 tpl:w-full tpl:max-w-sm tpl:rounded-[var(--tpl-radius-lg)] tpl:p-5\"\n style=\"\n background-color: var(--tpl-bg-elevated);\n box-shadow: var(--tpl-shadow-xl);\n \"\n >\n <h3\n class=\"tpl:mb-2 tpl:text-sm tpl:font-semibold\"\n style=\"color: var(--tpl-text)\"\n >\n {{ t.mediaLibrary.deleteWarningTitle }}\n </h3>\n <p\n class=\"tpl:text-xs\"\n :class=\"ui.hasUsedFiles.value ? 'tpl:mb-2' : 'tpl:mb-4'\"\n style=\"color: var(--tpl-text-muted)\"\n >\n {{ t.mediaLibrary.deleteWarningMessage }}\n </p>\n <p\n v-if=\"ui.hasUsedFiles.value\"\n class=\"tpl:mb-4 tpl:text-xs\"\n style=\"color: var(--tpl-text-muted)\"\n >\n {{ t.mediaLibrary.deleteWarningUsageNote }}\n </p>\n\n <div\n v-if=\"ui.hasUsedFiles.value\"\n class=\"tpl:mb-4 tpl:max-h-32 tpl:overflow-y-auto tpl:rounded tpl:border tpl:p-2\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div\n v-for=\"(info, mediaId) in library.deleteUsageInfo.value\"\n :key=\"mediaId\"\n class=\"tpl:text-xs\"\n style=\"color: var(--tpl-text)\"\n >\n <template v-if=\"info.template_count > 0\">\n <span class=\"tpl:font-medium\">\n {{\n ui.displayItems.value.find((i) => i.id === mediaId)\n ?.filename || mediaId\n }}\n </span>\n <span style=\"color: var(--tpl-text-muted)\">\n -\n {{\n t.mediaLibrary.usedInTemplates.replace(\n \"{count}\",\n info.template_count.toString(),\n )\n }}\n </span>\n </template>\n </div>\n </div>\n\n <div class=\"tpl:flex tpl:justify-end tpl:gap-2\">\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text);\n background-color: var(--tpl-bg);\n \"\n @click=\"library.cancelDelete\"\n >\n {{ t.mediaLibrary.cancel }}\n </button>\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-danger);\n color: var(--tpl-danger);\n background-color: var(--tpl-danger-light);\n \"\n @click=\"library.confirmDelete\"\n >\n {{\n ui.hasUsedFiles.value\n ? t.mediaLibrary.deleteAnyway\n : t.mediaLibrary.confirmDelete\n }}\n </button>\n </div>\n </div>\n </div>\n </Transition>\n\n <!-- Footer -->\n <div\n class=\"tpl:flex tpl:shrink-0 tpl:items-center tpl:justify-between tpl:border-t tpl:px-5 tpl:py-3\"\n style=\"border-color: var(--tpl-border)\"\n >\n <div class=\"tpl:flex tpl:min-w-0 tpl:flex-1 tpl:items-center tpl:gap-3\">\n <MediaPreviewPanel\n v-if=\"library.previewItem.value\"\n v-model:selected-conversion=\"ui.selectedConversion.value\"\n :item=\"library.previewItem.value\"\n :folders=\"library.folders.value\"\n />\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-5\">\n <!-- Copy URL + Move group -->\n <div\n v-if=\"library.selectedItems.value.size > 0\"\n class=\"tpl:flex tpl:items-center tpl:gap-2\"\n >\n <button\n v-if=\"library.previewItem.value\"\n class=\"tpl:flex tpl:cursor-pointer tpl:items-center tpl:gap-1 tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n borderColor: ui.copied.value\n ? 'var(--tpl-success)'\n : 'var(--tpl-border)',\n color: ui.copied.value ? 'var(--tpl-success)' : 'var(--tpl-text)',\n backgroundColor: 'var(--tpl-bg)',\n }\"\n @click=\"ui.copy(ui.selectedUrl.value!)\"\n >\n <Copy v-if=\"!ui.copied.value\" :size=\"12\" :stroke-width=\"2\" />\n <Check v-else :size=\"12\" :stroke-width=\"2\" />\n {{\n ui.copied.value ? t.mediaLibrary.copied : t.mediaLibrary.copyUrl\n }}\n </button>\n <div v-if=\"canUseMediaFolders\" class=\"tpl:relative\">\n <button\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-border);\n color: var(--tpl-text);\n background-color: var(--tpl-bg);\n \"\n @click=\"ui.showMovePicker.value = !ui.showMovePicker.value\"\n >\n {{ t.mediaLibrary.moveSelected }}\n </button>\n <MediaMovePicker\n v-if=\"ui.showMovePicker.value\"\n :folders=\"library.folders.value\"\n :current-folder-id=\"library.currentFolderId.value\"\n @select=\"ui.handleMoveToFolder\"\n @close=\"ui.showMovePicker.value = false\"\n />\n </div>\n </div>\n <!-- Delete + Select group -->\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <button\n v-if=\"library.selectedItems.value.size > 0\"\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:border tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n style=\"\n border-color: var(--tpl-danger);\n color: var(--tpl-danger);\n background-color: var(--tpl-danger-light);\n \"\n @click=\"ui.handleDeleteClick\"\n >\n {{ t.mediaLibrary.deleteSelected }}\n </button>\n <button\n v-if=\"onSelect\"\n class=\"tpl:cursor-pointer tpl:rounded-md tpl:px-4 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50\"\n style=\"background-color: var(--tpl-primary); color: var(--tpl-bg)\"\n :disabled=\"!library.previewItem.value\"\n @click=\"confirmSelection\"\n >\n {{ t.mediaLibrary.selectFile }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n","/// <reference types=\"vite/client\" />\n\nimport type en from \"./locales/en\";\n\nexport type MediaTranslations = typeof en;\n\n// Vite resolves this glob at build time. Adding a new locale file\n// automatically registers it — no array to keep in sync.\nconst localeModules = import.meta.glob<{ default: MediaTranslations }>(\n \"./locales/*.ts\",\n);\n\nfunction localesFromGlob(modules: Record<string, unknown>): string[] {\n return Object.keys(modules)\n .map((path) => path.match(/\\/([^/]+)\\.ts$/)?.[1])\n .filter((locale): locale is string => Boolean(locale));\n}\n\nconst supportedLocales = localesFromGlob(localeModules);\n\nfunction canonicalize(locale: string): string {\n return locale.trim().replace(/_/g, \"-\").toLowerCase();\n}\n\nfunction findSupportedLocale(locale: string): string | undefined {\n const canonical = canonicalize(locale);\n return supportedLocales.find((s) => canonicalize(s) === canonical);\n}\n\nfunction getBaseLocale(locale: string): string {\n return canonicalize(locale).split(\"-\")[0];\n}\n\nfunction resolveLocale(locale: string): string {\n return (\n findSupportedLocale(locale) ??\n findSupportedLocale(getBaseLocale(locale)) ??\n \"en\"\n );\n}\n\nexport async function loadMediaTranslations(\n locale: string,\n): Promise<MediaTranslations> {\n const target = resolveLocale(locale);\n const loader = localeModules[`./locales/${target}.ts`];\n const module = await loader();\n return module.default;\n}\n","import { createSdkAuthManager } from \"@templatical/core/cloud\";\nimport type { PlanConfig } from \"@templatical/types\";\nimport { ApiClient } from \"@templatical/core/cloud\";\nimport MediaLibrary from \"./MediaLibrary.vue\";\nimport { loadMediaTranslations, type MediaTranslations } from \"../i18n\";\nimport type { MediaLibraryConfig, MediaLibraryInstance } from \"./types\";\nimport { createApp, h, ref, type App, type Ref } from \"vue\";\n\n// Import SDK styles\nimport \"../styles/index.css\";\n\n// Re-export types for consumers\nexport type { MediaFolder, MediaItem } from \"../types\";\nexport type { MediaLibraryConfig, MediaLibraryInstance } from \"./types\";\n\nlet appInstance: App | null = null;\nconst mediaLibraryRef: Ref<InstanceType<typeof MediaLibrary> | null> =\n ref(null);\n\nasync function init(config: MediaLibraryConfig): Promise<MediaLibraryInstance> {\n const container =\n typeof config.container === \"string\"\n ? document.querySelector(config.container)\n : config.container;\n\n if (!container) {\n throw new Error(`Container element not found: ${config.container}`);\n }\n\n // Initialize auth\n const authManager = createSdkAuthManager(config.auth, config.onError);\n await authManager.initialize();\n\n // Fetch plan config\n const apiClient = new ApiClient(authManager);\n const planConfig: PlanConfig = await apiClient.fetchConfig();\n\n // Load translations\n const translations: MediaTranslations = await loadMediaTranslations(\n config.locale ?? \"en\",\n );\n\n // Apply theme overrides to container\n applyTheme(container as HTMLElement, config.theme);\n\n // Unmount any prior app *after* awaits so concurrent init() calls don't\n // both pass an early check while appInstance is still null and orphan\n // the first-mounted app.\n if (appInstance) {\n unmount();\n }\n\n return new Promise((resolve, reject) => {\n try {\n appInstance = createApp({\n setup() {\n const onReady = () => {\n const instance: MediaLibraryInstance = {\n setTheme: (theme) => applyTheme(container as HTMLElement, theme),\n unmount,\n };\n\n resolve(instance);\n };\n\n return () =>\n h(MediaLibrary, {\n authManager,\n projectId: authManager.projectId,\n planConfig,\n translations,\n onSelect: config.onSelect,\n onError: config.onError,\n ref: mediaLibraryRef,\n onReady,\n });\n },\n });\n\n appInstance.mount(container);\n } catch (error) {\n reject(error);\n }\n });\n}\n\nfunction unmount(): void {\n if (appInstance) {\n appInstance.unmount();\n appInstance = null;\n mediaLibraryRef.value = null;\n }\n}\n\nfunction applyTheme(\n container: HTMLElement,\n theme?: { primaryColor?: string; borderRadius?: number },\n): void {\n if (!theme) {\n return;\n }\n\n if (theme.primaryColor) {\n container.style.setProperty(\"--tpl-primary\", theme.primaryColor);\n }\n\n if (theme.borderRadius !== undefined) {\n container.style.setProperty(\"--tpl-radius\", `${theme.borderRadius}px`);\n container.style.setProperty(\n \"--tpl-radius-sm\",\n `${Math.max(0, theme.borderRadius - 3)}px`,\n );\n container.style.setProperty(\n \"--tpl-radius-lg\",\n `${theme.borderRadius + 4}px`,\n );\n }\n}\n\nconst TemplaticalMedia = {\n init,\n unmount,\n};\n\n// Assign to window for IIFE usage\nif (typeof window !== \"undefined\") {\n (\n window as unknown as Window & { TemplaticalMedia: typeof TemplaticalMedia }\n ).TemplaticalMedia = TemplaticalMedia;\n}\n\n// Named exports for destructured imports\nexport { init, unmount };\n\n// Default export for library mode\nexport default TemplaticalMedia;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6BA,IAAM,IAAQ,GASR,IAAO,GAIP,IAAI,QAAe,EAAM,YAAY;EAY3C,AATA,EAAQ,gBAAgB,EAAM,YAAY,GAC1C,EAAQ,eAAe,EAAM,WAAW,GACxC,EACE,aACA,QAAe,EAAM,SAAS,CAChC,GAIA,EAAQ,cAAc;GACpB,QAFoB,EAAuB,EAAM,UAEzC;GACR,WAAW,EAAI,EAAK;GACpB,aAAa,MACX,EAAM,WAAW,SAAS,MAAY;GACxC,UAAU,QAAe,EAAM,WAAW,QAAQ;GAClD,aAAa,YAAY,CAAC;EAC5B,CAAC;EAGD,IAAM,IAAqB,QACnB,EAAM,WAAW,SAAS,iBAAiB,EACnD,GACM,IAAmB,QACjB,EAAM,WAAW,SAAS,mBAAmB,EACrD,GAGM,IAAmB,QACjB,EAAM,WAAW,QAAQ,cAAc,CAC/C,GACM,IAAoB,QAClB,EAAM,WAAW,QAAQ,eAAe,CAChD,GAEM,EAAE,2BAAwB,GAAmB,GAE7C,IAAU,EAAgB;GAC9B,WAAW,EAAM;GACjB,aAAa,EAAM;GACnB,SAAS,EAAM;EACjB,CAAC,GAEK,IAAK,EAAkB;GAC3B;GACA;GACA,cAAc;EAChB,CAAC;EAGD,SAAS,IAAyB;GAChC,IAAI,CAAC,EAAQ,YAAY,OACvB;GAGF,IAAM,IAAO,EAAQ,YAAY;GAKjC,EAAM,WAAW;IAHf,GAAG;IACH,KAAK,EAAG,YAAY,SAAS,EAAK;GAEnB,CAAmB;EACtC;SAEA,QAAgB;GAGd,AAFA,EAAQ,UAAU,GAClB,EAAQ,mBAAmB,GAC3B,EAAK,OAAO;EACd,CAAC,mBAIC,EAwfM,OAxfN,GAwfM;GA9eJ,EAoCM,OApCN,GAoCM,CAhCJ,EAEK,MAFL,GAEK,EADA,EAAA,MAAE,aAAa,KAAK,GAAA,CAAA,GAEzB,EA4BM,OA5BN,GA4BM,CA3BJ,EAIE,GAAA;IAHC,cAAY,EAAA;IACZ,eAAa,EAAA;IACb,MAAM;+CAET,EAqBM,OArBN,GAqBM,CApBJ,EAaE,SAAA;IAZC,OAAO,EAAA,CAAA,CAAE,CAAC,YAAY;IACvB,MAAK;IACL,OAAM;IACN,OAAA;KAAA,gBAAA;KAAA,oBAAA;KAAA,OAAA;IAAA;IAKC,aAAa,EAAA,MAAE,aAAa;IAC5B,SAAK,AAAA,EAAA,QAAA,MAAiB,EAAA,CAAA,CAAE,CAAC,kBAAmB,EAAO,OAA4B,KAAK;oBAIvF,EAKE,EAAA,EAAA,GAAA;IAJA,OAAM;IACL,MAAM;IACN,gBAAc;IACf,OAAA,EAAA,OAAA,sBAAA;;GAOR,EAuOM,OAvON,GAuOM,CArOJ,EA4Ba,GAAA;IA3BX,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;IACf,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;;qBAqBT,CAlBE,EAAA,SAAsB,EAAA,CAAA,CAAE,CAAC,YAAY,SAAA,EAAA,GAD7C,EAmBM,OAnBN,GAmBM,CAXJ,EAUE,GAAA;KATC,SAAS,EAAA,CAAA,CAAO,CAAC,QAAQ;KACzB,qBAAmB,EAAA,CAAA,CAAO,CAAC,gBAAgB;KAC3C,aAAW,EAAA,CAAA,CAAO,CAAC,SAAS;KAC5B,uBAAqB,EAAA,CAAA,CAAE,CAAC,kBAAkB;KAC1C,YAAU,EAAA,CAAA,CAAO,CAAC;KAClB,gBAAe,EAAA,CAAA,CAAE,CAAC;KAClB,gBAAe,EAAA,CAAA,CAAE,CAAC;KAClB,gBAAe,EAAA,CAAA,CAAE,CAAC;KAClB,sBAAsB,EAAA,CAAA,CAAO,CAAC;;;;;;;;;;;;;OAMrC,EAqMM,OArMN,IAqMM,CAnMJ,EAsJM,OAtJN,IAsJM,CAlJJ,EAqFM,OArFN,IAqFM;IAlFI,EAAA,SAAA,EAAA,GADR,EAsBS,UAAA;;KApBP,OAAM;KACL,OAAK,EAAA;aAA2B,EAAA,CAAA,CAAE,CAAC,YAAY,QAAA,uBAAA;uBAA6H,EAAA,CAAA,CAAE,CAAC,YAAY,QAAA,kBAAA;cAAqG,EAAA,CAAA,CAAE,CAAC,YAAY,QAAA,gCAAA;;KAW/S,OAAwB,EAAA,CAAA,CAAE,CAAC,YAAY,QAA0B,EAAA,MAAE,aAAa,cAAgC,EAAA,MAAE,aAAa;KAK/H,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAE,CAAC,YAAY,QAAK,CAAI,EAAA,CAAA,CAAE,CAAC,YAAY;QAE/C,EAA0C,EAAA,EAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;;IAGvB,EAAA,CAAA,CAAO,CAAC,SAAS,UAAK,qBAAA,EAAA,GACpC,EAKO,QALP,IAKO,EADF,EAAA,MAAE,aAAa,cAAc,GAAA,CAAA,MAAA,EAAA,GAIlC,EAIE,GAAA;;KAHC,SAAS,EAAA,CAAA,CAAO,CAAC,QAAQ;KACzB,qBAAmB,EAAA,CAAA,CAAO,CAAC,gBAAgB;KAC3C,YAAU,EAAA,CAAA,CAAO,CAAC;;;;;;IAKvB,EAyCM,OAzCN,IAyCM,CAlCJ,EAgBS,UAAA;KAfP,OAAM;KACL,OAAK,EAAA;aAAiD,EAAA,CAAA,CAAE,CAAC,WAAW,UAAK,SAAA,uBAAA;uBAAiK,EAAA,CAAA,CAAE,CAAC,WAAW,UAAK,SAAA,2BAAA;;KAU7P,OAAO,EAAA,MAAE,aAAa;KACtB,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAE,CAAC,WAAW,QAAK;QAE3B,EAAwC,EAAA,EAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;kBAErC,EAgBS,UAAA;KAfP,OAAM;KACL,OAAK,EAAA;aAAiD,EAAA,CAAA,CAAE,CAAC,WAAW,UAAK,SAAA,uBAAA;uBAAiK,EAAA,CAAA,CAAE,CAAC,WAAW,UAAK,SAAA,2BAAA;;KAU7P,OAAO,EAAA,MAAE,aAAa;KACtB,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAE,CAAC,WAAW,QAAK;QAE3B,EAAqC,EAAA,EAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;;OAKtC,EA0DM,OA1DN,IA0DM,CAxDI,EAAA,CAAA,CAAmB,CAAC,SAAM,KAAA,EAAA,GADlC,EAyBS,UAAA;;IAvBP,OAAM;IACN,OAAA;KAAA,gBAAA;KAAA,oBAAA;KAAA,OAAA;IAAA;IAKC,OAAO,EAAA,CAAA,CAAO,CAAC,eAAe,SAAK;IACnC,UAAM,AAAA,EAAA,QAAA,MAAmB,EAAA,CAAA,CAAO,CAAC,iBAAqC,EAAO,OAA6B,SAAK,IAAA;OAMhH,EAES,UAFT,GAES,EADJ,EAAA,MAAE,aAAa,SAAS,GAAA,CAAA,IAAA,EAAA,EAAA,GAE7B,EAMS,GAAA,MAAA,EALY,EAAA,CAAA,IAAZ,YADT,EAMS,UAAA;IAJN,KAAK;IACL,OAAO;QAEL,EAAA,CAAA,CAAE,CAAC,iBAAiB,CAAQ,CAAA,GAAA,GAAA,EAAA,mCAGnC,EA8BS,UAAA;IA7BP,OAAM;IACN,OAAA;KAAA,gBAAA;KAAA,oBAAA;KAAA,OAAA;IAAA;IAKC,OAAO,EAAA,CAAA,CAAO,CAAC,WAAW;IAC1B,UAAM,AAAA,EAAA,QAAA,MAAmB,EAAA,CAAA,CAAO,CAAC,OAAQ,EAAO,OAA6B,KAAK;;IAInF,EAES,UAFT,IAES,EADJ,EAAA,MAAE,aAAa,UAAU,GAAA,CAAA;IAE9B,EAES,UAFT,IAES,EADJ,EAAA,MAAE,aAAa,UAAU,GAAA,CAAA;IAE9B,EAES,UAFT,IAES,EADJ,EAAA,MAAE,aAAa,WAAW,GAAA,CAAA;IAE/B,EAES,UAFT,IAES,EADJ,EAAA,MAAE,aAAa,YAAY,GAAA,CAAA;IAEhC,EAES,UAFT,IAES,EADJ,EAAA,MAAE,aAAa,WAAW,GAAA,CAAA;IAE/B,EAES,UAFT,IAES,EADJ,EAAA,MAAE,aAAa,YAAY,GAAA,CAAA;mBAOtC,EAyCM,OAzCN,IAyCM,CAtCI,EAAA,CAAA,CAAO,CAAC,SAAS,UAAK,WAAA,EAAA,GAD9B,EAsBM,OAtBN,IAsBM,CAlBJ,EAIE,GAAA;IAHC,gBAAc,EAAA,CAAA,CAAO,CAAC,YAAY;IAClC,mBAAiB,EAAA,CAAA,CAAO,CAAC,eAAe;IACxC,UAAQ,EAAA,CAAA,CAAE,CAAC;;;;;OAGN,EAAA,SAAA,EAAA,GADR,EAYS,UAAA;;IAVP,OAAM;IACN,OAAA;KAAA,gBAAA;KAAA,OAAA;KAAA,oBAAA;IAAA;IAKC,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAE,CAAC,mBAAmB,QAAK;OAEnC,EAAqC,EAAA,EAAA,GAAA;IAA9B,MAAM;IAAK,gBAAc;SAAK,MACrC,EAAG,EAAA,MAAE,aAAa,aAAa,GAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAKnC,EAaE,GAAA;IAZC,OAAO,EAAA,CAAA,CAAE,CAAC,aAAa;IACvB,gBAAc,EAAA,CAAA,CAAO,CAAC,cAAc;IACpC,cAAY,EAAA,CAAA,CAAO,CAAC,UAAU;IAC9B,YAAyB,EAAA,CAAA,CAAO,CAAC,SAAS,UAAK,WAAgB,EAAA,CAAA,CAAO,CAAC,QAAQ;IAG/E,QAAQ,EAAA,CAAA,CAAE,CAAC,WAAW;IACtB,UAAQ,EAAA,CAAA,CAAE,CAAC;IACX,UAAQ,EAAA,CAAA,CAAO,CAAC;IAChB,YAAW,EAAA,CAAA,CAAO,CAAC;IACnB,QAAM,EAAA,CAAA,CAAE,CAAC;IACT,WAAS,EAAA,CAAA,CAAE,CAAC;;;;;;;;;;;;;GAOrB,EAME,IAAA;IALC,SAAS,EAAA,CAAA,CAAE,CAAC,mBAAmB;IAC/B,gBAAc,EAAA,CAAA,CAAO,CAAC,mBAAmB;IACzC,OAAO,EAAA,CAAA,CAAO,CAAC,mBAAmB;IAClC,UAAQ,EAAA,CAAA,CAAE,CAAC;IACX,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAE,CAAC,mBAAmB,QAAK;;;;;;;GAIrC,EAKE,IAAA;IAJC,SAAO,CAAA,CAAI,EAAA,CAAA,CAAE,CAAC,YAAY;IAC1B,MAAM,EAAA,CAAA,CAAE,CAAC,YAAY;IACrB,QAAM,EAAA,CAAA,CAAE,CAAC;IACT,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAE,CAAC,YAAY,QAAK;;;;;;GAI9B,EAQE,IAAA;IAPC,SAAS,EAAA,CAAA,CAAO,CAAC,mBAAmB;IACpC,MAAM,EAAA,CAAA,CAAO,CAAC,mBAAmB;IACjC,cAAY,EAAA,CAAA,CAAO,CAAC,iBAAiB;IACrC,gBAAc,EAAA,CAAA,CAAO,CAAC,YAAY;IAClC,OAAO,EAAA,CAAA,CAAO,CAAC,aAAa;IAC5B,WAAS,EAAA,CAAA,CAAE,CAAC;IACZ,SAAO,EAAA,CAAA,CAAO,CAAC;;;;;;;;;;GAIlB,EA2Ga,GAAA;IA1GX,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;IACf,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;;qBAoGT,CAjGE,EAAA,CAAA,CAAO,CAAC,kBAAkB,SAAA,EAAA,GADlC,EAkGM,OAAA;;KAhGJ,OAAM;KACN,OAAA;MAAA,oBAAA;MAAA,mBAAA;MAAA,2BAAA;KAAA;KAKC,SAAK,AAAA,EAAA,QAAA,IAAA,GAAA,MAAO,EAAA,CAAA,CAAO,CAAC,gBAAR,EAAA,CAAA,CAAO,CAAC,aAAY,GAAA,CAAA,GAAA,CAAA,MAAA,CAAA;QAEjC,EAuFM,OAvFN,IAuFM;KAhFJ,EAKK,MALL,IAKK,EADA,EAAA,MAAE,aAAa,kBAAkB,GAAA,CAAA;KAEtC,EAMI,KAAA;MALF,OAAK,GAAA,CAAC,eACE,EAAA,CAAA,CAAE,CAAC,aAAa,QAAK,aAAA,UAAA,CAAA;MAC7B,OAAA,EAAA,OAAA,wBAAA;UAEG,EAAA,MAAE,aAAa,oBAAoB,GAAA,CAAA;KAGhC,EAAA,CAAA,CAAE,CAAC,aAAa,SAAA,EAAA,GADxB,EAMI,KANJ,IAMI,EADC,EAAA,MAAE,aAAa,sBAAsB,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;KAIlC,EAAA,CAAA,CAAE,CAAC,aAAa,SAAA,EAAA,GADxB,EA6BM,OA7BN,IA6BM,EAAA,EAAA,EAAA,GAxBJ,EAuBM,GAAA,MAAA,EAtBsB,EAAA,CAAA,CAAO,CAAC,gBAAgB,QAA1C,GAAM,YADhB,EAuBM,OAAA;MArBH,KAAK;MACN,OAAM;MACN,OAAA,EAAA,OAAA,kBAAA;SAEgB,EAAK,iBAAc,KAAA,EAAA,GAAnC,EAgBW,GAAA,EAAA,KAAA,EAAA,GAAA,CAfT,EAKO,QALP,IAKO,EAHH,EAAA,CAAA,CAAE,CAAC,aAAa,MAAM,MAAM,MAAM,EAAE,OAAO,CAAO,CAAA,EAA0B,YAAY,CAAO,GAAA,CAAA,GAInG,EAQO,QARP,IAA2C,QAEzC,EACE,EAAA,MAAE,aAAa,gBAAgB,QAAA,WAAgE,EAAK,eAAe,SAAQ,CAAA,CAAA,GAAA,CAAA,CAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA;KAUrI,EA2BM,OA3BN,IA2BM,CA1BJ,EAUS,UAAA;MATP,OAAM;MACN,OAAA;OAAA,gBAAA;OAAA,OAAA;OAAA,oBAAA;MAAA;MAKC,SAAK,AAAA,EAAA,QAAA,GAAA,MAAE,EAAA,CAAA,CAAO,CAAC,gBAAR,EAAA,CAAA,CAAO,CAAC,aAAY,GAAA,CAAA;UAEzB,EAAA,MAAE,aAAa,MAAM,GAAA,CAAA,GAE1B,EAcS,UAAA;MAbP,OAAM;MACN,OAAA;OAAA,gBAAA;OAAA,OAAA;OAAA,oBAAA;MAAA;MAKC,SAAK,AAAA,EAAA,SAAA,GAAA,MAAE,EAAA,CAAA,CAAO,CAAC,iBAAR,EAAA,CAAA,CAAO,CAAC,cAAa,GAAA,CAAA;UAG3B,EAAA,CAAA,CAAE,CAAC,aAAa,QAA0B,EAAA,MAAE,aAAa,eAAiC,EAAA,MAAE,aAAa,aAAa,GAAA,CAAA,CAAA,CAAA;;;;GAWlI,EAkFM,OAlFN,IAkFM,CA9EJ,EAOM,OAPN,IAOM,CALI,EAAA,CAAA,CAAO,CAAC,YAAY,SAAA,EAAA,GAD5B,EAKE,GAAA;;IAHQ,uBAAqB,EAAA,CAAA,CAAE,CAAC,mBAAmB;sDAAtB,CAAA,CAAE,CAAC,mBAAmB,QAAK;IACvD,MAAM,EAAA,CAAA,CAAO,CAAC,YAAY;IAC1B,SAAS,EAAA,CAAA,CAAO,CAAC,QAAQ;;;;;sBAG9B,EAqEM,OArEN,IAqEM,CAlEI,EAAA,CAAA,CAAO,CAAC,cAAc,MAAM,OAAI,KAAA,EAAA,GADxC,EA0CM,OA1CN,IA0CM,CArCI,EAAA,CAAA,CAAO,CAAC,YAAY,SAAA,EAAA,GAD5B,EAiBS,UAAA;;IAfP,OAAM;IACL,OAAK,EAAA;kBAA+B,EAAA,CAAA,CAAE,CAAC,OAAO,QAAA,uBAAA;YAAyG,EAAA,CAAA,CAAE,CAAC,OAAO,QAAK,uBAAA;;;IAOtK,SAAK,AAAA,EAAA,SAAA,MAAE,EAAA,CAAA,CAAE,CAAC,KAAK,EAAA,CAAA,CAAE,CAAC,YAAY,KAAK;OAEvB,EAAA,CAAA,CAAE,CAAC,OAAO,cACvB,EAA6C,EAAA,CAAA,GAAA;;IAA9B,MAAM;IAAK,gBAAc;UADjB,EAAA,GAAvB,EAA6D,EAAA,EAAA,GAAA;;IAA9B,MAAM;IAAK,gBAAc;UACX,MAC7C,EACE,EAAA,CAAA,CAAE,CAAC,OAAO,QAAQ,EAAA,MAAE,aAAa,SAAS,EAAA,MAAE,aAAa,OAAO,GAAA,CAAA,CAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAGzD,EAAA,SAAA,EAAA,GAAX,EAmBM,OAnBN,IAmBM,CAlBJ,EAUS,UAAA;IATP,OAAM;IACN,OAAA;KAAA,gBAAA;KAAA,OAAA;KAAA,oBAAA;IAAA;IAKC,SAAK,AAAA,EAAA,SAAA,MAAE,EAAA,CAAA,CAAE,CAAC,eAAe,QAAK,CAAI,EAAA,CAAA,CAAE,CAAC,eAAe;QAElD,EAAA,MAAE,aAAa,YAAY,GAAA,CAAA,GAGxB,EAAA,CAAA,CAAE,CAAC,eAAe,SAAA,EAAA,GAD1B,EAME,GAAA;;IAJC,SAAS,EAAA,CAAA,CAAO,CAAC,QAAQ;IACzB,qBAAmB,EAAA,CAAA,CAAO,CAAC,gBAAgB;IAC3C,UAAQ,EAAA,CAAA,CAAE,CAAC;IACX,SAAK,AAAA,EAAA,SAAA,MAAE,EAAA,CAAA,CAAE,CAAC,eAAe,QAAK;;;;;kDAKrC,EAsBM,OAtBN,IAsBM,CApBI,EAAA,CAAA,CAAO,CAAC,cAAc,MAAM,OAAI,KAAA,EAAA,GADxC,EAWS,UAAA;;IATP,OAAM;IACN,OAAA;KAAA,gBAAA;KAAA,OAAA;KAAA,oBAAA;IAAA;IAKC,SAAK,AAAA,EAAA,SAAA,GAAA,MAAE,EAAA,CAAA,CAAE,CAAC,qBAAH,EAAA,CAAA,CAAE,CAAC,kBAAiB,GAAA,CAAA;QAEzB,EAAA,MAAE,aAAa,cAAc,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAG1B,EAAA,YAAA,EAAA,GADR,EAQS,UAAA;;IANP,OAAM;IACN,OAAA;KAAA,oBAAA;KAAA,OAAA;IAAA;IACC,UAAQ,CAAG,EAAA,CAAA,CAAO,CAAC,YAAY;IAC/B,SAAO;QAEL,EAAA,MAAE,aAAa,UAAU,GAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;;IE9lBlC,IAAgB,uBAAA,OAAA;CAAA,yBAAA,OAAA;CAAA,yBAAA,OAAA;CAAA,yBAAA,OAAA;CAAA,yBAAA,OAAA;CAAA,4BAAA,OAAA;AAAA,CAAA;AAItB,SAAS,EAAgB,GAA4C;CACnE,OAAO,OAAO,KAAK,CAAO,CAAC,CACxB,KAAK,MAAS,EAAK,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAChD,QAAQ,MAA6B,EAAQ,CAAO;AACzD;AAEA,IAAM,IAAmB,EAAgB,CAAa;AAEtD,SAAS,EAAa,GAAwB;CAC5C,OAAO,EAAO,KAAK,CAAC,CAAC,QAAQ,MAAM,GAAG,CAAC,CAAC,YAAY;AACtD;AAEA,SAAS,EAAoB,GAAoC;CAC/D,IAAM,IAAY,EAAa,CAAM;CACrC,OAAO,EAAiB,MAAM,MAAM,EAAa,CAAC,MAAM,CAAS;AACnE;AAEA,SAAS,GAAc,GAAwB;CAC7C,OAAO,EAAa,CAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACzC;AAEA,SAAS,GAAc,GAAwB;CAC7C,OACE,EAAoB,CAAM,KAC1B,EAAoB,GAAc,CAAM,CAAC,KACzC;AAEJ;AAEA,eAAsB,GACpB,GAC4B;CAE5B,IAAM,IAAS,EAAc,aADd,GAAc,CACa,EAAO;CAEjD,QAAO,MADc,EAAO,EAAA,CACd;AAChB;;;ACjCA,IAAI,IAA0B,MACxB,IACJ,EAAI,IAAI;AAEV,eAAe,GAAK,GAA2D;CAC7E,IAAM,IACJ,OAAO,EAAO,aAAc,WACxB,SAAS,cAAc,EAAO,SAAS,IACvC,EAAO;CAEb,IAAI,CAAC,GACH,MAAU,MAAM,gCAAgC,EAAO,WAAW;CAIpE,IAAM,IAAc,EAAqB,EAAO,MAAM,EAAO,OAAO;CACpE,MAAM,EAAY,WAAW;CAI7B,IAAM,IAAyB,MAAM,IADf,EAAU,CACK,CAAA,CAAU,YAAY,GAGrD,IAAkC,MAAM,GAC5C,EAAO,UAAU,IACnB;CAYA,OATA,EAAW,GAA0B,EAAO,KAAK,GAK7C,KACF,EAAQ,GAGH,IAAI,SAAS,GAAS,MAAW;EACtC,IAAI;GA0BF,AAzBA,IAAc,EAAU,EACtB,QAAQ;IACN,IAAM,UAAgB;KAMpB,EAAQ;MAJN,WAAW,MAAU,EAAW,GAA0B,CAAK;MAC/D;KAGM,CAAQ;IAClB;IAEA,aACE,EAAE,GAAc;KACd;KACA,WAAW,EAAY;KACvB;KACA;KACA,UAAU,EAAO;KACjB,SAAS,EAAO;KAChB,KAAK;KACL;IACF,CAAC;GACL,EACF,CAAC,GAED,EAAY,MAAM,CAAS;EAC7B,SAAS,GAAO;GACd,EAAO,CAAK;EACd;CACF,CAAC;AACH;AAEA,SAAS,IAAgB;CACvB,AAAI,MACF,EAAY,QAAQ,GACpB,IAAc,MACd,EAAgB,QAAQ;AAE5B;AAEA,SAAS,EACP,GACA,GACM;CACD,MAID,EAAM,gBACR,EAAU,MAAM,YAAY,iBAAiB,EAAM,YAAY,GAG7D,EAAM,iBAAiB,KAAA,MACzB,EAAU,MAAM,YAAY,gBAAgB,GAAG,EAAM,aAAa,GAAG,GACrE,EAAU,MAAM,YACd,mBACA,GAAG,KAAK,IAAI,GAAG,EAAM,eAAe,CAAC,EAAE,GACzC,GACA,EAAU,MAAM,YACd,mBACA,GAAG,EAAM,eAAe,EAAE,GAC5B;AAEJ;AAQI,OAAO,SAAW,QACpB,OAEE,mBAAmB;CARrB;CACA;AAOqB"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { C as e, F as t, G as n, H as r, J as i, K as a, L as o, M as s, O as c, P as l, T as u, V as d, Y as f, Z as p, b as m, c as h, ct as g, f as _, g as v, h as y, it as b, l as x, m as S, n as C, o as w, ot as T, p as E, s as D, st as O, t as k, u as A, v as j, x as M, y as N, z as P } from "./draggable-D840DIZB.js";
|
|
2
|
-
import { $t as F, A as ee, An as I, At as L, B as te, Bt as R, Cn as z, Ct as B, Dn as V, Dt as H, En as U, Et as ne, F as re, Fn as ie, G as ae, Gt as oe, H as se, Ht as ce, I as le, In as W, J as ue, K as de, Kt as fe, L as pe, Lt as me, M as he, Mt as ge, N as _e, O as ve, Ot as ye, P as be, Pn as xe, Pt as Se, Qt as Ce, Rt as we, Sn as Te, Tn as Ee, Tt as De, U as Oe, W as ke, Wt as Ae, Xt as je, Y as Me, Yt as Ne, Zt as Pe, an as Fe, at as Ie, cn as Le, ct as Re, dn as ze, dt as Be, en as Ve, et as He, fn as Ue, ht as We, in as Ge, it as Ke, j as qe, jn as Je, kn as Ye, kt as Xe, ln as Ze, lt as Qe, nn as $e, pt as et, q as tt, rn as nt, tn as rt, un as it, ut as at, wt as ot, yn as st, yt as ct, z as lt, zn as ut, zt as dt } from "./features-
|
|
3
|
-
import { A as ft, F as pt, G as mt, I as ht, M as gt, N as _t, O as vt, P as yt, T as G, V as bt, X as xt, Y as St, _ as Ct, b as wt, c as Tt, h as Et, m as Dt, o as Ot, s as kt, u as At, v as jt, y as Mt, z as Nt } from "./icons-
|
|
2
|
+
import { $t as F, A as ee, An as I, At as L, B as te, Bt as R, Cn as z, Ct as B, Dn as V, Dt as H, En as U, Et as ne, F as re, Fn as ie, G as ae, Gt as oe, H as se, Ht as ce, I as le, In as W, J as ue, K as de, Kt as fe, L as pe, Lt as me, M as he, Mt as ge, N as _e, O as ve, Ot as ye, P as be, Pn as xe, Pt as Se, Qt as Ce, Rt as we, Sn as Te, Tn as Ee, Tt as De, U as Oe, W as ke, Wt as Ae, Xt as je, Y as Me, Yt as Ne, Zt as Pe, an as Fe, at as Ie, cn as Le, ct as Re, dn as ze, dt as Be, en as Ve, et as He, fn as Ue, ht as We, in as Ge, it as Ke, j as qe, jn as Je, kn as Ye, kt as Xe, ln as Ze, lt as Qe, nn as $e, pt as et, q as tt, rn as nt, tn as rt, un as it, ut as at, wt as ot, yn as st, yt as ct, z as lt, zn as ut, zt as dt } from "./features-B3qgDBHf.js";
|
|
3
|
+
import { A as ft, F as pt, G as mt, I as ht, M as gt, N as _t, O as vt, P as yt, T as G, V as bt, X as xt, Y as St, _ as Ct, b as wt, c as Tt, h as Et, m as Dt, o as Ot, s as kt, u as At, v as jt, y as Mt, z as Nt } from "./icons-kiMqh99T.js";
|
|
4
4
|
import { t as Pt } from "./readableTextColor-f8Kykfnh.js";
|
|
5
|
-
import { t as Ft } from "./CountdownBlock-
|
|
6
|
-
import { t as It } from "./blockTypeIcons-
|
|
7
|
-
import { _ as Lt, f as K, g as Rt, h as q, i as zt, l as Bt, m as J, n as Vt, p as Y, t as X, u as Ht } from "./ColorPicker-
|
|
5
|
+
import { t as Ft } from "./CountdownBlock-BmGqb7Zi.js";
|
|
6
|
+
import { t as It } from "./blockTypeIcons-DNMvDz5B.js";
|
|
7
|
+
import { _ as Lt, f as K, g as Rt, h as q, i as zt, l as Bt, m as J, n as Vt, p as Y, t as X, u as Ht } from "./ColorPicker-CPMWLHpa.js";
|
|
8
8
|
import { n as Ut, r as Wt } from "./MergeTagSuggestion-rpZ6Ol-i.js";
|
|
9
9
|
import { t as Z } from "./ToggleSwitch-OrmX_w18.js";
|
|
10
|
-
import { n as Q, r as Gt, t as Kt } from "./NumberWithSuffix-
|
|
10
|
+
import { n as Q, r as Gt, t as Kt } from "./NumberWithSuffix-lqQlf0Uk.js";
|
|
11
11
|
//#region src/utils/resolveLintOptions.ts
|
|
12
12
|
function qt(e) {
|
|
13
13
|
return {
|
|
@@ -3046,7 +3046,7 @@ var co = { class: "tpl:mb-3.5" }, lo = ["value"], uo = ["value"], fo = {
|
|
|
3046
3046
|
"duplicate"
|
|
3047
3047
|
],
|
|
3048
3048
|
setup(e, { emit: t }) {
|
|
3049
|
-
let n = m(() => import("./CountdownToolbar-
|
|
3049
|
+
let n = m(() => import("./CountdownToolbar-BBwsdGbV.js")), r = e, i = t, { t: a } = R(), c = Ue(Ve, "Toolbar"), l = u(je, []), d = _(() => r.block.type), f = _(() => ut(r.block)), p = _(() => {
|
|
3050
3050
|
if (f.value) return l.find((e) => e.type === r.block.customType);
|
|
3051
3051
|
}), h = _(() => f.value ? p.value?.name ?? r.block.customType : dt(d.value, a)), x = c.fonts;
|
|
3052
3052
|
function C(e) {
|
|
@@ -3194,7 +3194,7 @@ var co = { class: "tpl:mb-3.5" }, lo = ["value"], uo = ["value"], fo = {
|
|
|
3194
3194
|
"update-settings"
|
|
3195
3195
|
],
|
|
3196
3196
|
setup(e, { emit: t }) {
|
|
3197
|
-
let n = m(() => import("./IssuesPanel-
|
|
3197
|
+
let n = m(() => import("./IssuesPanel-G0z-j3JS.js")), r = e, i = t, { t: a } = R(), o = p("content"), c = u(Le, null), l = _(() => c !== null), d = _(() => c?.issues.value.length ?? 0);
|
|
3198
3198
|
function f(e) {
|
|
3199
3199
|
return o.value === e ? "tpl:flex-1 tpl:text-[var(--tpl-primary)]" : "tpl:shrink-0 tpl:text-[var(--tpl-text-muted)] hover:tpl:text-[var(--tpl-text)]";
|
|
3200
3200
|
}
|
|
@@ -3963,4 +3963,4 @@ var co = { class: "tpl:mb-3.5" }, lo = ["value"], uo = ["value"], fo = {
|
|
|
3963
3963
|
//#endregion
|
|
3964
3964
|
export { Oc as a, vc as c, an as d, qt as f, Ac as i, gn as l, Qc as n, Ec as o, Nc as r, Cc as s, yl as t, on as u };
|
|
3965
3965
|
|
|
3966
|
-
//# sourceMappingURL=styles-
|
|
3966
|
+
//# sourceMappingURL=styles-B6rdq9JB.js.map
|