@templatical/editor 0.4.0 → 0.5.1

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.
Files changed (76) hide show
  1. package/dist/{AiFeatureMenu-vatvCD-m.js → AiFeatureMenu-D7Od4cI2.js} +1 -1
  2. package/dist/{CloudEditor-Bxe8Jt9u.js → CloudEditor-DG8fWnXI.js} +4 -4
  3. package/dist/{CollaboratorBar-Dv7VT09N.js → CollaboratorBar-BdXfCYAr.js} +1 -1
  4. package/dist/{ModuleBrowserModal-DAnqdlyq.js → ModuleBrowserModal-DpMInJoP.js} +4 -4
  5. package/dist/{ModulePreviewCanvas-CXApEVEG.js → ModulePreviewCanvas-MjIGlxVI.js} +1 -1
  6. package/dist/{ParagraphEditor-Bjdakcoz.js → ParagraphEditor-B5qZL5c2.js} +7 -7
  7. package/dist/{SaveModuleDialog-CZXltahx.js → SaveModuleDialog-BGFYMJby.js} +2 -2
  8. package/dist/{SnapshotHistory-OqEkaA0W.js → SnapshotHistory-4aWE_-GM.js} +1 -1
  9. package/dist/{TestEmailModal-CvEK6MTy.js → TestEmailModal-p-iH28wl.js} +2 -2
  10. package/dist/{TitleEditor-CxCD70Bs.js → TitleEditor-BHxJ6Oxd.js} +3 -3
  11. package/dist/{TplModal-C2Hoz1it.js → TplModal-BiUCSfou.js} +1 -1
  12. package/dist/{blockTypeIcons-DpJa9awv.js → blockTypeIcons-8GJD96Tw.js} +1 -1
  13. package/dist/bundle-stats.json +6 -6
  14. package/dist/cdn/chunks/{AiFeatureMenu-BggCm6wN.js → AiFeatureMenu-DSXAYiMk.js} +2 -2
  15. package/dist/cdn/chunks/{AiFeatureMenu-BggCm6wN.js.map → AiFeatureMenu-DSXAYiMk.js.map} +1 -1
  16. package/dist/cdn/chunks/{CloudEditor-CTNhzoZ1.js → CloudEditor-CRYF-bR3.js} +6 -6
  17. package/dist/cdn/chunks/{CloudEditor-CTNhzoZ1.js.map → CloudEditor-CRYF-bR3.js.map} +1 -1
  18. package/dist/cdn/chunks/{CollaboratorBar-De-3lvDy.js → CollaboratorBar-CTFgLtUt.js} +3 -3
  19. package/dist/cdn/chunks/{CollaboratorBar-De-3lvDy.js.map → CollaboratorBar-CTFgLtUt.js.map} +1 -1
  20. package/dist/cdn/chunks/{CountdownBlock-CUAl8R-c.js → CountdownBlock-BKg-e3Uo.js} +2 -2
  21. package/dist/cdn/chunks/{CountdownBlock-CUAl8R-c.js.map → CountdownBlock-BKg-e3Uo.js.map} +1 -1
  22. package/dist/cdn/chunks/{CountdownToolbar-3zLcGAcb.js → CountdownToolbar-CPAOXOwI.js} +3 -3
  23. package/dist/cdn/chunks/{CountdownToolbar-3zLcGAcb.js.map → CountdownToolbar-CPAOXOwI.js.map} +1 -1
  24. package/dist/cdn/chunks/{ModuleBrowserModal-CxICY31A.js → ModuleBrowserModal-B70ZM4KG.js} +5 -5
  25. package/dist/cdn/chunks/{ModuleBrowserModal-CxICY31A.js.map → ModuleBrowserModal-B70ZM4KG.js.map} +1 -1
  26. package/dist/cdn/chunks/{ModulePreviewCanvas-Cv0zciNS.js → ModulePreviewCanvas-VHhQwuFP.js} +2 -2
  27. package/dist/cdn/chunks/{ModulePreviewCanvas-Cv0zciNS.js.map → ModulePreviewCanvas-VHhQwuFP.js.map} +1 -1
  28. package/dist/cdn/chunks/{NumberWithSuffix-BaVxnNI4.js → NumberWithSuffix-DnqYqSKs.js} +2 -2
  29. package/dist/cdn/chunks/{NumberWithSuffix-BaVxnNI4.js.map → NumberWithSuffix-DnqYqSKs.js.map} +1 -1
  30. package/dist/cdn/chunks/{ParagraphEditor-BrzlI8vp.js → ParagraphEditor-oVEaeerJ.js} +21 -21
  31. package/dist/cdn/chunks/ParagraphEditor-oVEaeerJ.js.map +1 -0
  32. package/dist/cdn/chunks/{RichTextEditorContent-9vq4MRDp.js → RichTextEditorContent-CmOwLOeY.js} +2 -2
  33. package/dist/cdn/chunks/{RichTextEditorContent-9vq4MRDp.js.map → RichTextEditorContent-CmOwLOeY.js.map} +1 -1
  34. package/dist/cdn/chunks/{SaveModuleDialog-Lco3k1xX.js → SaveModuleDialog-B6kNizps.js} +2 -2
  35. package/dist/cdn/chunks/{SaveModuleDialog-Lco3k1xX.js.map → SaveModuleDialog-B6kNizps.js.map} +1 -1
  36. package/dist/cdn/chunks/{TitleEditor-BiiEtH7x.js → TitleEditor-CvZe3neh.js} +9 -9
  37. package/dist/cdn/chunks/TitleEditor-CvZe3neh.js.map +1 -0
  38. package/dist/cdn/chunks/{blockTypeIcons-DWhn7E7O.js → blockTypeIcons-Bs9B-yft.js} +3 -3
  39. package/dist/cdn/chunks/{blockTypeIcons-DWhn7E7O.js.map → blockTypeIcons-Bs9B-yft.js.map} +1 -1
  40. package/dist/cdn/chunks/{de-DEg-6TsA.js → de-BSWt7lYu.js} +4 -4
  41. package/dist/cdn/chunks/de-BSWt7lYu.js.map +1 -0
  42. package/dist/cdn/chunks/{dist-DFfcnJJB.js → dist-MGrg9tLo.js} +2 -2
  43. package/dist/cdn/chunks/{dist-DFfcnJJB.js.map → dist-MGrg9tLo.js.map} +1 -1
  44. package/dist/cdn/chunks/{en-DpHxxBnH.js → en-9-vIGlc7.js} +4 -4
  45. package/dist/cdn/chunks/en-9-vIGlc7.js.map +1 -0
  46. package/dist/cdn/chunks/{extensions-C6oPJqKD.js → extensions-D13MqxlW.js} +16 -7
  47. package/dist/cdn/chunks/{extensions-C6oPJqKD.js.map → extensions-D13MqxlW.js.map} +1 -1
  48. package/dist/cdn/chunks/{features-DV4PhoBs.js → features-BnG-dhzy.js} +18 -15
  49. package/dist/cdn/chunks/{features-DV4PhoBs.js.map → features-BnG-dhzy.js.map} +1 -1
  50. package/dist/cdn/chunks/{icons-LJ8U8lWI.js → icons-B_185qj_.js} +2 -2
  51. package/dist/cdn/chunks/{icons-LJ8U8lWI.js.map → icons-B_185qj_.js.map} +1 -1
  52. package/dist/cdn/chunks/{media-library-CWQAvfov.js → media-library-DxpFw4Tt.js} +3 -3
  53. package/dist/cdn/chunks/{media-library-CWQAvfov.js.map → media-library-DxpFw4Tt.js.map} +1 -1
  54. package/dist/cdn/chunks/{src-CVBDXDBH.js → src-Cw7KAyui.js} +4 -4
  55. package/dist/cdn/chunks/{src-CVBDXDBH.js.map → src-Cw7KAyui.js.map} +1 -1
  56. package/dist/cdn/chunks/{styles-CFnn-xE6.js → styles-DYDpAUsJ.js} +12 -12
  57. package/dist/cdn/chunks/styles-DYDpAUsJ.js.map +1 -0
  58. package/dist/cdn/chunks/{tiptap-kGWe8qnA.js → tiptap-CPAwPMop.js} +2 -2
  59. package/dist/cdn/chunks/{tiptap-kGWe8qnA.js.map → tiptap-CPAwPMop.js.map} +1 -1
  60. package/dist/cdn/editor.css +1 -1
  61. package/dist/cdn/editor.js +7 -7
  62. package/dist/{de-tDioEErp.js → de-DwLWZn6p.js} +3 -3
  63. package/dist/{en-W2p7oPaa.js → en-BrlGVpmd.js} +3 -3
  64. package/dist/{extensions-BQjnrlGT.js → extensions-Cmf6XVn9.js} +14 -5
  65. package/dist/index.d.ts +8 -8
  66. package/dist/style.css +1 -1
  67. package/dist/{styles-CdrFC7-K.js → styles-C-FrkTA9.js} +8 -8
  68. package/dist/templatical-editor.js +5 -5
  69. package/dist/{useEditorCore-JdLcaPeJ.js → useEditorCore-D0uZbPKG.js} +1717 -1714
  70. package/dist/{useMergeTag-BfFykpYl.js → useMergeTag-CEE4CG-D.js} +1 -1
  71. package/package.json +5 -5
  72. package/dist/cdn/chunks/ParagraphEditor-BrzlI8vp.js.map +0 -1
  73. package/dist/cdn/chunks/TitleEditor-BiiEtH7x.js.map +0 -1
  74. package/dist/cdn/chunks/de-DEg-6TsA.js.map +0 -1
  75. package/dist/cdn/chunks/en-DpHxxBnH.js.map +0 -1
  76. package/dist/cdn/chunks/styles-CFnn-xE6.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { $ as e, F as t, H as n, N as r, P as i, S as a, _ as o, at as s, b as c, ct as l, d as u, g as d, h as f, j as ee, lt as p, m, n as h, p as g, r as _, st as v, u as te, w as y, y as b } from "./draggable-Bcb86AsV.js";
2
- import { Dt as ne, O as x, w as S, xt as re } from "./features-DV4PhoBs.js";
3
- import { L as ie, U as ae, k as oe, y as se, z as ce } from "./icons-LJ8U8lWI.js";
4
- import { a as le, c as ue, d as C, f as w, h as T, i as E, l as D, n as O, o as k, p as A, r as j, s as M, t as N, u as P } from "./media-library-CWQAvfov.js";
2
+ import { Dt as ne, O as x, w as S, xt as re } from "./features-BnG-dhzy.js";
3
+ import { L as ie, U as ae, k as oe, y as se, z as ce } from "./icons-B_185qj_.js";
4
+ import { a as le, c as ue, d as C, f as w, h as T, i as E, l as D, n as O, o as k, p as A, r as j, s as M, t as N, u as P } from "./media-library-DxpFw4Tt.js";
5
5
  //#region ../media-library/src/standalone/MediaLibrary.vue?vue&type=script&setup=true&lang.ts
6
6
  var F = {
7
7
  class: "tpl tpl:flex tpl:flex-col tpl:overflow-hidden tpl:rounded-[var(--tpl-radius-lg)]",
@@ -494,4 +494,4 @@ typeof window < "u" && (window.TemplaticalMedia = {
494
494
  //#endregion
495
495
  export { N as MediaLibraryModal };
496
496
 
497
- //# sourceMappingURL=src-CVBDXDBH.js.map
497
+ //# sourceMappingURL=src-Cw7KAyui.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"src-CVBDXDBH.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","import type en from \"./locales/en\";\n\nexport type MediaTranslations = typeof en;\n\nconst supportedLocales = [\"en\", \"de\"];\n\nfunction getBaseLocale(locale: string): string {\n return locale.split(\"-\")[0].toLowerCase();\n}\n\nexport async function loadMediaTranslations(\n locale: string,\n): Promise<MediaTranslations> {\n const baseLocale = getBaseLocale(locale);\n const targetLocale = supportedLocales.includes(baseLocale)\n ? baseLocale\n : \"en\";\n\n const module = await import(`./locales/${targetLocale}.ts`);\n return module.default as MediaTranslations;\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-Cw7KAyui.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","import type en from \"./locales/en\";\n\nexport type MediaTranslations = typeof en;\n\nconst supportedLocales = [\"en\", \"de\"];\n\nfunction getBaseLocale(locale: string): string {\n return locale.split(\"-\")[0].toLowerCase();\n}\n\nexport async function loadMediaTranslations(\n locale: string,\n): Promise<MediaTranslations> {\n const baseLocale = getBaseLocale(locale);\n const targetLocale = supportedLocales.includes(baseLocale)\n ? baseLocale\n : \"en\";\n\n const module = await import(`./locales/${targetLocale}.ts`);\n return module.default as MediaTranslations;\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,12 +1,12 @@
1
1
  import { a as e } from "./rolldown-runtime-BNuo_Jkg.js";
2
2
  import { $ as t, B as n, E as r, F as i, H as a, I as o, N as s, R as c, S as l, U as u, Z as d, _ as f, at as p, b as m, c as h, ct as g, d as _, g as v, h as y, k as b, l as x, lt as S, m as C, n as w, p as T, s as E, st as D, t as O, u as k, x as A, y as j } from "./draggable-Bcb86AsV.js";
3
- import { A as ee, B as M, Et as te, F as N, G as ne, Gt as re, H as ie, Ht as P, I as F, It as ae, K as oe, Kt as se, L as ce, Lt as le, M as ue, Mt as I, N as de, P as fe, Pt as pe, Q as me, Qt as he, R as ge, Rt as _e, St as ve, U as ye, Ut as be, V as xe, Vt as Se, W as Ce, Wt as we, Z as Te, _n as Ee, _t as De, at as Oe, bn as ke, bt as Ae, cn as je, dn as Me, dt as Ne, fn as Pe, gn as Fe, gt as Ie, j as Le, jt as Re, kt as ze, mn as Be, nt as Ve, qt as He, rt as Ue, sn as We, st as Ge, tt as L, un as Ke, vn as R, vt as qe, wt as Je, xt as Ye, yt as Xe } from "./features-DV4PhoBs.js";
4
- import { A as Ze, B as Qe, F as $e, I as et, M as tt, N as nt, O as rt, P as z, T as B, _ as it, a as V, b as at, c as ot, h as st, m as ct, o as H, q as lt, s as ut, u as dt, v as ft } from "./icons-LJ8U8lWI.js";
3
+ import { A as ee, B as M, Et as te, F as N, G as ne, Gt as re, H as ie, Ht as P, I as F, It as ae, K as oe, Kt as se, L as ce, Lt as le, M as ue, Mt as I, N as de, P as fe, Pt as pe, Q as me, Qt as he, R as ge, Rt as _e, St as ve, U as ye, Ut as be, V as xe, Vt as Se, W as Ce, Wt as we, Z as Te, _n as Ee, _t as De, at as Oe, bn as ke, bt as Ae, cn as je, dn as Me, dt as Ne, fn as Pe, gn as Fe, gt as Ie, j as Le, jt as Re, kt as ze, mn as Be, nt as Ve, qt as He, rt as Ue, sn as We, st as Ge, tt as L, un as Ke, vn as R, vt as qe, wt as Je, xt as Ye, yt as Xe } from "./features-BnG-dhzy.js";
4
+ import { A as Ze, B as Qe, F as $e, I as et, M as tt, N as nt, O as rt, P as z, T as B, _ as it, a as V, b as at, c as ot, h as st, m as ct, o as H, q as lt, s as ut, u as dt, v as ft } from "./icons-B_185qj_.js";
5
5
  import { t as pt } from "./readableTextColor-Cd_cgWO_.js";
6
- import { t as mt } from "./CountdownBlock-CUAl8R-c.js";
7
- import { t as ht } from "./blockTypeIcons-DWhn7E7O.js";
6
+ import { t as mt } from "./CountdownBlock-BKg-e3Uo.js";
7
+ import { t as ht } from "./blockTypeIcons-Bs9B-yft.js";
8
8
  import { _ as gt, c as _t, f as U, g as vt, h as W, l as yt, m as G, p as K, t as bt } from "./styleConstants-DP1VOca8.js";
9
- import { i as q, n as J, r as Y, t as xt } from "./NumberWithSuffix-BaVxnNI4.js";
9
+ import { i as q, n as J, r as Y, t as xt } from "./NumberWithSuffix-DnqYqSKs.js";
10
10
  //#region src/components/Canvas.vue?vue&type=script&setup=true&lang.ts
11
11
  var St = /* @__PURE__ */ e(O(), 1), Ct = ["aria-label"], wt = { class: "tpl:relative" }, Tt = {
12
12
  class: "tpl:inline-flex tpl:size-3 tpl:items-center tpl:justify-center tpl:rounded-full tpl:text-[8px] tpl:font-bold",
@@ -318,7 +318,7 @@ var St = /* @__PURE__ */ e(O(), 1), Ct = ["aria-label"], wt = { class: "tpl:rela
318
318
  //#endregion
319
319
  //#region src/composables/useMergeTagField.ts
320
320
  function Ht(e) {
321
- let { modelValue: n, emit: r, elementRef: i } = e, { isEnabled: a, isRequesting: o, isMergeTagValue: s, getMergeTagLabel: c, requestMergeTag: l, syntax: u } = Te(), d = t(!1), f = !1, p = T(() => {
321
+ let { modelValue: n, emit: r, elementRef: i } = e, { canRequestMergeTag: a, isRequesting: o, isMergeTagValue: s, getMergeTagLabel: c, requestMergeTag: l, syntax: u } = Te(), d = t(!1), f = !1, p = T(() => {
322
322
  let e = n();
323
323
  if (!e) return [];
324
324
  let t = [], r = `(${u.value.source}|${u.logic.source})`, i = new RegExp(r, "g"), a = 0, o;
@@ -382,7 +382,7 @@ function Ht(e) {
382
382
  return {
383
383
  segments: p,
384
384
  hasMergeTags: m,
385
- mergeTagEnabled: a,
385
+ canRequestMergeTag: a,
386
386
  isRequestingMergeTag: o,
387
387
  isEditing: d,
388
388
  startEditing: h,
@@ -480,7 +480,7 @@ var Ut = ["aria-label", "onKeydown"], Wt = ["data-tooltip"], Gt = ["data-tooltip
480
480
  },
481
481
  emits: ["update:modelValue"],
482
482
  setup(e, { emit: n }) {
483
- let r = e, i = n, a = t(null), { segments: o, hasMergeTags: c, mergeTagEnabled: l, isRequestingMergeTag: u, isEditing: d, startEditing: h, stopEditing: g, handleInput: _, clearValue: b, insertMergeTag: S } = Ht({
483
+ let r = e, i = n, a = t(null), { segments: o, hasMergeTags: c, canRequestMergeTag: l, isRequestingMergeTag: u, isEditing: d, startEditing: h, stopEditing: g, handleInput: _, clearValue: b, insertMergeTag: S } = Ht({
484
484
  modelValue: () => r.modelValue,
485
485
  emit: (e) => i("update:modelValue", e),
486
486
  elementRef: a
@@ -620,7 +620,7 @@ var Ut = ["aria-label", "onKeydown"], Wt = ["data-tooltip"], Gt = ["data-tooltip
620
620
  },
621
621
  emits: ["update:modelValue"],
622
622
  setup(e, { emit: n }) {
623
- let r = e, i = n, a = t(null), { segments: o, hasMergeTags: c, mergeTagEnabled: l, isRequestingMergeTag: u, isEditing: d, startEditing: h, stopEditing: g, handleInput: _, clearValue: b, insertMergeTag: S } = Ht({
623
+ let r = e, i = n, a = t(null), { segments: o, hasMergeTags: c, canRequestMergeTag: l, isRequestingMergeTag: u, isEditing: d, startEditing: h, stopEditing: g, handleInput: _, clearValue: b, insertMergeTag: S } = Ht({
624
624
  modelValue: () => r.modelValue,
625
625
  emit: (e) => i("update:modelValue", e),
626
626
  elementRef: a
@@ -656,7 +656,7 @@ var Ut = ["aria-label", "onKeydown"], Wt = ["data-tooltip"], Gt = ["data-tooltip
656
656
  onInsert: p(S)
657
657
  }, null, 8, ["disabled", "onInsert"])) : v("", !0)]));
658
658
  }
659
- }), [["__scopeId", "data-v-b982cc87"]]), Nn = { class: "tpl:mb-3.5" }, Pn = ["value"], Fn = { value: "" }, In = ["value"], Ln = { class: "tpl:mb-3.5" }, Rn = { class: "tpl:mb-3.5" }, zn = {
659
+ }), [["__scopeId", "data-v-358207dd"]]), Nn = { class: "tpl:mb-3.5" }, Pn = ["value"], Fn = { value: "" }, In = ["value"], Ln = { class: "tpl:mb-3.5" }, Rn = { class: "tpl:mb-3.5" }, zn = {
660
660
  key: 0,
661
661
  class: "tpl:mt-2 tpl:flex tpl:cursor-pointer tpl:items-center tpl:gap-2 tpl:text-[12px] tpl:text-[var(--tpl-text-muted)]"
662
662
  }, Bn = ["checked"], Vn = { class: "tpl:grid tpl:grid-cols-2 tpl:gap-3" }, Hn = { class: "tpl:mb-3.5" }, Un = { class: "tpl:mb-3.5" }, Wn = { class: "tpl:grid tpl:grid-cols-2 tpl:gap-3" }, Gn = { class: "tpl:mb-3.5" }, Kn = { class: "tpl:flex tpl:items-stretch" }, qn = ["value"], Jn = { class: "tpl:mb-3.5" }, Yn = { class: "tpl:flex tpl:items-stretch" }, Xn = ["value"], Zn = /* @__PURE__ */ l({
@@ -2375,7 +2375,7 @@ var _i = {
2375
2375
  "duplicate"
2376
2376
  ],
2377
2377
  setup(e, { emit: t }) {
2378
- let n = A(() => import("./CountdownToolbar-3zLcGAcb.js")), i = e, a = t, { t: o } = I(), l = he(re, "Toolbar"), u = r(P, []), d = T(() => i.block.type), h = T(() => ke(i.block)), g = T(() => {
2378
+ let n = A(() => import("./CountdownToolbar-CPAOXOwI.js")), i = e, a = t, { t: o } = I(), l = he(re, "Toolbar"), u = r(P, []), d = T(() => i.block.type), h = T(() => ke(i.block)), g = T(() => {
2379
2379
  if (h.value) return u.find((e) => e.type === i.block.customType);
2380
2380
  }), b = T(() => h.value ? g.value?.name ?? i.block.customType : Re(d.value, o)), x = l.fonts;
2381
2381
  function w(e) {
@@ -2736,4 +2736,4 @@ var _i = {
2736
2736
  //#endregion
2737
2737
  export { Bo as a, Uo as i, qo as n, Vt as o, Go as r, Mt as s, Xo as t };
2738
2738
 
2739
- //# sourceMappingURL=styles-CFnn-xE6.js.map
2739
+ //# sourceMappingURL=styles-DYDpAUsJ.js.map