@templatical/editor 0.27.3 → 0.27.4

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 (128) hide show
  1. package/dist/{AiChatSidebar-inzMb2Vi.js → AiChatSidebar-LstHjwBU.js} +7 -7
  2. package/dist/{AiFeatureMenu-BTdgjwdx.js → AiFeatureMenu-DVQrznsN.js} +4 -4
  3. package/dist/{BlockIssueBadge-a7jENlL4.js → BlockIssueBadge-DKaFQNxW.js} +2 -2
  4. package/dist/{BlockPreviewCanvas-CMuRmhQg.js → BlockPreviewCanvas-D9eC04OA.js} +1 -1
  5. package/dist/{CloudHeaderExtras-Bgr-Ox9M.js → CloudHeaderExtras-DX0j3CJ3.js} +2 -2
  6. package/dist/{CloudPanels-oFNlTOO5.js → CloudPanels-DCeNSwXy.js} +3 -3
  7. package/dist/{CollaboratorBar-BHja900c.js → CollaboratorBar-BZ-JCjdM.js} +2 -2
  8. package/dist/{ColorPicker-ClUa_hMj.js → ColorPicker-j0TQu5lE.js} +1 -1
  9. package/dist/{CommentsPanel-CB1-poNb.js → CommentsPanel-c5LmzlNN.js} +1 -1
  10. package/dist/{CommentsSidebar-B6mV8ft4.js → CommentsSidebar-Bm1DxFb5.js} +10 -10
  11. package/dist/{CountdownToolbar-BpnKUXN_.js → CountdownToolbar-UPdwNvVI.js} +1 -1
  12. package/dist/{DesignReferenceSidebar-BC5UxrJl.js → DesignReferenceSidebar-C8WTApc5.js} +5 -5
  13. package/dist/{IssuesPanel-BFczwZkL.js → IssuesPanel-D49aJjLS.js} +5 -5
  14. package/dist/{MergeTagModeToggle-koHNtEJe.js → MergeTagModeToggle-CVzJY9b2.js} +2 -2
  15. package/dist/{ParagraphEditor-cKosDi_l.js → ParagraphEditor-C9-jQ5zP.js} +7 -7
  16. package/dist/{RestoreVersionDialog-DpZmcFuf.js → RestoreVersionDialog-Ds6gEF5u.js} +3 -3
  17. package/dist/{RichTextEditorContent-Br3WBNOs.js → RichTextEditorContent-CO1se6ln.js} +3 -3
  18. package/dist/{SaveBlockDialog-C7mSGScN.js → SaveBlockDialog-DJIcncsU.js} +6 -6
  19. package/dist/{SavedBlocksBrowserModal-D7MYzuVP.js → SavedBlocksBrowserModal-BUhhkGEb.js} +7 -7
  20. package/dist/{SavedBlocksPanels-D5T63WyR.js → SavedBlocksPanels-DBfPz4iB.js} +1 -1
  21. package/dist/{SavedBlocksPickBar-BluJS58M.js → SavedBlocksPickBar-D9NsfzCB.js} +2 -2
  22. package/dist/{TemplateScoringPanel-C0z27t2p.js → TemplateScoringPanel-BFsUqnXR.js} +10 -10
  23. package/dist/{TestEmailModal-DoSIuHXe.js → TestEmailModal-DARwBqpV.js} +6 -6
  24. package/dist/{TestEmailPanel-3Y6uUX3Z.js → TestEmailPanel-BkgAew1S.js} +1 -1
  25. package/dist/{TitleEditor-D9IWtoH3.js → TitleEditor-BWLwZh84.js} +4 -4
  26. package/dist/{TplModal-CyBCFn5s.js → TplModal-CJLs8as_.js} +1 -1
  27. package/dist/{VersionHistoryMenu-8nd_aOnh.js → VersionHistoryMenu-CrIVG_SN.js} +10 -10
  28. package/dist/{VersionHistoryPanels-Cm7MxfrI.js → VersionHistoryPanels-s45U7XY-.js} +1 -1
  29. package/dist/{VersionPreviewBanner-B9w773jz.js → VersionPreviewBanner-BIy95B34.js} +1 -1
  30. package/dist/{blockTypeIcons-BRCuWioG.js → blockTypeIcons-BjUkQsAe.js} +2 -2
  31. package/dist/bundle-stats.json +5 -5
  32. package/dist/cdn/chunks/{AiChatSidebar-BIvQg9Q5.js → AiChatSidebar-tZqbhmuJ.js} +2 -2
  33. package/dist/cdn/chunks/{AiChatSidebar-BIvQg9Q5.js.map → AiChatSidebar-tZqbhmuJ.js.map} +1 -1
  34. package/dist/cdn/chunks/{AiFeatureMenu-BMvcmvDZ.js → AiFeatureMenu-BhtNkpIq.js} +3 -3
  35. package/dist/cdn/chunks/{AiFeatureMenu-BMvcmvDZ.js.map → AiFeatureMenu-BhtNkpIq.js.map} +1 -1
  36. package/dist/cdn/chunks/{BlockIssueBadge-Drrmjqd7.js → BlockIssueBadge-D9L8j7Db.js} +2 -2
  37. package/dist/cdn/chunks/{BlockIssueBadge-Drrmjqd7.js.map → BlockIssueBadge-D9L8j7Db.js.map} +1 -1
  38. package/dist/cdn/chunks/{BlockPreviewCanvas-CuWJLv8h.js → BlockPreviewCanvas-Bt7fFzIQ.js} +2 -2
  39. package/dist/cdn/chunks/{BlockPreviewCanvas-CuWJLv8h.js.map → BlockPreviewCanvas-Bt7fFzIQ.js.map} +1 -1
  40. package/dist/cdn/chunks/{CloudHeaderExtras-Ctat5U0M.js → CloudHeaderExtras-CScGpeLl.js} +3 -3
  41. package/dist/cdn/chunks/{CloudHeaderExtras-Ctat5U0M.js.map → CloudHeaderExtras-CScGpeLl.js.map} +1 -1
  42. package/dist/cdn/chunks/{CloudPanels-YRYmXE9O.js → CloudPanels-DVtJkWsj.js} +4 -4
  43. package/dist/cdn/chunks/{CloudPanels-YRYmXE9O.js.map → CloudPanels-DVtJkWsj.js.map} +1 -1
  44. package/dist/cdn/chunks/{CollaboratorBar-DgdxBCkN.js → CollaboratorBar-BH1lM_Ta.js} +3 -3
  45. package/dist/cdn/chunks/{CollaboratorBar-DgdxBCkN.js.map → CollaboratorBar-BH1lM_Ta.js.map} +1 -1
  46. package/dist/cdn/chunks/{ColorPicker-B-we7_bC.js → ColorPicker-d4kY7WWd.js} +2 -2
  47. package/dist/cdn/chunks/{ColorPicker-B-we7_bC.js.map → ColorPicker-d4kY7WWd.js.map} +1 -1
  48. package/dist/cdn/chunks/{CommentsPanel-D7Y-74Nj.js → CommentsPanel-COhQMagD.js} +2 -2
  49. package/dist/cdn/chunks/{CommentsPanel-D7Y-74Nj.js.map → CommentsPanel-COhQMagD.js.map} +1 -1
  50. package/dist/cdn/chunks/{CommentsSidebar-DxTobvYS.js → CommentsSidebar-vzLX-_h3.js} +2 -2
  51. package/dist/cdn/chunks/{CommentsSidebar-DxTobvYS.js.map → CommentsSidebar-vzLX-_h3.js.map} +1 -1
  52. package/dist/cdn/chunks/{CountdownToolbar-D8QWL-jK.js → CountdownToolbar-BRDbI1mM.js} +2 -2
  53. package/dist/cdn/chunks/{CountdownToolbar-D8QWL-jK.js.map → CountdownToolbar-BRDbI1mM.js.map} +1 -1
  54. package/dist/cdn/chunks/{DesignReferenceSidebar-D9Lm4Al0.js → DesignReferenceSidebar-npLxDRJI.js} +2 -2
  55. package/dist/cdn/chunks/{DesignReferenceSidebar-D9Lm4Al0.js.map → DesignReferenceSidebar-npLxDRJI.js.map} +1 -1
  56. package/dist/cdn/chunks/{IssuesPanel-Dz90c1C6.js → IssuesPanel-CTGlv7HF.js} +2 -2
  57. package/dist/cdn/chunks/{IssuesPanel-Dz90c1C6.js.map → IssuesPanel-CTGlv7HF.js.map} +1 -1
  58. package/dist/cdn/chunks/{MergeTagModeToggle-CfFrfYNC.js → MergeTagModeToggle-CkpKFx9N.js} +2 -2
  59. package/dist/cdn/chunks/{MergeTagModeToggle-CfFrfYNC.js.map → MergeTagModeToggle-CkpKFx9N.js.map} +1 -1
  60. package/dist/cdn/chunks/{ParagraphEditor-Be-BO5hD.js → ParagraphEditor-BgeeE0Gj.js} +5 -5
  61. package/dist/cdn/chunks/{ParagraphEditor-Be-BO5hD.js.map → ParagraphEditor-BgeeE0Gj.js.map} +1 -1
  62. package/dist/cdn/chunks/{RestoreVersionDialog-CKtz_FEz.js → RestoreVersionDialog-tfoAQAeP.js} +3 -3
  63. package/dist/cdn/chunks/{RestoreVersionDialog-CKtz_FEz.js.map → RestoreVersionDialog-tfoAQAeP.js.map} +1 -1
  64. package/dist/cdn/chunks/{RichTextEditorContent-D3eWZ793.js → RichTextEditorContent-DvLBtUcW.js} +3 -3
  65. package/dist/cdn/chunks/{RichTextEditorContent-D3eWZ793.js.map → RichTextEditorContent-DvLBtUcW.js.map} +1 -1
  66. package/dist/cdn/chunks/{SaveBlockDialog-C5nT7Fxi.js → SaveBlockDialog-D67K2lHn.js} +5 -5
  67. package/dist/cdn/chunks/{SaveBlockDialog-C5nT7Fxi.js.map → SaveBlockDialog-D67K2lHn.js.map} +1 -1
  68. package/dist/cdn/chunks/{SavedBlocksBrowserModal-Cvyewimb.js → SavedBlocksBrowserModal-BxVR-yDt.js} +6 -6
  69. package/dist/cdn/chunks/{SavedBlocksBrowserModal-Cvyewimb.js.map → SavedBlocksBrowserModal-BxVR-yDt.js.map} +1 -1
  70. package/dist/cdn/chunks/{SavedBlocksPanels-B7aBlxKW.js → SavedBlocksPanels-VkKCO0uY.js} +2 -2
  71. package/dist/cdn/chunks/{SavedBlocksPanels-B7aBlxKW.js.map → SavedBlocksPanels-VkKCO0uY.js.map} +1 -1
  72. package/dist/cdn/chunks/{SavedBlocksPickBar-D0opM9P9.js → SavedBlocksPickBar-BJHQDgUT.js} +3 -3
  73. package/dist/cdn/chunks/{SavedBlocksPickBar-D0opM9P9.js.map → SavedBlocksPickBar-BJHQDgUT.js.map} +1 -1
  74. package/dist/cdn/chunks/{TemplateScoringPanel-DEsNZlHe.js → TemplateScoringPanel-MvdrkgqL.js} +2 -2
  75. package/dist/cdn/chunks/{TemplateScoringPanel-DEsNZlHe.js.map → TemplateScoringPanel-MvdrkgqL.js.map} +1 -1
  76. package/dist/cdn/chunks/{TestEmailModal-BANpGbEP.js → TestEmailModal-CEBFCevy.js} +6 -6
  77. package/dist/cdn/chunks/{TestEmailModal-BANpGbEP.js.map → TestEmailModal-CEBFCevy.js.map} +1 -1
  78. package/dist/cdn/chunks/{TestEmailPanel-DItZMP3B.js → TestEmailPanel-C35nqIIl.js} +2 -2
  79. package/dist/cdn/chunks/{TestEmailPanel-DItZMP3B.js.map → TestEmailPanel-C35nqIIl.js.map} +1 -1
  80. package/dist/cdn/chunks/{TitleEditor-D_NJ4Ww8.js → TitleEditor-c2aQCyds.js} +4 -4
  81. package/dist/cdn/chunks/{TitleEditor-D_NJ4Ww8.js.map → TitleEditor-c2aQCyds.js.map} +1 -1
  82. package/dist/cdn/chunks/{TplModal-C51W8LTn.js → TplModal-DSTVZKuI.js} +2 -2
  83. package/dist/cdn/chunks/{TplModal-C51W8LTn.js.map → TplModal-DSTVZKuI.js.map} +1 -1
  84. package/dist/cdn/chunks/{VersionHistoryMenu-Cv23A0uu.js → VersionHistoryMenu-BNYSIjVj.js} +4 -4
  85. package/dist/cdn/chunks/{VersionHistoryMenu-Cv23A0uu.js.map → VersionHistoryMenu-BNYSIjVj.js.map} +1 -1
  86. package/dist/cdn/chunks/{VersionHistoryPanels-DHDN1owI.js → VersionHistoryPanels-CvWySHUE.js} +2 -2
  87. package/dist/cdn/chunks/{VersionHistoryPanels-DHDN1owI.js.map → VersionHistoryPanels-CvWySHUE.js.map} +1 -1
  88. package/dist/cdn/chunks/{VersionPreviewBanner-Dw4kFkrh.js → VersionPreviewBanner-CBVDWnhq.js} +2 -2
  89. package/dist/cdn/chunks/{VersionPreviewBanner-Dw4kFkrh.js.map → VersionPreviewBanner-CBVDWnhq.js.map} +1 -1
  90. package/dist/cdn/chunks/{blockTypeIcons-hX_W4dqo.js → blockTypeIcons-A9qFb1cR.js} +2 -2
  91. package/dist/cdn/chunks/{blockTypeIcons-hX_W4dqo.js.map → blockTypeIcons-A9qFb1cR.js.map} +1 -1
  92. package/dist/cdn/chunks/{createCloudRuntime-D75oJ9j-.js → createCloudRuntime-DYDf_-rN.js} +2 -2
  93. package/dist/cdn/chunks/{createCloudRuntime-D75oJ9j-.js.map → createCloudRuntime-DYDf_-rN.js.map} +1 -1
  94. package/dist/cdn/chunks/{icons-C36Ha5VU.js → icons-Dl5bcXmT.js} +7 -7
  95. package/dist/cdn/chunks/{icons-C36Ha5VU.js.map → icons-Dl5bcXmT.js.map} +1 -1
  96. package/dist/cdn/chunks/{src-B_pCqXyM.js → src-BAWlZu4B.js} +3 -3
  97. package/dist/cdn/chunks/{src-B_pCqXyM.js.map → src-BAWlZu4B.js.map} +1 -1
  98. package/dist/cdn/chunks/{src-CoHDh8Ua.js → src-BDUi-9js.js} +15 -15
  99. package/dist/cdn/chunks/{src-CoHDh8Ua.js.map → src-BDUi-9js.js.map} +1 -1
  100. package/dist/cdn/chunks/{useEditorCore-BtEO1qms.js → useEditorCore-D84laTMj.js} +5 -5
  101. package/dist/cdn/chunks/{useEditorCore-BtEO1qms.js.map → useEditorCore-D84laTMj.js.map} +1 -1
  102. package/dist/cdn/editor.js +638 -625
  103. package/dist/cdn/editor.js.map +1 -1
  104. package/dist/{check-DZbmkMQe.js → check-GRcTaHlZ.js} +1 -1
  105. package/dist/{chevron-down-nYScOLeZ.js → chevron-down-NUIAa2Qf.js} +1 -1
  106. package/dist/{chevron-up-CpYpDLnc.js → chevron-up-Bjf2BQtL.js} +1 -1
  107. package/dist/{circle-alert-CuuK6thq.js → circle-alert-FpQ8ykQL.js} +1 -1
  108. package/dist/{clock-DxkrtqOr.js → clock-CaOM1DC-.js} +1 -1
  109. package/dist/{createLucideIcon-L-wQXW_R.js → createLucideIcon-CAmDKr5Z.js} +2 -2
  110. package/dist/{image-up-DouZRGVt.js → image-up-CIGT4cSb.js} +1 -1
  111. package/dist/{info-puX5V6Iq.js → info-9YwKinXj.js} +1 -1
  112. package/dist/{loader-circle-DqTxB7Kr.js → loader-circle-QyURl47g.js} +1 -1
  113. package/dist/{message-circle-BZ7YpB22.js → message-circle-C9pycEzV.js} +1 -1
  114. package/dist/{pencil-DmbRhTJu.js → pencil-BvW86jVn.js} +1 -1
  115. package/dist/{refresh-cw-OK_O-cL0.js → refresh-cw-BDAUomac.js} +1 -1
  116. package/dist/{scan-line-DyaSTsJ5.js → scan-line-B5EvAPSG.js} +1 -1
  117. package/dist/{send-B-wasJJC.js → send-BAUn7DLp.js} +1 -1
  118. package/dist/{shield-check-DUIyRrTo.js → shield-check-CLGywlg0.js} +1 -1
  119. package/dist/{sparkles-DYEMATWC.js → sparkles-X6C0spo6.js} +1 -1
  120. package/dist/templatical-editor.js +131 -118
  121. package/dist/{text-align-start-CzjLeBLe.js → text-align-start-C6FXOoEj.js} +1 -1
  122. package/dist/{trash-2-C0shEPry.js → trash-2-balHkQP4.js} +1 -1
  123. package/dist/{triangle-alert-Fw0ce8oQ.js → triangle-alert-D2JBEr6k.js} +1 -1
  124. package/dist/{upload-D69C2CBx.js → upload-D70OYprI.js} +1 -1
  125. package/dist/{useEditorCore-DoKDh27o.js → useEditorCore-D7Gz7_CW.js} +9 -9
  126. package/dist/{useScrollToBlock-KA65jhQ_.js → useScrollToBlock-DcImB73T.js} +1 -1
  127. package/dist/{x-BjTlFqRv.js → x-DTUPbuwx.js} +1 -1
  128. package/package.json +9 -9
@@ -1 +1 @@
1
- {"version":3,"file":"TitleEditor-D_NJ4Ww8.js","names":[],"sources":["../../../src/components/blocks/TitleEditor.vue","../../../src/components/blocks/TitleEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables\";\nimport { useRichTextEditor } from \"../../composables/useRichTextEditor\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { TitleBlock as TitleBlockType } from \"@templatical/types\";\nimport {\n Bold,\n Braces,\n Italic,\n Link,\n LoaderCircle,\n ScanLine,\n} from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport {\n THEME_STYLES_KEY,\n UI_THEME_KEY,\n MERGE_TAG_PICKER_KEY,\n LOGIC_TAG_PICKER_KEY,\n} from \"../../keys\";\nimport RichTextLinkDialog from \"./RichTextLinkDialog.vue\";\nimport RichTextEditorContent from \"./RichTextEditorContent.vue\";\nimport { withLinkColor } from \"../../utils/linkColorExtension\";\n\nconst props = defineProps<{\n block: TitleBlockType;\n toolbarPosition: { top: number; left: number };\n}>();\n\nconst emit = defineEmits<{\n (e: \"done\"): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst popoverRoot = usePopoverRoot();\n// Hide the floating toolbar while either built-in picker modal is open — see\n// ParagraphToolbar.vue for the same rationale.\nconst picker = inject(MERGE_TAG_PICKER_KEY, null);\nconst logicPicker = inject(LOGIC_TAG_PICKER_KEY, null);\nconst pickerIsOpen = computed(\n () => (picker?.isOpen.value ?? false) || (logicPicker?.isOpen.value ?? false),\n);\n\nconst { t } = useI18n();\n\nconst {\n editor,\n EditorContent,\n isLoading,\n initError,\n retry,\n showLinkDialog,\n linkUrl,\n linkColor,\n linkDialogRef,\n canRequestMergeTag,\n canInsertLogicTag,\n openLinkDialog,\n insertLink,\n removeLink,\n closeLinkDialog,\n handleLinkKeydown,\n handleAddMergeTag,\n handleAddLogicTag,\n} = useRichTextEditor({\n blockId: () => props.block.id,\n blockContent: () => props.block.content,\n onDone: () => emit(\"done\"),\n editorName: \"TitleEditor\",\n async loadExtensions({\n mergeTags,\n syntax,\n triggerChar,\n autocompleteEnabled,\n suggestionEmptyText,\n }) {\n const [\n { Editor: TiptapEditor, EditorContent: EC },\n { default: StarterKit },\n { default: LinkExt },\n { MergeTagNode, MergeTagSuggestion, LogicMergeTagNode, LineBoundaryKeys },\n ] = await Promise.all([\n import(\"@tiptap/vue-3\"),\n import(\"@tiptap/starter-kit\"),\n import(\"@tiptap/extension-link\"),\n import(\"../../extensions\"),\n ]);\n\n return {\n TiptapEditor,\n EC,\n extensions: [\n StarterKit.configure({\n heading: false,\n codeBlock: false,\n blockquote: false,\n horizontalRule: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n strike: false,\n // StarterKit bundles @tiptap/extension-link (openOnClick: true).\n // Disable it so the LinkExt below (openOnClick: false) is the only\n // link extension — otherwise clicking a link while editing opens it.\n link: false,\n }),\n withLinkColor(LinkExt).configure({\n openOnClick: false,\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n }),\n MergeTagNode.configure({ mergeTags, syntax }),\n LogicMergeTagNode.configure({ syntax }),\n LineBoundaryKeys,\n ...(autocompleteEnabled && triggerChar && mergeTags.length > 0\n ? [\n MergeTagSuggestion.configure({\n mergeTags,\n char: triggerChar,\n emptyText: suggestionEmptyText,\n popoverRoot,\n }),\n ]\n : []),\n ],\n };\n },\n});\n</script>\n\n<template>\n <div class=\"tpl-text-editor-wrapper tpl:relative\">\n <Teleport v-if=\"popoverRoot && !pickerIsOpen\" :to=\"popoverRoot\">\n <div\n :data-tpl-theme=\"tplUiTheme\"\n role=\"toolbar\"\n :aria-label=\"t.titleEditor.toolbar\"\n class=\"tpl tpl-text-toolbar tpl:absolute tpl:z-popover tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-[var(--tpl-shadow-lg)]\"\n :style=\"{\n ...themeStyles,\n top: `${toolbarPosition.top}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateY(-100%)',\n }\"\n >\n <template v-if=\"!isLoading && editor\">\n <!-- Bold -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('bold'),\n }\"\n :aria-label=\"t.titleEditor.bold\"\n :title=\"t.titleEditor.bold\"\n @click=\"editor?.chain().focus().toggleBold().run()\"\n >\n <Bold :size=\"16\" :stroke-width=\"2.5\" />\n </button>\n <!-- Italic -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('italic'),\n }\"\n :aria-label=\"t.titleEditor.italic\"\n :title=\"t.titleEditor.italic\"\n @click=\"editor?.chain().focus().toggleItalic().run()\"\n >\n <Italic :size=\"16\" :stroke-width=\"2\" />\n </button>\n <span\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n aria-hidden=\"true\"\n ></span>\n <!-- Link -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('link'),\n }\"\n :aria-label=\"t.titleEditor.addLink\"\n :title=\"t.titleEditor.addLink\"\n @click=\"openLinkDialog\"\n >\n <Link :size=\"16\" :stroke-width=\"2\" />\n </button>\n <!-- Add Merge Tag -->\n <span\n v-if=\"canRequestMergeTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canRequestMergeTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n @click=\"handleAddMergeTag\"\n >\n <ScanLine :size=\"16\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n <!-- Insert Logic -->\n <span\n v-if=\"canInsertLogicTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canInsertLogicTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n data-testid=\"insert-logic-button\"\n @click=\"handleAddLogicTag\"\n >\n <Braces :size=\"16\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n </template>\n <template v-else>\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n <LoaderCircle class=\"tpl-spinner\" :size=\"14\" :stroke-width=\"2\" />\n {{ t.errors.editorLoading }}\n </div>\n </template>\n </div>\n </Teleport>\n\n <RichTextEditorContent\n :editor=\"editor\"\n :editor-content=\"EditorContent\"\n :is-loading=\"isLoading\"\n :init-error=\"initError\"\n @retry=\"retry\"\n />\n\n <RichTextLinkDialog\n :visible=\"showLinkDialog\"\n :is-editing-link=\"editor?.isActive('link') ?? false\"\n v-model:dialog-ref=\"linkDialogRef\"\n v-model:link-url=\"linkUrl\"\n v-model:link-color=\"linkColor\"\n @close=\"closeLinkDialog\"\n @insert=\"insertLink\"\n @remove=\"removeLink\"\n @keydown=\"handleLinkKeydown\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables\";\nimport { useRichTextEditor } from \"../../composables/useRichTextEditor\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { TitleBlock as TitleBlockType } from \"@templatical/types\";\nimport {\n Bold,\n Braces,\n Italic,\n Link,\n LoaderCircle,\n ScanLine,\n} from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport {\n THEME_STYLES_KEY,\n UI_THEME_KEY,\n MERGE_TAG_PICKER_KEY,\n LOGIC_TAG_PICKER_KEY,\n} from \"../../keys\";\nimport RichTextLinkDialog from \"./RichTextLinkDialog.vue\";\nimport RichTextEditorContent from \"./RichTextEditorContent.vue\";\nimport { withLinkColor } from \"../../utils/linkColorExtension\";\n\nconst props = defineProps<{\n block: TitleBlockType;\n toolbarPosition: { top: number; left: number };\n}>();\n\nconst emit = defineEmits<{\n (e: \"done\"): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst popoverRoot = usePopoverRoot();\n// Hide the floating toolbar while either built-in picker modal is open — see\n// ParagraphToolbar.vue for the same rationale.\nconst picker = inject(MERGE_TAG_PICKER_KEY, null);\nconst logicPicker = inject(LOGIC_TAG_PICKER_KEY, null);\nconst pickerIsOpen = computed(\n () => (picker?.isOpen.value ?? false) || (logicPicker?.isOpen.value ?? false),\n);\n\nconst { t } = useI18n();\n\nconst {\n editor,\n EditorContent,\n isLoading,\n initError,\n retry,\n showLinkDialog,\n linkUrl,\n linkColor,\n linkDialogRef,\n canRequestMergeTag,\n canInsertLogicTag,\n openLinkDialog,\n insertLink,\n removeLink,\n closeLinkDialog,\n handleLinkKeydown,\n handleAddMergeTag,\n handleAddLogicTag,\n} = useRichTextEditor({\n blockId: () => props.block.id,\n blockContent: () => props.block.content,\n onDone: () => emit(\"done\"),\n editorName: \"TitleEditor\",\n async loadExtensions({\n mergeTags,\n syntax,\n triggerChar,\n autocompleteEnabled,\n suggestionEmptyText,\n }) {\n const [\n { Editor: TiptapEditor, EditorContent: EC },\n { default: StarterKit },\n { default: LinkExt },\n { MergeTagNode, MergeTagSuggestion, LogicMergeTagNode, LineBoundaryKeys },\n ] = await Promise.all([\n import(\"@tiptap/vue-3\"),\n import(\"@tiptap/starter-kit\"),\n import(\"@tiptap/extension-link\"),\n import(\"../../extensions\"),\n ]);\n\n return {\n TiptapEditor,\n EC,\n extensions: [\n StarterKit.configure({\n heading: false,\n codeBlock: false,\n blockquote: false,\n horizontalRule: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n strike: false,\n // StarterKit bundles @tiptap/extension-link (openOnClick: true).\n // Disable it so the LinkExt below (openOnClick: false) is the only\n // link extension — otherwise clicking a link while editing opens it.\n link: false,\n }),\n withLinkColor(LinkExt).configure({\n openOnClick: false,\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n }),\n MergeTagNode.configure({ mergeTags, syntax }),\n LogicMergeTagNode.configure({ syntax }),\n LineBoundaryKeys,\n ...(autocompleteEnabled && triggerChar && mergeTags.length > 0\n ? [\n MergeTagSuggestion.configure({\n mergeTags,\n char: triggerChar,\n emptyText: suggestionEmptyText,\n popoverRoot,\n }),\n ]\n : []),\n ],\n };\n },\n});\n</script>\n\n<template>\n <div class=\"tpl-text-editor-wrapper tpl:relative\">\n <Teleport v-if=\"popoverRoot && !pickerIsOpen\" :to=\"popoverRoot\">\n <div\n :data-tpl-theme=\"tplUiTheme\"\n role=\"toolbar\"\n :aria-label=\"t.titleEditor.toolbar\"\n class=\"tpl tpl-text-toolbar tpl:absolute tpl:z-popover tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-[var(--tpl-shadow-lg)]\"\n :style=\"{\n ...themeStyles,\n top: `${toolbarPosition.top}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateY(-100%)',\n }\"\n >\n <template v-if=\"!isLoading && editor\">\n <!-- Bold -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('bold'),\n }\"\n :aria-label=\"t.titleEditor.bold\"\n :title=\"t.titleEditor.bold\"\n @click=\"editor?.chain().focus().toggleBold().run()\"\n >\n <Bold :size=\"16\" :stroke-width=\"2.5\" />\n </button>\n <!-- Italic -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('italic'),\n }\"\n :aria-label=\"t.titleEditor.italic\"\n :title=\"t.titleEditor.italic\"\n @click=\"editor?.chain().focus().toggleItalic().run()\"\n >\n <Italic :size=\"16\" :stroke-width=\"2\" />\n </button>\n <span\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n aria-hidden=\"true\"\n ></span>\n <!-- Link -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('link'),\n }\"\n :aria-label=\"t.titleEditor.addLink\"\n :title=\"t.titleEditor.addLink\"\n @click=\"openLinkDialog\"\n >\n <Link :size=\"16\" :stroke-width=\"2\" />\n </button>\n <!-- Add Merge Tag -->\n <span\n v-if=\"canRequestMergeTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canRequestMergeTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n @click=\"handleAddMergeTag\"\n >\n <ScanLine :size=\"16\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n <!-- Insert Logic -->\n <span\n v-if=\"canInsertLogicTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canInsertLogicTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n data-testid=\"insert-logic-button\"\n @click=\"handleAddLogicTag\"\n >\n <Braces :size=\"16\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n </template>\n <template v-else>\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n <LoaderCircle class=\"tpl-spinner\" :size=\"14\" :stroke-width=\"2\" />\n {{ t.errors.editorLoading }}\n </div>\n </template>\n </div>\n </Teleport>\n\n <RichTextEditorContent\n :editor=\"editor\"\n :editor-content=\"EditorContent\"\n :is-loading=\"isLoading\"\n :init-error=\"initError\"\n @retry=\"retry\"\n />\n\n <RichTextLinkDialog\n :visible=\"showLinkDialog\"\n :is-editing-link=\"editor?.isActive('link') ?? false\"\n v-model:dialog-ref=\"linkDialogRef\"\n v-model:link-url=\"linkUrl\"\n v-model:link-color=\"linkColor\"\n @close=\"closeLinkDialog\"\n @insert=\"insertLink\"\n @remove=\"removeLink\"\n @keydown=\"handleLinkKeydown\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"TitleEditor-c2aQCyds.js","names":[],"sources":["../../../src/components/blocks/TitleEditor.vue","../../../src/components/blocks/TitleEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables\";\nimport { useRichTextEditor } from \"../../composables/useRichTextEditor\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { TitleBlock as TitleBlockType } from \"@templatical/types\";\nimport {\n Bold,\n Braces,\n Italic,\n Link,\n LoaderCircle,\n ScanLine,\n} from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport {\n THEME_STYLES_KEY,\n UI_THEME_KEY,\n MERGE_TAG_PICKER_KEY,\n LOGIC_TAG_PICKER_KEY,\n} from \"../../keys\";\nimport RichTextLinkDialog from \"./RichTextLinkDialog.vue\";\nimport RichTextEditorContent from \"./RichTextEditorContent.vue\";\nimport { withLinkColor } from \"../../utils/linkColorExtension\";\n\nconst props = defineProps<{\n block: TitleBlockType;\n toolbarPosition: { top: number; left: number };\n}>();\n\nconst emit = defineEmits<{\n (e: \"done\"): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst popoverRoot = usePopoverRoot();\n// Hide the floating toolbar while either built-in picker modal is open — see\n// ParagraphToolbar.vue for the same rationale.\nconst picker = inject(MERGE_TAG_PICKER_KEY, null);\nconst logicPicker = inject(LOGIC_TAG_PICKER_KEY, null);\nconst pickerIsOpen = computed(\n () => (picker?.isOpen.value ?? false) || (logicPicker?.isOpen.value ?? false),\n);\n\nconst { t } = useI18n();\n\nconst {\n editor,\n EditorContent,\n isLoading,\n initError,\n retry,\n showLinkDialog,\n linkUrl,\n linkColor,\n linkDialogRef,\n canRequestMergeTag,\n canInsertLogicTag,\n openLinkDialog,\n insertLink,\n removeLink,\n closeLinkDialog,\n handleLinkKeydown,\n handleAddMergeTag,\n handleAddLogicTag,\n} = useRichTextEditor({\n blockId: () => props.block.id,\n blockContent: () => props.block.content,\n onDone: () => emit(\"done\"),\n editorName: \"TitleEditor\",\n async loadExtensions({\n mergeTags,\n syntax,\n triggerChar,\n autocompleteEnabled,\n suggestionEmptyText,\n }) {\n const [\n { Editor: TiptapEditor, EditorContent: EC },\n { default: StarterKit },\n { default: LinkExt },\n { MergeTagNode, MergeTagSuggestion, LogicMergeTagNode, LineBoundaryKeys },\n ] = await Promise.all([\n import(\"@tiptap/vue-3\"),\n import(\"@tiptap/starter-kit\"),\n import(\"@tiptap/extension-link\"),\n import(\"../../extensions\"),\n ]);\n\n return {\n TiptapEditor,\n EC,\n extensions: [\n StarterKit.configure({\n heading: false,\n codeBlock: false,\n blockquote: false,\n horizontalRule: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n strike: false,\n // StarterKit bundles @tiptap/extension-link (openOnClick: true).\n // Disable it so the LinkExt below (openOnClick: false) is the only\n // link extension — otherwise clicking a link while editing opens it.\n link: false,\n }),\n withLinkColor(LinkExt).configure({\n openOnClick: false,\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n }),\n MergeTagNode.configure({ mergeTags, syntax }),\n LogicMergeTagNode.configure({ syntax }),\n LineBoundaryKeys,\n ...(autocompleteEnabled && triggerChar && mergeTags.length > 0\n ? [\n MergeTagSuggestion.configure({\n mergeTags,\n char: triggerChar,\n emptyText: suggestionEmptyText,\n popoverRoot,\n }),\n ]\n : []),\n ],\n };\n },\n});\n</script>\n\n<template>\n <div class=\"tpl-text-editor-wrapper tpl:relative\">\n <Teleport v-if=\"popoverRoot && !pickerIsOpen\" :to=\"popoverRoot\">\n <div\n :data-tpl-theme=\"tplUiTheme\"\n role=\"toolbar\"\n :aria-label=\"t.titleEditor.toolbar\"\n class=\"tpl tpl-text-toolbar tpl:absolute tpl:z-popover tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-[var(--tpl-shadow-lg)]\"\n :style=\"{\n ...themeStyles,\n top: `${toolbarPosition.top}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateY(-100%)',\n }\"\n >\n <template v-if=\"!isLoading && editor\">\n <!-- Bold -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('bold'),\n }\"\n :aria-label=\"t.titleEditor.bold\"\n :title=\"t.titleEditor.bold\"\n @click=\"editor?.chain().focus().toggleBold().run()\"\n >\n <Bold :size=\"16\" :stroke-width=\"2.5\" />\n </button>\n <!-- Italic -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('italic'),\n }\"\n :aria-label=\"t.titleEditor.italic\"\n :title=\"t.titleEditor.italic\"\n @click=\"editor?.chain().focus().toggleItalic().run()\"\n >\n <Italic :size=\"16\" :stroke-width=\"2\" />\n </button>\n <span\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n aria-hidden=\"true\"\n ></span>\n <!-- Link -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('link'),\n }\"\n :aria-label=\"t.titleEditor.addLink\"\n :title=\"t.titleEditor.addLink\"\n @click=\"openLinkDialog\"\n >\n <Link :size=\"16\" :stroke-width=\"2\" />\n </button>\n <!-- Add Merge Tag -->\n <span\n v-if=\"canRequestMergeTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canRequestMergeTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n @click=\"handleAddMergeTag\"\n >\n <ScanLine :size=\"16\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n <!-- Insert Logic -->\n <span\n v-if=\"canInsertLogicTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canInsertLogicTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n data-testid=\"insert-logic-button\"\n @click=\"handleAddLogicTag\"\n >\n <Braces :size=\"16\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n </template>\n <template v-else>\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n <LoaderCircle class=\"tpl-spinner\" :size=\"14\" :stroke-width=\"2\" />\n {{ t.errors.editorLoading }}\n </div>\n </template>\n </div>\n </Teleport>\n\n <RichTextEditorContent\n :editor=\"editor\"\n :editor-content=\"EditorContent\"\n :is-loading=\"isLoading\"\n :init-error=\"initError\"\n @retry=\"retry\"\n />\n\n <RichTextLinkDialog\n :visible=\"showLinkDialog\"\n :is-editing-link=\"editor?.isActive('link') ?? false\"\n v-model:dialog-ref=\"linkDialogRef\"\n v-model:link-url=\"linkUrl\"\n v-model:link-color=\"linkColor\"\n @close=\"closeLinkDialog\"\n @insert=\"insertLink\"\n @remove=\"removeLink\"\n @keydown=\"handleLinkKeydown\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../../composables\";\nimport { useRichTextEditor } from \"../../composables/useRichTextEditor\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { TitleBlock as TitleBlockType } from \"@templatical/types\";\nimport {\n Bold,\n Braces,\n Italic,\n Link,\n LoaderCircle,\n ScanLine,\n} from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport {\n THEME_STYLES_KEY,\n UI_THEME_KEY,\n MERGE_TAG_PICKER_KEY,\n LOGIC_TAG_PICKER_KEY,\n} from \"../../keys\";\nimport RichTextLinkDialog from \"./RichTextLinkDialog.vue\";\nimport RichTextEditorContent from \"./RichTextEditorContent.vue\";\nimport { withLinkColor } from \"../../utils/linkColorExtension\";\n\nconst props = defineProps<{\n block: TitleBlockType;\n toolbarPosition: { top: number; left: number };\n}>();\n\nconst emit = defineEmits<{\n (e: \"done\"): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst popoverRoot = usePopoverRoot();\n// Hide the floating toolbar while either built-in picker modal is open — see\n// ParagraphToolbar.vue for the same rationale.\nconst picker = inject(MERGE_TAG_PICKER_KEY, null);\nconst logicPicker = inject(LOGIC_TAG_PICKER_KEY, null);\nconst pickerIsOpen = computed(\n () => (picker?.isOpen.value ?? false) || (logicPicker?.isOpen.value ?? false),\n);\n\nconst { t } = useI18n();\n\nconst {\n editor,\n EditorContent,\n isLoading,\n initError,\n retry,\n showLinkDialog,\n linkUrl,\n linkColor,\n linkDialogRef,\n canRequestMergeTag,\n canInsertLogicTag,\n openLinkDialog,\n insertLink,\n removeLink,\n closeLinkDialog,\n handleLinkKeydown,\n handleAddMergeTag,\n handleAddLogicTag,\n} = useRichTextEditor({\n blockId: () => props.block.id,\n blockContent: () => props.block.content,\n onDone: () => emit(\"done\"),\n editorName: \"TitleEditor\",\n async loadExtensions({\n mergeTags,\n syntax,\n triggerChar,\n autocompleteEnabled,\n suggestionEmptyText,\n }) {\n const [\n { Editor: TiptapEditor, EditorContent: EC },\n { default: StarterKit },\n { default: LinkExt },\n { MergeTagNode, MergeTagSuggestion, LogicMergeTagNode, LineBoundaryKeys },\n ] = await Promise.all([\n import(\"@tiptap/vue-3\"),\n import(\"@tiptap/starter-kit\"),\n import(\"@tiptap/extension-link\"),\n import(\"../../extensions\"),\n ]);\n\n return {\n TiptapEditor,\n EC,\n extensions: [\n StarterKit.configure({\n heading: false,\n codeBlock: false,\n blockquote: false,\n horizontalRule: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n strike: false,\n // StarterKit bundles @tiptap/extension-link (openOnClick: true).\n // Disable it so the LinkExt below (openOnClick: false) is the only\n // link extension — otherwise clicking a link while editing opens it.\n link: false,\n }),\n withLinkColor(LinkExt).configure({\n openOnClick: false,\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n }),\n MergeTagNode.configure({ mergeTags, syntax }),\n LogicMergeTagNode.configure({ syntax }),\n LineBoundaryKeys,\n ...(autocompleteEnabled && triggerChar && mergeTags.length > 0\n ? [\n MergeTagSuggestion.configure({\n mergeTags,\n char: triggerChar,\n emptyText: suggestionEmptyText,\n popoverRoot,\n }),\n ]\n : []),\n ],\n };\n },\n});\n</script>\n\n<template>\n <div class=\"tpl-text-editor-wrapper tpl:relative\">\n <Teleport v-if=\"popoverRoot && !pickerIsOpen\" :to=\"popoverRoot\">\n <div\n :data-tpl-theme=\"tplUiTheme\"\n role=\"toolbar\"\n :aria-label=\"t.titleEditor.toolbar\"\n class=\"tpl tpl-text-toolbar tpl:absolute tpl:z-popover tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-[var(--tpl-shadow-lg)]\"\n :style=\"{\n ...themeStyles,\n top: `${toolbarPosition.top}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateY(-100%)',\n }\"\n >\n <template v-if=\"!isLoading && editor\">\n <!-- Bold -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('bold'),\n }\"\n :aria-label=\"t.titleEditor.bold\"\n :title=\"t.titleEditor.bold\"\n @click=\"editor?.chain().focus().toggleBold().run()\"\n >\n <Bold :size=\"16\" :stroke-width=\"2.5\" />\n </button>\n <!-- Italic -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('italic'),\n }\"\n :aria-label=\"t.titleEditor.italic\"\n :title=\"t.titleEditor.italic\"\n @click=\"editor?.chain().focus().toggleItalic().run()\"\n >\n <Italic :size=\"16\" :stroke-width=\"2\" />\n </button>\n <span\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n aria-hidden=\"true\"\n ></span>\n <!-- Link -->\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': editor?.isActive('link'),\n }\"\n :aria-label=\"t.titleEditor.addLink\"\n :title=\"t.titleEditor.addLink\"\n @click=\"openLinkDialog\"\n >\n <Link :size=\"16\" :stroke-width=\"2\" />\n </button>\n <!-- Add Merge Tag -->\n <span\n v-if=\"canRequestMergeTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canRequestMergeTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n @click=\"handleAddMergeTag\"\n >\n <ScanLine :size=\"16\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n <!-- Insert Logic -->\n <span\n v-if=\"canInsertLogicTag\"\n class=\"tpl:mx-1.5 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n ></span>\n <button\n v-if=\"canInsertLogicTag\"\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n data-testid=\"insert-logic-button\"\n @click=\"handleAddLogicTag\"\n >\n <Braces :size=\"16\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n </template>\n <template v-else>\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n <LoaderCircle class=\"tpl-spinner\" :size=\"14\" :stroke-width=\"2\" />\n {{ t.errors.editorLoading }}\n </div>\n </template>\n </div>\n </Teleport>\n\n <RichTextEditorContent\n :editor=\"editor\"\n :editor-content=\"EditorContent\"\n :is-loading=\"isLoading\"\n :init-error=\"initError\"\n @retry=\"retry\"\n />\n\n <RichTextLinkDialog\n :visible=\"showLinkDialog\"\n :is-editing-link=\"editor?.isActive('link') ?? false\"\n v-model:dialog-ref=\"linkDialogRef\"\n v-model:link-url=\"linkUrl\"\n v-model:link-color=\"linkColor\"\n @close=\"closeLinkDialog\"\n @insert=\"insertLink\"\n @remove=\"removeLink\"\n @keydown=\"handleLinkKeydown\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;EAwBA,IAAM,IAAQ,GAKR,IAAO,GAIP,IAAc,EAAO,IAAkB,IAAI,GAC3C,IAAa,EAAO,GAAc,IAAI,GACtC,IAAc,EAAe,GAG7B,IAAS,EAAO,GAAsB,IAAI,GAC1C,IAAc,EAAO,GAAsB,IAAI,GAC/C,KAAe,SACZ,GAAQ,OAAO,SAAS,QAAW,GAAa,OAAO,SAAS,GACzE,GAEM,EAAE,SAAM,EAAQ,GAEhB,EACJ,WACA,kBACA,cACA,eACA,WACA,oBACA,YACA,cACA,kBACA,uBACA,sBACA,mBACA,gBACA,gBACA,qBACA,uBACA,sBACA,yBACE,GAAkB;GACpB,eAAe,EAAM,MAAM;GAC3B,oBAAoB,EAAM,MAAM;GAChC,cAAc,EAAK,MAAM;GACzB,YAAY;GACZ,MAAM,eAAe,EACnB,cACA,WACA,gBACA,wBACA,0BACC;IACD,IAAM,CACJ,EAAE,QAAQ,GAAc,eAAe,KACvC,EAAE,SAAS,KACX,EAAE,SAAS,KACX,EAAE,iBAAc,uBAAoB,sBAAmB,yBACrD,MAAM,QAAQ,IAAI;KACpB,OAAO,uBAAA,CAAA,MAAA,MAAA,EAAA,CAAA;KACP,OAAO,uBAAA,CAAA,MAAA,MAAA,EAAA,CAAA;KACP,OAAO,uBAAA,CAAA,MAAA,MAAA,EAAA,CAAA;KACP,OAAO;IACT,CAAC;IAED,OAAO;KACL;KACA;KACA,YAAY;MACV,EAAW,UAAU;OACnB,SAAS;OACT,WAAW;OACX,YAAY;OACZ,gBAAgB;OAChB,YAAY;OACZ,aAAa;OACb,UAAU;OACV,QAAQ;OAIR,MAAM;MACR,CAAC;MACD,GAAc,CAAO,CAAC,CAAC,UAAU;OAC/B,aAAa;OACb,gBAAgB;QACd,QAAQ;QACR,KAAK;OACP;MACF,CAAC;MACD,EAAa,UAAU;OAAE;OAAW;MAAO,CAAC;MAC5C,EAAkB,UAAU,EAAE,UAAO,CAAC;MACtC;MACA,GAAI,KAAuB,KAAe,EAAU,SAAS,IACzD,CACE,EAAmB,UAAU;OAC3B;OACA,MAAM;OACN,WAAW;OACX;MACF,CAAC,CACH,IACA,CAAC;KACP;IACF;GACF;EACF,CAAC;oBAIC,EAAA,GAAA,EA0HM,OA1HN,GA0HM;GAzHY,EAAA,CAAA,KAAW,CAAK,GAAA,SAAhC,EAAA,GAAA,EAoGW,GAAA;;IApGoC,IAAI,EAAA,CAAA;GACjD,GAAA,CAAA,EAkGM,OAAA;IAjGH,kBAAgB,EAAA,CAAA;IACjB,MAAK;IACJ,cAAY,EAAA,CAAA,CAAC,CAAC,YAAY;IAC3B,OAAM;IACL,OAAK,EAAA;KAAiB,GAAA,EAAA,CAAA;KAA+B,KAAA,GAAA,EAAA,gBAAgB,IAAG;KAAyB,MAAA,GAAA,EAAA,gBAAgB,KAAI;;;GAOrG,GAAA,CAAA,CAAA,EAAA,CAAA,KAAa,EAAA,CAAA,KAA9B,EAAA,GAAA,EA6EW,GAAA,EAAA,KAAA,EAAA,GAAA;IA3ET,EAWS,UAAA;KAVP,MAAK;KACL,OAAK,EAAA,CAAC,wBAAsB,EAC4B,gCAAA,EAAA,CAAA,CAAM,EAAE,SAAQ,MAAA,EAAA,CAAA,CAAA;KAGvE,cAAY,EAAA,CAAA,CAAC,CAAC,YAAY;KAC1B,OAAO,EAAA,CAAA,CAAC,CAAC,YAAY;KACrB,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAM,EAAE,MAAK,CAAA,CAAG,MAAK,CAAA,CAAG,WAAU,CAAA,CAAG,IAAG;IAEhD,GAAA,CAAA,EAAuC,EAAA,EAAA,GAAA;KAAhC,MAAM;KAAK,gBAAc;;IAGlC,EAWS,UAAA;KAVP,MAAK;KACL,OAAK,EAAA,CAAC,wBAAsB,EAC4B,gCAAA,EAAA,CAAA,CAAM,EAAE,SAAQ,QAAA,EAAA,CAAA,CAAA;KAGvE,cAAY,EAAA,CAAA,CAAC,CAAC,YAAY;KAC1B,OAAO,EAAA,CAAA,CAAC,CAAC,YAAY;KACrB,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAM,EAAE,MAAK,CAAA,CAAG,MAAK,CAAA,CAAG,aAAY,CAAA,CAAG,IAAG;IAElD,GAAA,CAAA,EAAuC,EAAA,EAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;;IAEpC,AAAA,EAAA,OAAA,EAGQ,QAAA;KAFN,OAAM;KACN,eAAY;;IAGd,EAWS,UAAA;KAVP,MAAK;KACL,OAAK,EAAA,CAAC,wBAAsB,EAC4B,gCAAA,EAAA,CAAA,CAAM,EAAE,SAAQ,MAAA,EAAA,CAAA,CAAA;KAGvE,cAAY,EAAA,CAAA,CAAC,CAAC,YAAY;KAC1B,OAAO,EAAA,CAAA,CAAC,CAAC,YAAY;KACrB,SAAK,AAAA,EAAA,QAAE,GAAA,MAAA,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;IAER,GAAA,CAAA,EAAqC,EAAA,EAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;;IAI1B,EAAA,CAAA,KADR,EAAA,GAAA,EAGQ,QAHR,CAGQ,KAAA,EAAA,IAAA,EAAA;IAEA,EAAA,CAAA,KADR,EAAA,GAAA,EAUS,UAAA;;KARP,MAAK;KACL,OAAM;KACL,cAAY,EAAA,CAAA,CAAC,CAAC,SAAS;KACvB,OAAO,EAAA,CAAA,CAAC,CAAC,SAAS;KAClB,SAAK,AAAA,EAAA,QAAE,GAAA,MAAA,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;IAER,GAAA,CAAA,EAAyC,EAAA,EAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;IAAK,CAAA,GAAA,EAAA,MACzC,EAAG,EAAA,CAAA,CAAC,CAAC,SAAS,WAAW,GAAA,CAAA,CAAA,GAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;IAInB,EAAA,CAAA,KADR,EAAA,GAAA,EAGQ,QAHR,CAGQ,KAAA,EAAA,IAAA,EAAA;IAEA,EAAA,CAAA,KADR,EAAA,GAAA,EAWS,UAAA;;KATP,MAAK;KACL,OAAM;KACL,cAAY,EAAA,CAAA,CAAC,CAAC,SAAS;KACvB,OAAO,EAAA,CAAA,CAAC,CAAC,SAAS;KACnB,eAAY;KACX,SAAK,AAAA,EAAA,QAAE,GAAA,MAAA,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;IAER,GAAA,CAAA,EAAuC,EAAA,EAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;IAAK,CAAA,GAAA,EAAA,MACvC,EAAG,EAAA,CAAA,CAAC,CAAC,SAAS,WAAW,GAAA,CAAA,CAAA,GAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;GAI3B,GAAA,EAAA,MAAA,EAAA,GAAA,EAKM,OALN,GAKM,CAFJ,EAAiE,EAAA,EAAA,GAAA;IAAnD,OAAM;IAAe,MAAM;IAAK,gBAAc;GAAK,CAAA,GAAA,EAAA,MACjE,EAAG,EAAA,CAAA,CAAC,CAAC,OAAO,aAAa,GAAA,CAAA,CAAA,CAAA,EAAA,GAAA,IAAA,CAAA,CAAA,GAAA,GAAA,CAAA,IAAA,CAAA,KAAA,EAAA,IAAA,EAAA;GAMjC,EAME,GAAA;IALC,QAAQ,EAAA,CAAA;IACR,kBAAgB,EAAA,CAAA;IAChB,cAAY,EAAA,CAAA;IACZ,cAAY,EAAA,EAAA;IACZ,SAAO,EAAA,EAAA;;;;;;;;GAGV,EAUE,GAAA;IATC,SAAS,EAAA,EAAA;IACT,mBAAiB,EAAA,CAAA,CAAM,EAAE,SAAQ,MAAA,KAAA;IAC1B,cAAY,EAAA,CAAA;IAAA,sBAAA,AAAA,EAAA,QAAA,MAAA,EAAA,CAAA,IAAA,EAAa,QAAA,IAAA;IACzB,YAAU,EAAA,CAAA;IAAA,oBAAA,AAAA,EAAA,QAAA,MAAA,EAAA,CAAA,IAAA,EAAO,QAAA,IAAA;IACjB,cAAY,EAAA,CAAA;IAAA,sBAAA,AAAA,EAAA,QAAA,MAAA,EAAA,CAAA,IAAA,EAAS,QAAA,IAAA;IAC5B,SAAO,EAAA,EAAA;IACP,UAAQ,EAAA,EAAA;IACR,UAAQ,EAAA,EAAA;IACR,WAAS,EAAA,EAAA"}
@@ -1,5 +1,5 @@
1
1
  import { E as e, H as t, I as n, N as r, Q as i, S as a, at as o, b as s, d as c, f as l, g as u, h as d, l as f, lt as p, m, n as h, p as g } from "./draggable-BfpsXFg7.js";
2
- import { E as _ } from "./useEditorCore-BtEO1qms.js";
2
+ import { E as _ } from "./useEditorCore-D84laTMj.js";
3
3
  import { B as v, H as y } from "./keys-oJdkdtPn.js";
4
4
  import { n as b } from "./usePopoverPosition-C1N2kaiZ.js";
5
5
  //#region src/components/TplModal.vue?vue&type=script&setup=true&lang.ts
@@ -47,4 +47,4 @@ var x = ["data-tpl-theme"], S = /* @__PURE__ */ a({
47
47
  //#endregion
48
48
  export { S as t };
49
49
 
50
- //# sourceMappingURL=TplModal-C51W8LTn.js.map
50
+ //# sourceMappingURL=TplModal-DSTVZKuI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TplModal-C51W8LTn.js","names":[],"sources":["../../../src/components/TplModal.vue","../../../src/components/TplModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useFocusTrap } from \"../composables\";\nimport { usePopoverRoot } from \"../composables/usePopoverRoot\";\nimport { THEME_STYLES_KEY, UI_THEME_KEY } from \"../keys\";\nimport { computed, inject, ref } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst dialogRef = ref<HTMLElement | null>(null);\nconst isVisible = computed(() => props.visible);\nuseFocusTrap(dialogRef, isVisible);\n\nconst tplUiTheme = inject(UI_THEME_KEY);\n\n// The backdrop below carries the bare `tpl` class, which re-declares every\n// `--tpl-*` token from the base `.tpl` rule. A custom property declared on an\n// element beats one inherited from an ancestor, so that re-declaration shadows\n// the consumer's `theme` config — which lives as inline styles on the editor\n// root — for this whole teleported subtree. Re-applying `themeStyles` here is\n// what restores it, and doing it on the backdrop covers every dialog rendered\n// through this wrapper rather than each one remembering to. `data-tpl-theme`\n// does the same job for the dark token block. See the invariant in\n// `tests/theme-token-scope.test.ts` (issue #487).\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst popoverRoot = usePopoverRoot();\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Escape\") {\n emit(\"close\");\n }\n emit(\"keydown\", event);\n}\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot\" :to=\"popoverRoot\">\n <Transition\n enter-active-class=\"tpl:transition\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <div\n v-if=\"visible\"\n :data-tpl-theme=\"tplUiTheme\"\n class=\"tpl tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center\"\n style=\"\n background-color: var(--tpl-overlay);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n :style=\"themeStyles\"\n @click.self=\"emit('close')\"\n @keydown=\"handleKeydown\"\n >\n <div ref=\"dialogRef\">\n <slot />\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { useFocusTrap } from \"../composables\";\nimport { usePopoverRoot } from \"../composables/usePopoverRoot\";\nimport { THEME_STYLES_KEY, UI_THEME_KEY } from \"../keys\";\nimport { computed, inject, ref } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst dialogRef = ref<HTMLElement | null>(null);\nconst isVisible = computed(() => props.visible);\nuseFocusTrap(dialogRef, isVisible);\n\nconst tplUiTheme = inject(UI_THEME_KEY);\n\n// The backdrop below carries the bare `tpl` class, which re-declares every\n// `--tpl-*` token from the base `.tpl` rule. A custom property declared on an\n// element beats one inherited from an ancestor, so that re-declaration shadows\n// the consumer's `theme` config — which lives as inline styles on the editor\n// root — for this whole teleported subtree. Re-applying `themeStyles` here is\n// what restores it, and doing it on the backdrop covers every dialog rendered\n// through this wrapper rather than each one remembering to. `data-tpl-theme`\n// does the same job for the dark token block. See the invariant in\n// `tests/theme-token-scope.test.ts` (issue #487).\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst popoverRoot = usePopoverRoot();\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Escape\") {\n emit(\"close\");\n }\n emit(\"keydown\", event);\n}\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot\" :to=\"popoverRoot\">\n <Transition\n enter-active-class=\"tpl:transition\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <div\n v-if=\"visible\"\n :data-tpl-theme=\"tplUiTheme\"\n class=\"tpl tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center\"\n style=\"\n background-color: var(--tpl-overlay);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n :style=\"themeStyles\"\n @click.self=\"emit('close')\"\n @keydown=\"handleKeydown\"\n >\n <div ref=\"dialogRef\">\n <slot />\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":";;;;;;;;;;EAMA,IAAM,IAAQ,GAIR,IAAO,GAKP,IAAY,EAAwB,IAAI,GACxC,IAAY,QAAe,EAAM,OAAO;EAC9C,EAAa,GAAW,CAAS;EAEjC,IAAM,IAAa,EAAO,CAAY,GAWhC,IAAc,EAAO,GAAkB,IAAI,GAC3C,IAAc,EAAe;EAEnC,SAAS,EAAc,GAA4B;GAIjD,AAHI,EAAM,QAAQ,YAChB,EAAK,OAAO,GAEd,EAAK,WAAW,CAAK;EACvB;mBAIkB,EAAA,CAAA,KAAhB,EAAA,GAAA,EA2BW,GAAA;;GA3BmB,IAAI,EAAA,CAAA;EAChC,GAAA,CAAA,EAyBa,GAAA;GAxBX,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;GACf,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;;GAEf,SAAA,QAgBM,CAfE,EAAA,WADR,EAAA,GAAA,EAgBM,OAAA;;IAdH,kBAAgB,EAAA,CAAA;IACjB,OAAM;IACN,OAIC,EAAA,CAJD;KAAA,oBAAA;KAAA,mBAAA;KAAA,2BAAA;IAAA,GAKQ,EAAA,CAAA,CAAW,CAAA;IAClB,SAAK,AAAA,EAAA,OAAA,GAAA,MAAO,EAAI,OAAA,GAAA,CAAA,MAAA,CAAA;IAChB,WAAS;GAEV,GAAA,CAAA,EAEM,OAAA;IAFG,SAAA;IAAJ,KAAI;GACP,GAAA,CAAA,EAAQ,EAAA,QAAA,SAAA,CAAA,GAAA,GAAA,CAAA,GAAA,IAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"TplModal-DSTVZKuI.js","names":[],"sources":["../../../src/components/TplModal.vue","../../../src/components/TplModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useFocusTrap } from \"../composables\";\nimport { usePopoverRoot } from \"../composables/usePopoverRoot\";\nimport { THEME_STYLES_KEY, UI_THEME_KEY } from \"../keys\";\nimport { computed, inject, ref } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst dialogRef = ref<HTMLElement | null>(null);\nconst isVisible = computed(() => props.visible);\nuseFocusTrap(dialogRef, isVisible);\n\nconst tplUiTheme = inject(UI_THEME_KEY);\n\n// The backdrop below carries the bare `tpl` class, which re-declares every\n// `--tpl-*` token from the base `.tpl` rule. A custom property declared on an\n// element beats one inherited from an ancestor, so that re-declaration shadows\n// the consumer's `theme` config — which lives as inline styles on the editor\n// root — for this whole teleported subtree. Re-applying `themeStyles` here is\n// what restores it, and doing it on the backdrop covers every dialog rendered\n// through this wrapper rather than each one remembering to. `data-tpl-theme`\n// does the same job for the dark token block. See the invariant in\n// `tests/theme-token-scope.test.ts` (issue #487).\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst popoverRoot = usePopoverRoot();\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Escape\") {\n emit(\"close\");\n }\n emit(\"keydown\", event);\n}\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot\" :to=\"popoverRoot\">\n <Transition\n enter-active-class=\"tpl:transition\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <div\n v-if=\"visible\"\n :data-tpl-theme=\"tplUiTheme\"\n class=\"tpl tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center\"\n style=\"\n background-color: var(--tpl-overlay);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n :style=\"themeStyles\"\n @click.self=\"emit('close')\"\n @keydown=\"handleKeydown\"\n >\n <div ref=\"dialogRef\">\n <slot />\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { useFocusTrap } from \"../composables\";\nimport { usePopoverRoot } from \"../composables/usePopoverRoot\";\nimport { THEME_STYLES_KEY, UI_THEME_KEY } from \"../keys\";\nimport { computed, inject, ref } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst dialogRef = ref<HTMLElement | null>(null);\nconst isVisible = computed(() => props.visible);\nuseFocusTrap(dialogRef, isVisible);\n\nconst tplUiTheme = inject(UI_THEME_KEY);\n\n// The backdrop below carries the bare `tpl` class, which re-declares every\n// `--tpl-*` token from the base `.tpl` rule. A custom property declared on an\n// element beats one inherited from an ancestor, so that re-declaration shadows\n// the consumer's `theme` config — which lives as inline styles on the editor\n// root — for this whole teleported subtree. Re-applying `themeStyles` here is\n// what restores it, and doing it on the backdrop covers every dialog rendered\n// through this wrapper rather than each one remembering to. `data-tpl-theme`\n// does the same job for the dark token block. See the invariant in\n// `tests/theme-token-scope.test.ts` (issue #487).\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst popoverRoot = usePopoverRoot();\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Escape\") {\n emit(\"close\");\n }\n emit(\"keydown\", event);\n}\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot\" :to=\"popoverRoot\">\n <Transition\n enter-active-class=\"tpl:transition\"\n enter-from-class=\"tpl:opacity-0\"\n enter-to-class=\"tpl:opacity-100\"\n leave-active-class=\"tpl:transition tpl:duration-100\"\n leave-from-class=\"tpl:opacity-100\"\n leave-to-class=\"tpl:opacity-0\"\n >\n <div\n v-if=\"visible\"\n :data-tpl-theme=\"tplUiTheme\"\n class=\"tpl tpl:fixed tpl:inset-0 tpl:z-modal tpl:flex tpl:items-center tpl:justify-center\"\n style=\"\n background-color: var(--tpl-overlay);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n \"\n :style=\"themeStyles\"\n @click.self=\"emit('close')\"\n @keydown=\"handleKeydown\"\n >\n <div ref=\"dialogRef\">\n <slot />\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":";;;;;;;;;;EAMA,IAAM,IAAQ,GAIR,IAAO,GAKP,IAAY,EAAwB,IAAI,GACxC,IAAY,QAAe,EAAM,OAAO;EAC9C,EAAa,GAAW,CAAS;EAEjC,IAAM,IAAa,EAAO,CAAY,GAWhC,IAAc,EAAO,GAAkB,IAAI,GAC3C,IAAc,EAAe;EAEnC,SAAS,EAAc,GAA4B;GAIjD,AAHI,EAAM,QAAQ,YAChB,EAAK,OAAO,GAEd,EAAK,WAAW,CAAK;EACvB;mBAIkB,EAAA,CAAA,KAAhB,EAAA,GAAA,EA2BW,GAAA;;GA3BmB,IAAI,EAAA,CAAA;EAChC,GAAA,CAAA,EAyBa,GAAA;GAxBX,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;GACf,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;;GAEf,SAAA,QAgBM,CAfE,EAAA,WADR,EAAA,GAAA,EAgBM,OAAA;;IAdH,kBAAgB,EAAA,CAAA;IACjB,OAAM;IACN,OAIC,EAAA,CAJD;KAAA,oBAAA;KAAA,mBAAA;KAAA,2BAAA;IAAA,GAKQ,EAAA,CAAA,CAAW,CAAA;IAClB,SAAK,AAAA,EAAA,OAAA,GAAA,MAAO,EAAI,OAAA,GAAA,CAAA,MAAA,CAAA;IAChB,WAAS;GAEV,GAAA,CAAA,EAEM,OAAA;IAFG,SAAA;IAAJ,KAAI;GACP,GAAA,CAAA,EAAQ,EAAA,QAAA,SAAA,CAAA,GAAA,GAAA,CAAA,GAAA,IAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { F as e, H as t, N as n, Q as r, S as i, at as a, b as o, ct as s, f as c, g as l, h as u, l as d, n as f, p, u as m, ut as h, y as g } from "./draggable-BfpsXFg7.js";
2
2
  import { t as _ } from "./dist-CM8TB0VD.js";
3
3
  import { t as v } from "./useI18n-4sUbTM3Y.js";
4
- import { Ft as y, It as b, Pt as x, it as S, kt as C } from "./icons-C36Ha5VU.js";
4
+ import { Ft as y, It as b, Pt as x, it as S, kt as C } from "./icons-Dl5bcXmT.js";
5
5
  import { t as w } from "./formatRelativeTime-CtUU-QZ8.js";
6
6
  //#region src/components/VersionHistoryMenu.vue?vue&type=script&setup=true&lang.ts
7
7
  var T = [
@@ -89,7 +89,7 @@ var T = [
89
89
  title: a(V).versionHistory.olderVersion,
90
90
  "aria-label": a(V).versionHistory.olderVersion,
91
91
  onClick: d(Y, ["stop"])
92
- }, [o(a(y), {
92
+ }, [o(a(x), {
93
93
  size: 14,
94
94
  "stroke-width": 2
95
95
  })], 8, T),
@@ -135,7 +135,7 @@ var T = [
135
135
  title: a(V).versionHistory.newerVersion,
136
136
  "aria-label": a(V).versionHistory.newerVersion,
137
137
  onClick: d(J, ["stop"])
138
- }, [o(a(x), {
138
+ }, [o(a(y), {
139
139
  size: 14,
140
140
  "stroke-width": 2
141
141
  })], 8, L)
@@ -145,4 +145,4 @@ var T = [
145
145
  //#endregion
146
146
  export { R as default };
147
147
 
148
- //# sourceMappingURL=VersionHistoryMenu-Cv23A0uu.js.map
148
+ //# sourceMappingURL=VersionHistoryMenu-BNYSIjVj.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VersionHistoryMenu-Cv23A0uu.js","names":[],"sources":["../../../src/components/VersionHistoryMenu.vue","../../../src/components/VersionHistoryMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * The header's version-history control: step older / newer through the list, or\n * open the dropdown and jump straight to one.\n *\n * Shared by both editors — it was `cloud/components/SnapshotHistory.vue` and\n * spoke Cloud's wire shape (`created_at`, `is_autosave`) directly. It now reads\n * the `TemplateVersion` contract, so any provider drives it.\n */\nimport { computed, ref } from \"vue\";\nimport { onClickOutside } from \"@vueuse/core\";\nimport {\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n Clock,\n LoaderCircle,\n} from \"@lucide/vue\";\nimport type { TemplateVersion } from \"@templatical/types\";\nimport { useI18n } from \"../composables/useI18n\";\nimport { formatRelativeTime } from \"../utils/formatRelativeTime\";\n\nconst props = defineProps<{\n versions: TemplateVersion[];\n isLoading: boolean;\n isRestoring: boolean;\n /** Which version is on the canvas, or `null` while editing normally. */\n previewingId: string | null;\n}>();\n\nconst emit = defineEmits<{\n (e: \"open\"): void;\n (e: \"navigate\", version: TemplateVersion): void;\n}>();\n\nconst { t, format } = useI18n();\n\nconst isOpen = ref(false);\nconst dropdownRef = ref<HTMLElement | null>(null);\n\n/**\n * Position in the list (0 = newest), derived from what is actually previewed\n * rather than tracked locally. A local index went stale the moment the user\n * cancelled a preview — the arrows then stepped from wherever they had left off\n * instead of from the top.\n */\nconst currentIndex = computed(() =>\n props.previewingId === null\n ? -1\n : props.versions.findIndex((v) => v.id === props.previewingId),\n);\n\nconst canGoNewer = computed(\n () => currentIndex.value > 0 && !props.isRestoring && !props.isLoading,\n);\n\nconst canGoOlder = computed(\n () =>\n currentIndex.value < props.versions.length - 1 &&\n props.versions.length > 0 &&\n !props.isRestoring &&\n !props.isLoading,\n);\n\nfunction goNewer(): void {\n if (!canGoNewer.value) return;\n emit(\"navigate\", props.versions[currentIndex.value - 1]);\n}\n\nfunction goOlder(): void {\n if (!canGoOlder.value) return;\n emit(\"navigate\", props.versions[currentIndex.value + 1]);\n}\n\nfunction toggleDropdown(): void {\n isOpen.value = !isOpen.value;\n // Always on open, never only when empty: history grows behind the user's back\n // (every save may record one), so a list fetched once would go stale silently.\n if (isOpen.value) emit(\"open\");\n}\n\nfunction selectVersion(version: TemplateVersion): void {\n emit(\"navigate\", version);\n isOpen.value = false;\n}\n\nfunction formatDate(dateString: string): string {\n const result = formatRelativeTime(dateString, t.time, format, 7);\n if (result !== null) return result;\n\n return new Date(dateString).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\nonClickOutside(dropdownRef, () => {\n isOpen.value = false;\n});\n</script>\n\n<template>\n <div\n ref=\"dropdownRef\"\n class=\"tpl:relative tpl:flex tpl:items-center tpl:gap-0.5\"\n data-testid=\"version-history\"\n >\n <!-- Step to an older version -->\n <button\n class=\"tpl:flex tpl:size-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:disabled:cursor-not-allowed tpl:disabled:opacity-30 tpl:disabled:hover:bg-transparent tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-older\"\n :disabled=\"!canGoOlder\"\n :title=\"t.versionHistory.olderVersion\"\n :aria-label=\"t.versionHistory.olderVersion\"\n @click.stop=\"goOlder\"\n >\n <ChevronLeft :size=\"14\" :stroke-width=\"2\" />\n </button>\n\n <!-- History dropdown toggle -->\n <button\n class=\"tpl:flex tpl:h-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:gap-0.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:px-1.5 tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-toggle\"\n :aria-expanded=\"isOpen\"\n :title=\"t.versionHistory.tooltip\"\n :aria-label=\"t.versionHistory.tooltip\"\n @click.stop=\"toggleDropdown\"\n >\n <Clock :size=\"16\" :stroke-width=\"1.5\" />\n <ChevronDown\n class=\"tpl:transition-transform\"\n :class=\"{ 'tpl:rotate-180': isOpen }\"\n :size=\"10\"\n :stroke-width=\"2\"\n />\n </button>\n\n <Transition name=\"tpl-dropdown\">\n <div\n v-if=\"isOpen\"\n class=\"tpl-scale-in tpl:absolute tpl:top-full tpl:left-1/2 tpl:z-50 tpl:mt-2 tpl:w-72 tpl:-translate-x-1/2 tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:bg-[var(--tpl-bg)] tpl:border tpl:border-[var(--tpl-border)] tpl:shadow-[var(--tpl-shadow-lg)]\"\n data-testid=\"version-history-dropdown\"\n >\n <div\n class=\"tpl:border-b tpl:px-3 tpl:py-2 tpl:text-xs tpl:font-semibold tpl:text-[var(--tpl-text)] tpl:border-[var(--tpl-border)]\"\n >\n {{ t.versionHistory.dropdownTitle }}\n </div>\n\n <div\n v-if=\"isLoading && versions.length === 0\"\n class=\"tpl:flex tpl:items-center tpl:justify-center tpl:py-8\"\n role=\"status\"\n aria-busy=\"true\"\n >\n <LoaderCircle\n class=\"tpl:animate-spin tpl:text-[var(--tpl-primary)]\"\n :size=\"20\"\n :stroke-width=\"2\"\n />\n </div>\n\n <div\n v-else-if=\"versions.length === 0\"\n class=\"tpl:px-3 tpl:py-6 tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-empty\"\n >\n {{ t.versionHistory.empty }}\n </div>\n\n <div v-else class=\"tpl:max-h-64 tpl:overflow-y-auto\">\n <button\n v-for=\"version in versions\"\n :key=\"version.id\"\n class=\"tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:border-l-2 tpl:px-3 tpl:py-2.5 tpl:text-left tpl:transition-all tpl:hover:border-l-[var(--tpl-primary)] tpl:hover:bg-[var(--tpl-bg-hover)]\"\n :class=\"\n version.id === previewingId\n ? 'tpl:border-l-[var(--tpl-primary)] tpl:bg-[var(--tpl-bg-active)]'\n : 'tpl:border-l-transparent'\n \"\n style=\"background-color: transparent\"\n data-testid=\"version-history-entry\"\n :data-version-id=\"version.id\"\n :disabled=\"isRestoring\"\n @click=\"selectVersion(version)\"\n >\n <div class=\"tpl:flex tpl:flex-col tpl:gap-0.5\">\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]\"\n >\n <span>{{\n version.label ?? formatDate(version.createdAt)\n }}</span>\n <span\n v-if=\"version.isAutomatic\"\n class=\"tpl:rounded tpl:px-1 tpl:py-0.5 tpl:text-xs tpl:font-normal tpl:bg-[var(--tpl-bg-active)] tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.versionHistory.auto }}\n </span>\n </div>\n <!-- A labelled version still shows when it was taken, and by whom\n if the store tracks that; an unlabelled one already leads with\n the date, so the line would repeat it. -->\n <div\n v-if=\"version.label || version.author?.name\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n <template v-if=\"version.label\">{{\n formatDate(version.createdAt)\n }}</template>\n <template v-if=\"version.label && version.author?.name\">\n ·\n </template>\n <template v-if=\"version.author?.name\">{{\n version.author.name\n }}</template>\n </div>\n </div>\n </button>\n </div>\n </div>\n </Transition>\n\n <!-- Step to a newer version -->\n <button\n class=\"tpl:flex tpl:size-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:disabled:cursor-not-allowed tpl:disabled:opacity-30 tpl:disabled:hover:bg-transparent tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-newer\"\n :disabled=\"!canGoNewer\"\n :title=\"t.versionHistory.newerVersion\"\n :aria-label=\"t.versionHistory.newerVersion\"\n @click.stop=\"goNewer\"\n >\n <ChevronRight :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * The header's version-history control: step older / newer through the list, or\n * open the dropdown and jump straight to one.\n *\n * Shared by both editors — it was `cloud/components/SnapshotHistory.vue` and\n * spoke Cloud's wire shape (`created_at`, `is_autosave`) directly. It now reads\n * the `TemplateVersion` contract, so any provider drives it.\n */\nimport { computed, ref } from \"vue\";\nimport { onClickOutside } from \"@vueuse/core\";\nimport {\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n Clock,\n LoaderCircle,\n} from \"@lucide/vue\";\nimport type { TemplateVersion } from \"@templatical/types\";\nimport { useI18n } from \"../composables/useI18n\";\nimport { formatRelativeTime } from \"../utils/formatRelativeTime\";\n\nconst props = defineProps<{\n versions: TemplateVersion[];\n isLoading: boolean;\n isRestoring: boolean;\n /** Which version is on the canvas, or `null` while editing normally. */\n previewingId: string | null;\n}>();\n\nconst emit = defineEmits<{\n (e: \"open\"): void;\n (e: \"navigate\", version: TemplateVersion): void;\n}>();\n\nconst { t, format } = useI18n();\n\nconst isOpen = ref(false);\nconst dropdownRef = ref<HTMLElement | null>(null);\n\n/**\n * Position in the list (0 = newest), derived from what is actually previewed\n * rather than tracked locally. A local index went stale the moment the user\n * cancelled a preview — the arrows then stepped from wherever they had left off\n * instead of from the top.\n */\nconst currentIndex = computed(() =>\n props.previewingId === null\n ? -1\n : props.versions.findIndex((v) => v.id === props.previewingId),\n);\n\nconst canGoNewer = computed(\n () => currentIndex.value > 0 && !props.isRestoring && !props.isLoading,\n);\n\nconst canGoOlder = computed(\n () =>\n currentIndex.value < props.versions.length - 1 &&\n props.versions.length > 0 &&\n !props.isRestoring &&\n !props.isLoading,\n);\n\nfunction goNewer(): void {\n if (!canGoNewer.value) return;\n emit(\"navigate\", props.versions[currentIndex.value - 1]);\n}\n\nfunction goOlder(): void {\n if (!canGoOlder.value) return;\n emit(\"navigate\", props.versions[currentIndex.value + 1]);\n}\n\nfunction toggleDropdown(): void {\n isOpen.value = !isOpen.value;\n // Always on open, never only when empty: history grows behind the user's back\n // (every save may record one), so a list fetched once would go stale silently.\n if (isOpen.value) emit(\"open\");\n}\n\nfunction selectVersion(version: TemplateVersion): void {\n emit(\"navigate\", version);\n isOpen.value = false;\n}\n\nfunction formatDate(dateString: string): string {\n const result = formatRelativeTime(dateString, t.time, format, 7);\n if (result !== null) return result;\n\n return new Date(dateString).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\nonClickOutside(dropdownRef, () => {\n isOpen.value = false;\n});\n</script>\n\n<template>\n <div\n ref=\"dropdownRef\"\n class=\"tpl:relative tpl:flex tpl:items-center tpl:gap-0.5\"\n data-testid=\"version-history\"\n >\n <!-- Step to an older version -->\n <button\n class=\"tpl:flex tpl:size-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:disabled:cursor-not-allowed tpl:disabled:opacity-30 tpl:disabled:hover:bg-transparent tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-older\"\n :disabled=\"!canGoOlder\"\n :title=\"t.versionHistory.olderVersion\"\n :aria-label=\"t.versionHistory.olderVersion\"\n @click.stop=\"goOlder\"\n >\n <ChevronLeft :size=\"14\" :stroke-width=\"2\" />\n </button>\n\n <!-- History dropdown toggle -->\n <button\n class=\"tpl:flex tpl:h-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:gap-0.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:px-1.5 tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-toggle\"\n :aria-expanded=\"isOpen\"\n :title=\"t.versionHistory.tooltip\"\n :aria-label=\"t.versionHistory.tooltip\"\n @click.stop=\"toggleDropdown\"\n >\n <Clock :size=\"16\" :stroke-width=\"1.5\" />\n <ChevronDown\n class=\"tpl:transition-transform\"\n :class=\"{ 'tpl:rotate-180': isOpen }\"\n :size=\"10\"\n :stroke-width=\"2\"\n />\n </button>\n\n <Transition name=\"tpl-dropdown\">\n <div\n v-if=\"isOpen\"\n class=\"tpl-scale-in tpl:absolute tpl:top-full tpl:left-1/2 tpl:z-50 tpl:mt-2 tpl:w-72 tpl:-translate-x-1/2 tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:bg-[var(--tpl-bg)] tpl:border tpl:border-[var(--tpl-border)] tpl:shadow-[var(--tpl-shadow-lg)]\"\n data-testid=\"version-history-dropdown\"\n >\n <div\n class=\"tpl:border-b tpl:px-3 tpl:py-2 tpl:text-xs tpl:font-semibold tpl:text-[var(--tpl-text)] tpl:border-[var(--tpl-border)]\"\n >\n {{ t.versionHistory.dropdownTitle }}\n </div>\n\n <div\n v-if=\"isLoading && versions.length === 0\"\n class=\"tpl:flex tpl:items-center tpl:justify-center tpl:py-8\"\n role=\"status\"\n aria-busy=\"true\"\n >\n <LoaderCircle\n class=\"tpl:animate-spin tpl:text-[var(--tpl-primary)]\"\n :size=\"20\"\n :stroke-width=\"2\"\n />\n </div>\n\n <div\n v-else-if=\"versions.length === 0\"\n class=\"tpl:px-3 tpl:py-6 tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-empty\"\n >\n {{ t.versionHistory.empty }}\n </div>\n\n <div v-else class=\"tpl:max-h-64 tpl:overflow-y-auto\">\n <button\n v-for=\"version in versions\"\n :key=\"version.id\"\n class=\"tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:border-l-2 tpl:px-3 tpl:py-2.5 tpl:text-left tpl:transition-all tpl:hover:border-l-[var(--tpl-primary)] tpl:hover:bg-[var(--tpl-bg-hover)]\"\n :class=\"\n version.id === previewingId\n ? 'tpl:border-l-[var(--tpl-primary)] tpl:bg-[var(--tpl-bg-active)]'\n : 'tpl:border-l-transparent'\n \"\n style=\"background-color: transparent\"\n data-testid=\"version-history-entry\"\n :data-version-id=\"version.id\"\n :disabled=\"isRestoring\"\n @click=\"selectVersion(version)\"\n >\n <div class=\"tpl:flex tpl:flex-col tpl:gap-0.5\">\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]\"\n >\n <span>{{\n version.label ?? formatDate(version.createdAt)\n }}</span>\n <span\n v-if=\"version.isAutomatic\"\n class=\"tpl:rounded tpl:px-1 tpl:py-0.5 tpl:text-xs tpl:font-normal tpl:bg-[var(--tpl-bg-active)] tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.versionHistory.auto }}\n </span>\n </div>\n <!-- A labelled version still shows when it was taken, and by whom\n if the store tracks that; an unlabelled one already leads with\n the date, so the line would repeat it. -->\n <div\n v-if=\"version.label || version.author?.name\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n <template v-if=\"version.label\">{{\n formatDate(version.createdAt)\n }}</template>\n <template v-if=\"version.label && version.author?.name\">\n ·\n </template>\n <template v-if=\"version.author?.name\">{{\n version.author.name\n }}</template>\n </div>\n </div>\n </button>\n </div>\n </div>\n </Transition>\n\n <!-- Step to a newer version -->\n <button\n class=\"tpl:flex tpl:size-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:disabled:cursor-not-allowed tpl:disabled:opacity-30 tpl:disabled:hover:bg-transparent tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-newer\"\n :disabled=\"!canGoNewer\"\n :title=\"t.versionHistory.newerVersion\"\n :aria-label=\"t.versionHistory.newerVersion\"\n @click.stop=\"goNewer\"\n >\n <ChevronRight :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsBA,IAAM,IAAQ,GAQR,IAAO,GAKP,EAAE,MAAG,cAAW,EAAQ,GAExB,IAAS,EAAI,EAAK,GAClB,IAAc,EAAwB,IAAI,GAQ1C,IAAe,QACnB,EAAM,iBAAiB,OACnB,KACA,EAAM,SAAS,WAAW,MAAM,EAAE,OAAO,EAAM,YAAY,CACjE,GAEM,IAAa,QACX,EAAa,QAAQ,KAAK,CAAC,EAAM,eAAe,CAAC,EAAM,SAC/D,GAEM,IAAa,QAEf,EAAa,QAAQ,EAAM,SAAS,SAAS,KAC7C,EAAM,SAAS,SAAS,KACxB,CAAC,EAAM,eACP,CAAC,EAAM,SACX;EAEA,SAAS,IAAgB;GAClB,EAAW,SAChB,EAAK,YAAY,EAAM,SAAS,EAAa,QAAQ,EAAE;EACzD;EAEA,SAAS,IAAgB;GAClB,EAAW,SAChB,EAAK,YAAY,EAAM,SAAS,EAAa,QAAQ,EAAE;EACzD;EAEA,SAAS,IAAuB;GAI9B,AAHA,EAAO,QAAQ,CAAC,EAAO,OAGnB,EAAO,SAAO,EAAK,MAAM;EAC/B;EAEA,SAAS,EAAc,GAAgC;GAErD,AADA,EAAK,YAAY,CAAO,GACxB,EAAO,QAAQ;EACjB;EAEA,SAAS,EAAW,GAA4B;GAC9C,IAAM,IAAS,EAAmB,GAAY,EAAE,MAAM,GAAQ,CAAC;GAG/D,OAFI,MAAW,OAER,IAAI,KAAK,CAAU,CAAC,CAAC,mBAAmB,KAAA,GAAW;IACxD,OAAO;IACP,KAAK;IACL,MAAM;IACN,QAAQ;GACV,CAAC,IAP2B;EAQ9B;SAEA,EAAe,SAAmB;GAChC,EAAO,QAAQ;EACjB,CAAC,cAIC,EAAA,GAAA,EAoIM,OAAA;GAnIA,SAAA;GAAJ,KAAI;GACJ,OAAM;GACN,eAAY;;GAGZ,EASS,UAAA;IARP,OAAM;IACN,eAAY;IACX,UAAQ,CAAG,EAAA;IACX,OAAO,EAAA,CAAA,CAAC,CAAC,eAAe;IACxB,cAAY,EAAA,CAAA,CAAC,CAAC,eAAe;IAC7B,SAAK,EAAO,GAAO,CAAA,MAAA,CAAA;GAEpB,GAAA,CAAA,EAA4C,EAAA,CAAA,GAAA;IAA9B,MAAM;IAAK,gBAAc;;GAIzC,EAeS,UAAA;IAdP,OAAM;IACN,eAAY;IACX,iBAAe,EAAA;IACf,OAAO,EAAA,CAAA,CAAC,CAAC,eAAe;IACxB,cAAY,EAAA,CAAA,CAAC,CAAC,eAAe;IAC7B,SAAK,EAAO,GAAc,CAAA,MAAA,CAAA;GAE3B,GAAA,CAAA,EAAwC,EAAA,CAAA,GAAA;IAAhC,MAAM;IAAK,gBAAc;GACjC,CAAA,GAAA,EAKE,EAAA,CAAA,GAAA;IAJA,OAAK,EAAA,CAAC,4BAA0B,EAAA,kBACJ,EAAA,MAAM,CAAA,CAAA;IACjC,MAAM;IACN,gBAAc;;GAInB,EAoFa,GAAA,EApFD,MAAK,eAAc,GAAA;IAC7B,SAAA,QAkFM,CAjFE,EAAA,SADR,EAAA,GAAA,EAkFM,OAlFN,GAkFM,CA7EJ,EAIM,OAJN,GAIM,EADD,EAAA,CAAA,CAAC,CAAC,eAAe,aAAa,GAAA,CAAA,GAI3B,EAAA,aAAa,EAAA,SAAS,WAAM,KADpC,EAAA,GAAA,EAWM,OAXN,GAWM,CALJ,EAIE,EAAA,CAAA,GAAA;KAHA,OAAM;KACL,MAAM;KACN,gBAAc;IAKN,CAAA,CAAA,CAAA,KAAA,EAAA,SAAS,WAAM,KAD5B,EAAA,GAAA,EAMM,OANN,GAMM,EADD,EAAA,CAAA,CAAC,CAAC,eAAe,KAAK,GAAA,CAAA,MAG3B,EAAA,GAAA,EAiDM,OAjDN,GAiDM,EAhDJ,EAAA,EAAA,GAAA,EA+CS,GAAA,MAAA,EA9CW,EAAA,WAAX,OADT,EAAA,GAAA,EA+CS,UAAA;KA7CN,KAAK,EAAQ;KACd,OAAK,EAAA,CAAC,0MACiB,EAAQ,OAAO,EAAA,eAAA,oEAAA,0BAAA,CAAA;KAKtC,OAAA,EAAA,oBAAA,cAAA;KACA,eAAY;KACX,mBAAiB,EAAQ;KACzB,UAAU,EAAA;KACV,UAAK,MAAE,EAAc,CAAO;IAE7B,GAAA,CAAA,EA+BM,OA/BN,GA+BM,CA9BJ,EAYM,OAZN,GAYM,CATJ,EAES,QAAA,MAAA,EADP,EAAQ,SAAS,EAAW,EAAQ,SAAS,CAAA,GAAA,CAAA,GAGvC,EAAQ,eADhB,EAAA,GAAA,EAKO,QALP,GAKO,EADF,EAAA,CAAA,CAAC,CAAC,eAAe,IAAI,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,GAOpB,EAAQ,SAAS,EAAQ,QAAQ,QADzC,EAAA,GAAA,EAaM,OAbN,GAaM;KATY,EAAQ,SAAxB,EAAA,GAAA,EAEa,GAAA,EAAA,KAAA,EAAA,GAAA,CADX,EAAA,EAAA,EAAW,EAAQ,SAAS,CAAA,GAAA,CAAA,CAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA;KAEd,EAAQ,SAAS,EAAQ,QAAQ,QAAjD,EAAA,GAAA,EAEW,GAAA,EAAA,KAAA,EAAA,GAAA,CAF4C,EAAA,KAEvD,CAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA;KACgB,EAAQ,QAAQ,QAAhC,EAAA,GAAA,EAEa,GAAA,EAAA,KAAA,EAAA,GAAA,CADX,EAAA,EAAA,EAAQ,OAAO,IAAI,GAAA,CAAA,CAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA;;;;GAUjC,EASS,UAAA;IARP,OAAM;IACN,eAAY;IACX,UAAQ,CAAG,EAAA;IACX,OAAO,EAAA,CAAA,CAAC,CAAC,eAAe;IACxB,cAAY,EAAA,CAAA,CAAC,CAAC,eAAe;IAC7B,SAAK,EAAO,GAAO,CAAA,MAAA,CAAA;GAEpB,GAAA,CAAA,EAA6C,EAAA,CAAA,GAAA;IAA9B,MAAM;IAAK,gBAAc"}
1
+ {"version":3,"file":"VersionHistoryMenu-BNYSIjVj.js","names":[],"sources":["../../../src/components/VersionHistoryMenu.vue","../../../src/components/VersionHistoryMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * The header's version-history control: step older / newer through the list, or\n * open the dropdown and jump straight to one.\n *\n * Shared by both editors — it was `cloud/components/SnapshotHistory.vue` and\n * spoke Cloud's wire shape (`created_at`, `is_autosave`) directly. It now reads\n * the `TemplateVersion` contract, so any provider drives it.\n */\nimport { computed, ref } from \"vue\";\nimport { onClickOutside } from \"@vueuse/core\";\nimport {\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n Clock,\n LoaderCircle,\n} from \"@lucide/vue\";\nimport type { TemplateVersion } from \"@templatical/types\";\nimport { useI18n } from \"../composables/useI18n\";\nimport { formatRelativeTime } from \"../utils/formatRelativeTime\";\n\nconst props = defineProps<{\n versions: TemplateVersion[];\n isLoading: boolean;\n isRestoring: boolean;\n /** Which version is on the canvas, or `null` while editing normally. */\n previewingId: string | null;\n}>();\n\nconst emit = defineEmits<{\n (e: \"open\"): void;\n (e: \"navigate\", version: TemplateVersion): void;\n}>();\n\nconst { t, format } = useI18n();\n\nconst isOpen = ref(false);\nconst dropdownRef = ref<HTMLElement | null>(null);\n\n/**\n * Position in the list (0 = newest), derived from what is actually previewed\n * rather than tracked locally. A local index went stale the moment the user\n * cancelled a preview — the arrows then stepped from wherever they had left off\n * instead of from the top.\n */\nconst currentIndex = computed(() =>\n props.previewingId === null\n ? -1\n : props.versions.findIndex((v) => v.id === props.previewingId),\n);\n\nconst canGoNewer = computed(\n () => currentIndex.value > 0 && !props.isRestoring && !props.isLoading,\n);\n\nconst canGoOlder = computed(\n () =>\n currentIndex.value < props.versions.length - 1 &&\n props.versions.length > 0 &&\n !props.isRestoring &&\n !props.isLoading,\n);\n\nfunction goNewer(): void {\n if (!canGoNewer.value) return;\n emit(\"navigate\", props.versions[currentIndex.value - 1]);\n}\n\nfunction goOlder(): void {\n if (!canGoOlder.value) return;\n emit(\"navigate\", props.versions[currentIndex.value + 1]);\n}\n\nfunction toggleDropdown(): void {\n isOpen.value = !isOpen.value;\n // Always on open, never only when empty: history grows behind the user's back\n // (every save may record one), so a list fetched once would go stale silently.\n if (isOpen.value) emit(\"open\");\n}\n\nfunction selectVersion(version: TemplateVersion): void {\n emit(\"navigate\", version);\n isOpen.value = false;\n}\n\nfunction formatDate(dateString: string): string {\n const result = formatRelativeTime(dateString, t.time, format, 7);\n if (result !== null) return result;\n\n return new Date(dateString).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\nonClickOutside(dropdownRef, () => {\n isOpen.value = false;\n});\n</script>\n\n<template>\n <div\n ref=\"dropdownRef\"\n class=\"tpl:relative tpl:flex tpl:items-center tpl:gap-0.5\"\n data-testid=\"version-history\"\n >\n <!-- Step to an older version -->\n <button\n class=\"tpl:flex tpl:size-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:disabled:cursor-not-allowed tpl:disabled:opacity-30 tpl:disabled:hover:bg-transparent tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-older\"\n :disabled=\"!canGoOlder\"\n :title=\"t.versionHistory.olderVersion\"\n :aria-label=\"t.versionHistory.olderVersion\"\n @click.stop=\"goOlder\"\n >\n <ChevronLeft :size=\"14\" :stroke-width=\"2\" />\n </button>\n\n <!-- History dropdown toggle -->\n <button\n class=\"tpl:flex tpl:h-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:gap-0.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:px-1.5 tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-toggle\"\n :aria-expanded=\"isOpen\"\n :title=\"t.versionHistory.tooltip\"\n :aria-label=\"t.versionHistory.tooltip\"\n @click.stop=\"toggleDropdown\"\n >\n <Clock :size=\"16\" :stroke-width=\"1.5\" />\n <ChevronDown\n class=\"tpl:transition-transform\"\n :class=\"{ 'tpl:rotate-180': isOpen }\"\n :size=\"10\"\n :stroke-width=\"2\"\n />\n </button>\n\n <Transition name=\"tpl-dropdown\">\n <div\n v-if=\"isOpen\"\n class=\"tpl-scale-in tpl:absolute tpl:top-full tpl:left-1/2 tpl:z-50 tpl:mt-2 tpl:w-72 tpl:-translate-x-1/2 tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:bg-[var(--tpl-bg)] tpl:border tpl:border-[var(--tpl-border)] tpl:shadow-[var(--tpl-shadow-lg)]\"\n data-testid=\"version-history-dropdown\"\n >\n <div\n class=\"tpl:border-b tpl:px-3 tpl:py-2 tpl:text-xs tpl:font-semibold tpl:text-[var(--tpl-text)] tpl:border-[var(--tpl-border)]\"\n >\n {{ t.versionHistory.dropdownTitle }}\n </div>\n\n <div\n v-if=\"isLoading && versions.length === 0\"\n class=\"tpl:flex tpl:items-center tpl:justify-center tpl:py-8\"\n role=\"status\"\n aria-busy=\"true\"\n >\n <LoaderCircle\n class=\"tpl:animate-spin tpl:text-[var(--tpl-primary)]\"\n :size=\"20\"\n :stroke-width=\"2\"\n />\n </div>\n\n <div\n v-else-if=\"versions.length === 0\"\n class=\"tpl:px-3 tpl:py-6 tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-empty\"\n >\n {{ t.versionHistory.empty }}\n </div>\n\n <div v-else class=\"tpl:max-h-64 tpl:overflow-y-auto\">\n <button\n v-for=\"version in versions\"\n :key=\"version.id\"\n class=\"tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:border-l-2 tpl:px-3 tpl:py-2.5 tpl:text-left tpl:transition-all tpl:hover:border-l-[var(--tpl-primary)] tpl:hover:bg-[var(--tpl-bg-hover)]\"\n :class=\"\n version.id === previewingId\n ? 'tpl:border-l-[var(--tpl-primary)] tpl:bg-[var(--tpl-bg-active)]'\n : 'tpl:border-l-transparent'\n \"\n style=\"background-color: transparent\"\n data-testid=\"version-history-entry\"\n :data-version-id=\"version.id\"\n :disabled=\"isRestoring\"\n @click=\"selectVersion(version)\"\n >\n <div class=\"tpl:flex tpl:flex-col tpl:gap-0.5\">\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]\"\n >\n <span>{{\n version.label ?? formatDate(version.createdAt)\n }}</span>\n <span\n v-if=\"version.isAutomatic\"\n class=\"tpl:rounded tpl:px-1 tpl:py-0.5 tpl:text-xs tpl:font-normal tpl:bg-[var(--tpl-bg-active)] tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.versionHistory.auto }}\n </span>\n </div>\n <!-- A labelled version still shows when it was taken, and by whom\n if the store tracks that; an unlabelled one already leads with\n the date, so the line would repeat it. -->\n <div\n v-if=\"version.label || version.author?.name\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n <template v-if=\"version.label\">{{\n formatDate(version.createdAt)\n }}</template>\n <template v-if=\"version.label && version.author?.name\">\n ·\n </template>\n <template v-if=\"version.author?.name\">{{\n version.author.name\n }}</template>\n </div>\n </div>\n </button>\n </div>\n </div>\n </Transition>\n\n <!-- Step to a newer version -->\n <button\n class=\"tpl:flex tpl:size-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:disabled:cursor-not-allowed tpl:disabled:opacity-30 tpl:disabled:hover:bg-transparent tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-newer\"\n :disabled=\"!canGoNewer\"\n :title=\"t.versionHistory.newerVersion\"\n :aria-label=\"t.versionHistory.newerVersion\"\n @click.stop=\"goNewer\"\n >\n <ChevronRight :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * The header's version-history control: step older / newer through the list, or\n * open the dropdown and jump straight to one.\n *\n * Shared by both editors — it was `cloud/components/SnapshotHistory.vue` and\n * spoke Cloud's wire shape (`created_at`, `is_autosave`) directly. It now reads\n * the `TemplateVersion` contract, so any provider drives it.\n */\nimport { computed, ref } from \"vue\";\nimport { onClickOutside } from \"@vueuse/core\";\nimport {\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n Clock,\n LoaderCircle,\n} from \"@lucide/vue\";\nimport type { TemplateVersion } from \"@templatical/types\";\nimport { useI18n } from \"../composables/useI18n\";\nimport { formatRelativeTime } from \"../utils/formatRelativeTime\";\n\nconst props = defineProps<{\n versions: TemplateVersion[];\n isLoading: boolean;\n isRestoring: boolean;\n /** Which version is on the canvas, or `null` while editing normally. */\n previewingId: string | null;\n}>();\n\nconst emit = defineEmits<{\n (e: \"open\"): void;\n (e: \"navigate\", version: TemplateVersion): void;\n}>();\n\nconst { t, format } = useI18n();\n\nconst isOpen = ref(false);\nconst dropdownRef = ref<HTMLElement | null>(null);\n\n/**\n * Position in the list (0 = newest), derived from what is actually previewed\n * rather than tracked locally. A local index went stale the moment the user\n * cancelled a preview — the arrows then stepped from wherever they had left off\n * instead of from the top.\n */\nconst currentIndex = computed(() =>\n props.previewingId === null\n ? -1\n : props.versions.findIndex((v) => v.id === props.previewingId),\n);\n\nconst canGoNewer = computed(\n () => currentIndex.value > 0 && !props.isRestoring && !props.isLoading,\n);\n\nconst canGoOlder = computed(\n () =>\n currentIndex.value < props.versions.length - 1 &&\n props.versions.length > 0 &&\n !props.isRestoring &&\n !props.isLoading,\n);\n\nfunction goNewer(): void {\n if (!canGoNewer.value) return;\n emit(\"navigate\", props.versions[currentIndex.value - 1]);\n}\n\nfunction goOlder(): void {\n if (!canGoOlder.value) return;\n emit(\"navigate\", props.versions[currentIndex.value + 1]);\n}\n\nfunction toggleDropdown(): void {\n isOpen.value = !isOpen.value;\n // Always on open, never only when empty: history grows behind the user's back\n // (every save may record one), so a list fetched once would go stale silently.\n if (isOpen.value) emit(\"open\");\n}\n\nfunction selectVersion(version: TemplateVersion): void {\n emit(\"navigate\", version);\n isOpen.value = false;\n}\n\nfunction formatDate(dateString: string): string {\n const result = formatRelativeTime(dateString, t.time, format, 7);\n if (result !== null) return result;\n\n return new Date(dateString).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\nonClickOutside(dropdownRef, () => {\n isOpen.value = false;\n});\n</script>\n\n<template>\n <div\n ref=\"dropdownRef\"\n class=\"tpl:relative tpl:flex tpl:items-center tpl:gap-0.5\"\n data-testid=\"version-history\"\n >\n <!-- Step to an older version -->\n <button\n class=\"tpl:flex tpl:size-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:disabled:cursor-not-allowed tpl:disabled:opacity-30 tpl:disabled:hover:bg-transparent tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-older\"\n :disabled=\"!canGoOlder\"\n :title=\"t.versionHistory.olderVersion\"\n :aria-label=\"t.versionHistory.olderVersion\"\n @click.stop=\"goOlder\"\n >\n <ChevronLeft :size=\"14\" :stroke-width=\"2\" />\n </button>\n\n <!-- History dropdown toggle -->\n <button\n class=\"tpl:flex tpl:h-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:gap-0.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:px-1.5 tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-toggle\"\n :aria-expanded=\"isOpen\"\n :title=\"t.versionHistory.tooltip\"\n :aria-label=\"t.versionHistory.tooltip\"\n @click.stop=\"toggleDropdown\"\n >\n <Clock :size=\"16\" :stroke-width=\"1.5\" />\n <ChevronDown\n class=\"tpl:transition-transform\"\n :class=\"{ 'tpl:rotate-180': isOpen }\"\n :size=\"10\"\n :stroke-width=\"2\"\n />\n </button>\n\n <Transition name=\"tpl-dropdown\">\n <div\n v-if=\"isOpen\"\n class=\"tpl-scale-in tpl:absolute tpl:top-full tpl:left-1/2 tpl:z-50 tpl:mt-2 tpl:w-72 tpl:-translate-x-1/2 tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:bg-[var(--tpl-bg)] tpl:border tpl:border-[var(--tpl-border)] tpl:shadow-[var(--tpl-shadow-lg)]\"\n data-testid=\"version-history-dropdown\"\n >\n <div\n class=\"tpl:border-b tpl:px-3 tpl:py-2 tpl:text-xs tpl:font-semibold tpl:text-[var(--tpl-text)] tpl:border-[var(--tpl-border)]\"\n >\n {{ t.versionHistory.dropdownTitle }}\n </div>\n\n <div\n v-if=\"isLoading && versions.length === 0\"\n class=\"tpl:flex tpl:items-center tpl:justify-center tpl:py-8\"\n role=\"status\"\n aria-busy=\"true\"\n >\n <LoaderCircle\n class=\"tpl:animate-spin tpl:text-[var(--tpl-primary)]\"\n :size=\"20\"\n :stroke-width=\"2\"\n />\n </div>\n\n <div\n v-else-if=\"versions.length === 0\"\n class=\"tpl:px-3 tpl:py-6 tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-empty\"\n >\n {{ t.versionHistory.empty }}\n </div>\n\n <div v-else class=\"tpl:max-h-64 tpl:overflow-y-auto\">\n <button\n v-for=\"version in versions\"\n :key=\"version.id\"\n class=\"tpl:flex tpl:w-full tpl:cursor-pointer tpl:items-center tpl:border-l-2 tpl:px-3 tpl:py-2.5 tpl:text-left tpl:transition-all tpl:hover:border-l-[var(--tpl-primary)] tpl:hover:bg-[var(--tpl-bg-hover)]\"\n :class=\"\n version.id === previewingId\n ? 'tpl:border-l-[var(--tpl-primary)] tpl:bg-[var(--tpl-bg-active)]'\n : 'tpl:border-l-transparent'\n \"\n style=\"background-color: transparent\"\n data-testid=\"version-history-entry\"\n :data-version-id=\"version.id\"\n :disabled=\"isRestoring\"\n @click=\"selectVersion(version)\"\n >\n <div class=\"tpl:flex tpl:flex-col tpl:gap-0.5\">\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]\"\n >\n <span>{{\n version.label ?? formatDate(version.createdAt)\n }}</span>\n <span\n v-if=\"version.isAutomatic\"\n class=\"tpl:rounded tpl:px-1 tpl:py-0.5 tpl:text-xs tpl:font-normal tpl:bg-[var(--tpl-bg-active)] tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.versionHistory.auto }}\n </span>\n </div>\n <!-- A labelled version still shows when it was taken, and by whom\n if the store tracks that; an unlabelled one already leads with\n the date, so the line would repeat it. -->\n <div\n v-if=\"version.label || version.author?.name\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n <template v-if=\"version.label\">{{\n formatDate(version.createdAt)\n }}</template>\n <template v-if=\"version.label && version.author?.name\">\n ·\n </template>\n <template v-if=\"version.author?.name\">{{\n version.author.name\n }}</template>\n </div>\n </div>\n </button>\n </div>\n </div>\n </Transition>\n\n <!-- Step to a newer version -->\n <button\n class=\"tpl:flex tpl:size-7 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:transition-colors tpl:hover:bg-[var(--tpl-bg-hover)] tpl:disabled:cursor-not-allowed tpl:disabled:opacity-30 tpl:disabled:hover:bg-transparent tpl:text-[var(--tpl-text-muted)]\"\n data-testid=\"version-history-newer\"\n :disabled=\"!canGoNewer\"\n :title=\"t.versionHistory.newerVersion\"\n :aria-label=\"t.versionHistory.newerVersion\"\n @click.stop=\"goNewer\"\n >\n <ChevronRight :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n</template>\n"],"mappings":"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"}
@@ -5,7 +5,7 @@ var c = /* @__PURE__ */ t({
5
5
  __name: "VersionHistoryPanels",
6
6
  props: { feature: {} },
7
7
  setup(t) {
8
- let c = t, l = s(() => import("./VersionPreviewBanner-Dw4kFkrh.js")), u = s(() => import("./RestoreVersionDialog-CKtz_FEz.js"));
8
+ let c = t, l = s(() => import("./VersionPreviewBanner-CBVDWnhq.js")), u = s(() => import("./RestoreVersionDialog-tfoAQAeP.js"));
9
9
  async function d() {
10
10
  try {
11
11
  await c.feature.requestRestore();
@@ -45,4 +45,4 @@ var c = /* @__PURE__ */ t({
45
45
  //#endregion
46
46
  export { c as default };
47
47
 
48
- //# sourceMappingURL=VersionHistoryPanels-DHDN1owI.js.map
48
+ //# sourceMappingURL=VersionHistoryPanels-CvWySHUE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VersionHistoryPanels-DHDN1owI.js","names":[],"sources":["../../../src/components/VersionHistoryPanels.vue","../../../src/components/VersionHistoryPanels.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Mount point for the version-history chrome that sits outside the header,\n * shared by the OSS and Cloud editors.\n *\n * Same shape as `SavedBlocksPanels.vue` / `TestEmailPanel.vue`: everything here\n * is `defineAsyncComponent` behind a `v-if` on its own state, and the editors in\n * turn lazy-load *this* wrapper and render it only when a\n * `VersionHistoryProvider` is configured — so a consumer without one downloads\n * none of it.\n *\n * The header's dropdown control is not here for one reason only: it has to sit\n * in the header's centre column. It is lazily imported at those two sites\n * instead, and covered by the same CDN chunk guard.\n */\nimport { defineAsyncComponent } from \"vue\";\nimport type { UseVersionHistoryFeatureReturn } from \"../composables/useVersionHistoryFeature\";\n\nconst props = defineProps<{\n feature: UseVersionHistoryFeatureReturn;\n}>();\n\nconst VersionPreviewBanner = defineAsyncComponent(\n () => import(\"./VersionPreviewBanner.vue\"),\n);\n// Its own chunk, fetched only if a restore is attempted with unsaved work —\n// which for a Cloud session (autosave on) is the uncommon case.\nconst RestoreVersionDialog = defineAsyncComponent(\n () => import(\"./RestoreVersionDialog.vue\"),\n);\n\n/**\n * Every action here swallows its rejection: the feature already reported it\n * through `onError` and rolled the canvas back, and an unhandled rejection out\n * of a DOM event binding helps nobody.\n */\nasync function handleRequestRestore(): Promise<void> {\n try {\n await props.feature.requestRestore();\n } catch {\n /* reported through onError */\n }\n}\n\nasync function handleSaveAndRestore(): Promise<void> {\n try {\n await props.feature.saveAndRestore();\n } catch {\n /* reported through onError */\n }\n}\n\nasync function handleDiscardAndRestore(): Promise<void> {\n try {\n await props.feature.discardAndRestore();\n } catch {\n /* reported through onError */\n }\n}\n</script>\n\n<template>\n <VersionPreviewBanner\n v-if=\"feature.isPreviewing.value\"\n :visible=\"feature.isPreviewing.value\"\n :can-restore=\"feature.canRestore.value\"\n @cancel=\"feature.cancelPreview()\"\n @confirm=\"handleRequestRestore\"\n />\n\n <RestoreVersionDialog\n v-if=\"feature.isConfirmingRestore.value\"\n :visible=\"feature.isConfirmingRestore.value\"\n :can-save=\"feature.canSaveBeforeRestore.value\"\n :is-busy=\"feature.isConfirmBusy.value\"\n @cancel=\"feature.cancelRestoreConfirm()\"\n @save-and-restore=\"handleSaveAndRestore\"\n @discard-and-restore=\"handleDiscardAndRestore\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Mount point for the version-history chrome that sits outside the header,\n * shared by the OSS and Cloud editors.\n *\n * Same shape as `SavedBlocksPanels.vue` / `TestEmailPanel.vue`: everything here\n * is `defineAsyncComponent` behind a `v-if` on its own state, and the editors in\n * turn lazy-load *this* wrapper and render it only when a\n * `VersionHistoryProvider` is configured — so a consumer without one downloads\n * none of it.\n *\n * The header's dropdown control is not here for one reason only: it has to sit\n * in the header's centre column. It is lazily imported at those two sites\n * instead, and covered by the same CDN chunk guard.\n */\nimport { defineAsyncComponent } from \"vue\";\nimport type { UseVersionHistoryFeatureReturn } from \"../composables/useVersionHistoryFeature\";\n\nconst props = defineProps<{\n feature: UseVersionHistoryFeatureReturn;\n}>();\n\nconst VersionPreviewBanner = defineAsyncComponent(\n () => import(\"./VersionPreviewBanner.vue\"),\n);\n// Its own chunk, fetched only if a restore is attempted with unsaved work —\n// which for a Cloud session (autosave on) is the uncommon case.\nconst RestoreVersionDialog = defineAsyncComponent(\n () => import(\"./RestoreVersionDialog.vue\"),\n);\n\n/**\n * Every action here swallows its rejection: the feature already reported it\n * through `onError` and rolled the canvas back, and an unhandled rejection out\n * of a DOM event binding helps nobody.\n */\nasync function handleRequestRestore(): Promise<void> {\n try {\n await props.feature.requestRestore();\n } catch {\n /* reported through onError */\n }\n}\n\nasync function handleSaveAndRestore(): Promise<void> {\n try {\n await props.feature.saveAndRestore();\n } catch {\n /* reported through onError */\n }\n}\n\nasync function handleDiscardAndRestore(): Promise<void> {\n try {\n await props.feature.discardAndRestore();\n } catch {\n /* reported through onError */\n }\n}\n</script>\n\n<template>\n <VersionPreviewBanner\n v-if=\"feature.isPreviewing.value\"\n :visible=\"feature.isPreviewing.value\"\n :can-restore=\"feature.canRestore.value\"\n @cancel=\"feature.cancelPreview()\"\n @confirm=\"handleRequestRestore\"\n />\n\n <RestoreVersionDialog\n v-if=\"feature.isConfirmingRestore.value\"\n :visible=\"feature.isConfirmingRestore.value\"\n :can-save=\"feature.canSaveBeforeRestore.value\"\n :is-busy=\"feature.isConfirmBusy.value\"\n @cancel=\"feature.cancelRestoreConfirm()\"\n @save-and-restore=\"handleSaveAndRestore\"\n @discard-and-restore=\"handleDiscardAndRestore\"\n />\n</template>\n"],"mappings":";;;;;;;EAkBA,IAAM,IAAQ,GAIR,IAAuB,QACrB,OAAO,qCACf,GAGM,IAAuB,QACrB,OAAO,qCACf;EAOA,eAAe,IAAsC;GACnD,IAAI;IACF,MAAM,EAAM,QAAQ,eAAe;GACrC,QAAQ,CAER;EACF;EAEA,eAAe,IAAsC;GACnD,IAAI;IACF,MAAM,EAAM,QAAQ,eAAe;GACrC,QAAQ,CAER;EACF;EAEA,eAAe,IAAyC;GACtD,IAAI;IACF,MAAM,EAAM,QAAQ,kBAAkB;GACxC,QAAQ,CAER;EACF;oBAKU,EAAA,GAAA,EAAA,GAAA,MAAA,CAAA,EAAA,QAAQ,aAAa,SAD7B,EAAA,GAAA,EAME,EAAA,CAAA,GAAA;;GAJC,SAAS,EAAA,QAAQ,aAAa;GAC9B,eAAa,EAAA,QAAQ,WAAW;GAChC,UAAM,AAAA,EAAA,QAAA,MAAE,EAAA,QAAQ,cAAa;GAC7B,WAAS;EAIJ,GAAA,MAAA,GAAA,CAAA,WAAA,aAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAA,QAAQ,oBAAoB,SADpC,EAAA,GAAA,EAQE,EAAA,CAAA,GAAA;;GANC,SAAS,EAAA,QAAQ,oBAAoB;GACrC,YAAU,EAAA,QAAQ,qBAAqB;GACvC,WAAS,EAAA,QAAQ,cAAc;GAC/B,UAAM,AAAA,EAAA,QAAA,MAAE,EAAA,QAAQ,qBAAoB;GACpC,kBAAkB;GAClB,qBAAqB"}
1
+ {"version":3,"file":"VersionHistoryPanels-CvWySHUE.js","names":[],"sources":["../../../src/components/VersionHistoryPanels.vue","../../../src/components/VersionHistoryPanels.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Mount point for the version-history chrome that sits outside the header,\n * shared by the OSS and Cloud editors.\n *\n * Same shape as `SavedBlocksPanels.vue` / `TestEmailPanel.vue`: everything here\n * is `defineAsyncComponent` behind a `v-if` on its own state, and the editors in\n * turn lazy-load *this* wrapper and render it only when a\n * `VersionHistoryProvider` is configured — so a consumer without one downloads\n * none of it.\n *\n * The header's dropdown control is not here for one reason only: it has to sit\n * in the header's centre column. It is lazily imported at those two sites\n * instead, and covered by the same CDN chunk guard.\n */\nimport { defineAsyncComponent } from \"vue\";\nimport type { UseVersionHistoryFeatureReturn } from \"../composables/useVersionHistoryFeature\";\n\nconst props = defineProps<{\n feature: UseVersionHistoryFeatureReturn;\n}>();\n\nconst VersionPreviewBanner = defineAsyncComponent(\n () => import(\"./VersionPreviewBanner.vue\"),\n);\n// Its own chunk, fetched only if a restore is attempted with unsaved work —\n// which for a Cloud session (autosave on) is the uncommon case.\nconst RestoreVersionDialog = defineAsyncComponent(\n () => import(\"./RestoreVersionDialog.vue\"),\n);\n\n/**\n * Every action here swallows its rejection: the feature already reported it\n * through `onError` and rolled the canvas back, and an unhandled rejection out\n * of a DOM event binding helps nobody.\n */\nasync function handleRequestRestore(): Promise<void> {\n try {\n await props.feature.requestRestore();\n } catch {\n /* reported through onError */\n }\n}\n\nasync function handleSaveAndRestore(): Promise<void> {\n try {\n await props.feature.saveAndRestore();\n } catch {\n /* reported through onError */\n }\n}\n\nasync function handleDiscardAndRestore(): Promise<void> {\n try {\n await props.feature.discardAndRestore();\n } catch {\n /* reported through onError */\n }\n}\n</script>\n\n<template>\n <VersionPreviewBanner\n v-if=\"feature.isPreviewing.value\"\n :visible=\"feature.isPreviewing.value\"\n :can-restore=\"feature.canRestore.value\"\n @cancel=\"feature.cancelPreview()\"\n @confirm=\"handleRequestRestore\"\n />\n\n <RestoreVersionDialog\n v-if=\"feature.isConfirmingRestore.value\"\n :visible=\"feature.isConfirmingRestore.value\"\n :can-save=\"feature.canSaveBeforeRestore.value\"\n :is-busy=\"feature.isConfirmBusy.value\"\n @cancel=\"feature.cancelRestoreConfirm()\"\n @save-and-restore=\"handleSaveAndRestore\"\n @discard-and-restore=\"handleDiscardAndRestore\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Mount point for the version-history chrome that sits outside the header,\n * shared by the OSS and Cloud editors.\n *\n * Same shape as `SavedBlocksPanels.vue` / `TestEmailPanel.vue`: everything here\n * is `defineAsyncComponent` behind a `v-if` on its own state, and the editors in\n * turn lazy-load *this* wrapper and render it only when a\n * `VersionHistoryProvider` is configured — so a consumer without one downloads\n * none of it.\n *\n * The header's dropdown control is not here for one reason only: it has to sit\n * in the header's centre column. It is lazily imported at those two sites\n * instead, and covered by the same CDN chunk guard.\n */\nimport { defineAsyncComponent } from \"vue\";\nimport type { UseVersionHistoryFeatureReturn } from \"../composables/useVersionHistoryFeature\";\n\nconst props = defineProps<{\n feature: UseVersionHistoryFeatureReturn;\n}>();\n\nconst VersionPreviewBanner = defineAsyncComponent(\n () => import(\"./VersionPreviewBanner.vue\"),\n);\n// Its own chunk, fetched only if a restore is attempted with unsaved work —\n// which for a Cloud session (autosave on) is the uncommon case.\nconst RestoreVersionDialog = defineAsyncComponent(\n () => import(\"./RestoreVersionDialog.vue\"),\n);\n\n/**\n * Every action here swallows its rejection: the feature already reported it\n * through `onError` and rolled the canvas back, and an unhandled rejection out\n * of a DOM event binding helps nobody.\n */\nasync function handleRequestRestore(): Promise<void> {\n try {\n await props.feature.requestRestore();\n } catch {\n /* reported through onError */\n }\n}\n\nasync function handleSaveAndRestore(): Promise<void> {\n try {\n await props.feature.saveAndRestore();\n } catch {\n /* reported through onError */\n }\n}\n\nasync function handleDiscardAndRestore(): Promise<void> {\n try {\n await props.feature.discardAndRestore();\n } catch {\n /* reported through onError */\n }\n}\n</script>\n\n<template>\n <VersionPreviewBanner\n v-if=\"feature.isPreviewing.value\"\n :visible=\"feature.isPreviewing.value\"\n :can-restore=\"feature.canRestore.value\"\n @cancel=\"feature.cancelPreview()\"\n @confirm=\"handleRequestRestore\"\n />\n\n <RestoreVersionDialog\n v-if=\"feature.isConfirmingRestore.value\"\n :visible=\"feature.isConfirmingRestore.value\"\n :can-save=\"feature.canSaveBeforeRestore.value\"\n :is-busy=\"feature.isConfirmBusy.value\"\n @cancel=\"feature.cancelRestoreConfirm()\"\n @save-and-restore=\"handleSaveAndRestore\"\n @discard-and-restore=\"handleDiscardAndRestore\"\n />\n</template>\n"],"mappings":";;;;;;;EAkBA,IAAM,IAAQ,GAIR,IAAuB,QACrB,OAAO,qCACf,GAGM,IAAuB,QACrB,OAAO,qCACf;EAOA,eAAe,IAAsC;GACnD,IAAI;IACF,MAAM,EAAM,QAAQ,eAAe;GACrC,QAAQ,CAER;EACF;EAEA,eAAe,IAAsC;GACnD,IAAI;IACF,MAAM,EAAM,QAAQ,eAAe;GACrC,QAAQ,CAER;EACF;EAEA,eAAe,IAAyC;GACtD,IAAI;IACF,MAAM,EAAM,QAAQ,kBAAkB;GACxC,QAAQ,CAER;EACF;oBAKU,EAAA,GAAA,EAAA,GAAA,MAAA,CAAA,EAAA,QAAQ,aAAa,SAD7B,EAAA,GAAA,EAME,EAAA,CAAA,GAAA;;GAJC,SAAS,EAAA,QAAQ,aAAa;GAC9B,eAAa,EAAA,QAAQ,WAAW;GAChC,UAAM,AAAA,EAAA,QAAA,MAAE,EAAA,QAAQ,cAAa;GAC7B,WAAS;EAIJ,GAAA,MAAA,GAAA,CAAA,WAAA,aAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAA,QAAQ,oBAAoB,SADpC,EAAA,GAAA,EAQE,EAAA,CAAA,GAAA;;GANC,SAAS,EAAA,QAAQ,oBAAoB;GACrC,YAAU,EAAA,QAAQ,qBAAqB;GACvC,WAAS,EAAA,QAAQ,cAAc;GAC/B,UAAM,AAAA,EAAA,QAAA,MAAE,EAAA,QAAQ,qBAAoB;GACpC,kBAAkB;GAClB,qBAAqB"}
@@ -1,6 +1,6 @@
1
1
  import { N as e, S as t, at as n, b as r, ct as i, g as a, h as o, p as s, ut as c } from "./draggable-BfpsXFg7.js";
2
2
  import { t as l } from "./useI18n-4sUbTM3Y.js";
3
- import { kt as u } from "./icons-C36Ha5VU.js";
3
+ import { kt as u } from "./icons-Dl5bcXmT.js";
4
4
  import { f as d, v as f } from "./styleConstants-9oK5kn21.js";
5
5
  //#region src/components/VersionPreviewBanner.vue?vue&type=script&setup=true&lang.ts
6
6
  var p = {
@@ -37,4 +37,4 @@ var p = {
37
37
  //#endregion
38
38
  export { g as default };
39
39
 
40
- //# sourceMappingURL=VersionPreviewBanner-Dw4kFkrh.js.map
40
+ //# sourceMappingURL=VersionPreviewBanner-CBVDWnhq.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VersionPreviewBanner-Dw4kFkrh.js","names":[],"sources":["../../../src/components/VersionPreviewBanner.vue","../../../src/components/VersionPreviewBanner.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ghostBtnClass, primaryBtnClass } from \"../constants/styleConstants\";\n/**\n * Shown while a past version is on the canvas instead of the user's own work.\n * Cancel puts the pre-preview content back; Restore makes the version current.\n *\n * Lives outside `src/cloud/` because version history is a BYO provider, not a\n * Cloud feature — a consumer's own `versionHistory` provider drives this banner\n * with no Cloud involved.\n */\nimport { Clock } from \"@lucide/vue\";\nimport { useI18n } from \"../composables/useI18n\";\n\ndefineProps<{\n visible: boolean;\n /**\n * Whether the provider supplied `restore`. When it didn't, history is\n * browse-and-preview only, so the confirm action does not render at all\n * rather than rendering disabled — the same discipline saved blocks uses.\n */\n canRestore: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"cancel\"): void;\n (e: \"confirm\"): void;\n}>();\n\nconst { t } = useI18n();\n</script>\n\n<template>\n <div\n v-if=\"visible\"\n class=\"tpl-preview-banner tpl:absolute tpl:top-14 tpl:right-0 tpl:left-0 tpl:z-40 tpl:flex tpl:items-center tpl:justify-center tpl:gap-4 tpl:px-4 tpl:py-3 tpl:bg-[var(--tpl-primary-light)] tpl:border-b tpl:border-[var(--tpl-primary)]\"\n data-testid=\"version-preview-banner\"\n role=\"status\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:text-sm tpl:text-[var(--tpl-text)]\"\n >\n <Clock\n :size=\"18\"\n :stroke-width=\"2\"\n class=\"tpl:text-[var(--tpl-primary)]\"\n />\n <span>{{ t.versionPreview.message }}</span>\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <button\n :class=\"ghostBtnClass\"\n style=\"background-color: transparent\"\n data-testid=\"version-preview-cancel\"\n @click=\"emit('cancel')\"\n >\n {{ t.versionPreview.cancel }}\n </button>\n <button\n v-if=\"canRestore\"\n :class=\"primaryBtnClass\"\n data-testid=\"version-preview-restore\"\n @click=\"emit('confirm')\"\n >\n {{ t.versionPreview.restore }}\n </button>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ghostBtnClass, primaryBtnClass } from \"../constants/styleConstants\";\n/**\n * Shown while a past version is on the canvas instead of the user's own work.\n * Cancel puts the pre-preview content back; Restore makes the version current.\n *\n * Lives outside `src/cloud/` because version history is a BYO provider, not a\n * Cloud feature — a consumer's own `versionHistory` provider drives this banner\n * with no Cloud involved.\n */\nimport { Clock } from \"@lucide/vue\";\nimport { useI18n } from \"../composables/useI18n\";\n\ndefineProps<{\n visible: boolean;\n /**\n * Whether the provider supplied `restore`. When it didn't, history is\n * browse-and-preview only, so the confirm action does not render at all\n * rather than rendering disabled — the same discipline saved blocks uses.\n */\n canRestore: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"cancel\"): void;\n (e: \"confirm\"): void;\n}>();\n\nconst { t } = useI18n();\n</script>\n\n<template>\n <div\n v-if=\"visible\"\n class=\"tpl-preview-banner tpl:absolute tpl:top-14 tpl:right-0 tpl:left-0 tpl:z-40 tpl:flex tpl:items-center tpl:justify-center tpl:gap-4 tpl:px-4 tpl:py-3 tpl:bg-[var(--tpl-primary-light)] tpl:border-b tpl:border-[var(--tpl-primary)]\"\n data-testid=\"version-preview-banner\"\n role=\"status\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:text-sm tpl:text-[var(--tpl-text)]\"\n >\n <Clock\n :size=\"18\"\n :stroke-width=\"2\"\n class=\"tpl:text-[var(--tpl-primary)]\"\n />\n <span>{{ t.versionPreview.message }}</span>\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <button\n :class=\"ghostBtnClass\"\n style=\"background-color: transparent\"\n data-testid=\"version-preview-cancel\"\n @click=\"emit('cancel')\"\n >\n {{ t.versionPreview.cancel }}\n </button>\n <button\n v-if=\"canRestore\"\n :class=\"primaryBtnClass\"\n data-testid=\"version-preview-restore\"\n @click=\"emit('confirm')\"\n >\n {{ t.versionPreview.restore }}\n </button>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAuBA,IAAM,IAAO,GAKP,EAAE,SAAM,EAAQ;mBAKZ,EAAA,WADR,EAAA,GAAA,EAkCM,OAlCN,GAkCM,CA5BJ,EASM,OATN,GASM,CANJ,EAIE,EAAA,CAAA,GAAA;GAHC,MAAM;GACN,gBAAc;GACf,OAAM;EAER,CAAA,GAAA,EAA2C,QAAA,MAAA,EAAlC,EAAA,CAAA,CAAC,CAAC,eAAe,OAAO,GAAA,CAAA,CAAA,CAAA,GAEnC,EAiBM,OAjBN,GAiBM,CAhBJ,EAOS,UAAA;GANN,OAAK,EAAE,EAAA,CAAA,CAAa;GACrB,OAAA,EAAA,oBAAA,cAAA;GACA,eAAY;GACX,SAAK,AAAA,EAAA,QAAA,MAAE,EAAI,QAAA;EAET,GAAA,EAAA,EAAA,CAAA,CAAC,CAAC,eAAe,MAAM,GAAA,CAAA,GAGpB,EAAA,cADR,EAAA,GAAA,EAOS,UAAA;;GALN,OAAK,EAAE,EAAA,CAAA,CAAe;GACvB,eAAY;GACX,SAAK,AAAA,EAAA,QAAA,MAAE,EAAI,SAAA;EAET,GAAA,EAAA,EAAA,CAAA,CAAC,CAAC,eAAe,OAAO,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
1
+ {"version":3,"file":"VersionPreviewBanner-CBVDWnhq.js","names":[],"sources":["../../../src/components/VersionPreviewBanner.vue","../../../src/components/VersionPreviewBanner.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ghostBtnClass, primaryBtnClass } from \"../constants/styleConstants\";\n/**\n * Shown while a past version is on the canvas instead of the user's own work.\n * Cancel puts the pre-preview content back; Restore makes the version current.\n *\n * Lives outside `src/cloud/` because version history is a BYO provider, not a\n * Cloud feature — a consumer's own `versionHistory` provider drives this banner\n * with no Cloud involved.\n */\nimport { Clock } from \"@lucide/vue\";\nimport { useI18n } from \"../composables/useI18n\";\n\ndefineProps<{\n visible: boolean;\n /**\n * Whether the provider supplied `restore`. When it didn't, history is\n * browse-and-preview only, so the confirm action does not render at all\n * rather than rendering disabled — the same discipline saved blocks uses.\n */\n canRestore: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"cancel\"): void;\n (e: \"confirm\"): void;\n}>();\n\nconst { t } = useI18n();\n</script>\n\n<template>\n <div\n v-if=\"visible\"\n class=\"tpl-preview-banner tpl:absolute tpl:top-14 tpl:right-0 tpl:left-0 tpl:z-40 tpl:flex tpl:items-center tpl:justify-center tpl:gap-4 tpl:px-4 tpl:py-3 tpl:bg-[var(--tpl-primary-light)] tpl:border-b tpl:border-[var(--tpl-primary)]\"\n data-testid=\"version-preview-banner\"\n role=\"status\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:text-sm tpl:text-[var(--tpl-text)]\"\n >\n <Clock\n :size=\"18\"\n :stroke-width=\"2\"\n class=\"tpl:text-[var(--tpl-primary)]\"\n />\n <span>{{ t.versionPreview.message }}</span>\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <button\n :class=\"ghostBtnClass\"\n style=\"background-color: transparent\"\n data-testid=\"version-preview-cancel\"\n @click=\"emit('cancel')\"\n >\n {{ t.versionPreview.cancel }}\n </button>\n <button\n v-if=\"canRestore\"\n :class=\"primaryBtnClass\"\n data-testid=\"version-preview-restore\"\n @click=\"emit('confirm')\"\n >\n {{ t.versionPreview.restore }}\n </button>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ghostBtnClass, primaryBtnClass } from \"../constants/styleConstants\";\n/**\n * Shown while a past version is on the canvas instead of the user's own work.\n * Cancel puts the pre-preview content back; Restore makes the version current.\n *\n * Lives outside `src/cloud/` because version history is a BYO provider, not a\n * Cloud feature — a consumer's own `versionHistory` provider drives this banner\n * with no Cloud involved.\n */\nimport { Clock } from \"@lucide/vue\";\nimport { useI18n } from \"../composables/useI18n\";\n\ndefineProps<{\n visible: boolean;\n /**\n * Whether the provider supplied `restore`. When it didn't, history is\n * browse-and-preview only, so the confirm action does not render at all\n * rather than rendering disabled — the same discipline saved blocks uses.\n */\n canRestore: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"cancel\"): void;\n (e: \"confirm\"): void;\n}>();\n\nconst { t } = useI18n();\n</script>\n\n<template>\n <div\n v-if=\"visible\"\n class=\"tpl-preview-banner tpl:absolute tpl:top-14 tpl:right-0 tpl:left-0 tpl:z-40 tpl:flex tpl:items-center tpl:justify-center tpl:gap-4 tpl:px-4 tpl:py-3 tpl:bg-[var(--tpl-primary-light)] tpl:border-b tpl:border-[var(--tpl-primary)]\"\n data-testid=\"version-preview-banner\"\n role=\"status\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:text-sm tpl:text-[var(--tpl-text)]\"\n >\n <Clock\n :size=\"18\"\n :stroke-width=\"2\"\n class=\"tpl:text-[var(--tpl-primary)]\"\n />\n <span>{{ t.versionPreview.message }}</span>\n </div>\n <div class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <button\n :class=\"ghostBtnClass\"\n style=\"background-color: transparent\"\n data-testid=\"version-preview-cancel\"\n @click=\"emit('cancel')\"\n >\n {{ t.versionPreview.cancel }}\n </button>\n <button\n v-if=\"canRestore\"\n :class=\"primaryBtnClass\"\n data-testid=\"version-preview-restore\"\n @click=\"emit('confirm')\"\n >\n {{ t.versionPreview.restore }}\n </button>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAuBA,IAAM,IAAO,GAKP,EAAE,SAAM,EAAQ;mBAKZ,EAAA,WADR,EAAA,GAAA,EAkCM,OAlCN,GAkCM,CA5BJ,EASM,OATN,GASM,CANJ,EAIE,EAAA,CAAA,GAAA;GAHC,MAAM;GACN,gBAAc;GACf,OAAM;EAER,CAAA,GAAA,EAA2C,QAAA,MAAA,EAAlC,EAAA,CAAA,CAAC,CAAC,eAAe,OAAO,GAAA,CAAA,CAAA,CAAA,GAEnC,EAiBM,OAjBN,GAiBM,CAhBJ,EAOS,UAAA;GANN,OAAK,EAAE,EAAA,CAAA,CAAa;GACrB,OAAA,EAAA,oBAAA,cAAA;GACA,eAAY;GACX,SAAK,AAAA,EAAA,QAAA,MAAE,EAAI,QAAA;EAET,GAAA,EAAA,EAAA,CAAA,CAAC,CAAC,eAAe,MAAM,GAAA,CAAA,GAGpB,EAAA,cADR,EAAA,GAAA,EAOS,UAAA;;GALN,OAAK,EAAE,EAAA,CAAA,CAAe;GACvB,eAAY;GACX,SAAK,AAAA,EAAA,QAAA,MAAE,EAAI,SAAA;EAET,GAAA,EAAA,EAAA,CAAA,CAAC,CAAC,eAAe,OAAO,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
@@ -1,4 +1,4 @@
1
- import { A as e, Dt as t, G as n, Ot as r, V as i, W as a, X as o, Z as s, et as c, f as l, ft as u, mt as d, v as f } from "./icons-C36Ha5VU.js";
1
+ import { A as e, Dt as t, G as n, Ot as r, V as i, W as a, X as o, Z as s, et as c, f as l, ft as u, mt as d, v as f } from "./icons-Dl5bcXmT.js";
2
2
  //#region src/utils/blockTypeIcons.ts
3
3
  var p = {
4
4
  section: t,
@@ -18,4 +18,4 @@ var p = {
18
18
  //#endregion
19
19
  export { p as t };
20
20
 
21
- //# sourceMappingURL=blockTypeIcons-hX_W4dqo.js.map
21
+ //# sourceMappingURL=blockTypeIcons-A9qFb1cR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"blockTypeIcons-hX_W4dqo.js","names":[],"sources":["../../../src/utils/blockTypeIcons.ts"],"sourcesContent":["import {\n Code,\n Columns3,\n Heading,\n Image,\n Minus,\n MoveVertical,\n Navigation,\n Pilcrow,\n Play,\n RectangleHorizontal,\n Share2,\n Table,\n Timer,\n} from \"@lucide/vue\";\nimport type { Component } from \"vue\";\n\nexport const blockTypeIcons: Record<string, Component> = {\n section: Columns3,\n title: Heading,\n paragraph: Pilcrow,\n image: Image,\n button: RectangleHorizontal,\n divider: Minus,\n video: Play,\n social: Share2,\n menu: Navigation,\n table: Table,\n spacer: MoveVertical,\n countdown: Timer,\n html: Code,\n};\n"],"mappings":";;AAiBA,IAAa,IAA4C;CACvD,SAAS;CACT,OAAO;CACP,WAAW;CACX,OAAO;CACP,QAAQ;CACR,SAAS;CACT,OAAO;CACP,QAAQ;CACR,MAAM;CACN,OAAO;CACP,QAAQ;CACR,WAAW;CACX,MAAM;AACR"}
1
+ {"version":3,"file":"blockTypeIcons-A9qFb1cR.js","names":[],"sources":["../../../src/utils/blockTypeIcons.ts"],"sourcesContent":["import {\n Code,\n Columns3,\n Heading,\n Image,\n Minus,\n MoveVertical,\n Navigation,\n Pilcrow,\n Play,\n RectangleHorizontal,\n Share2,\n Table,\n Timer,\n} from \"@lucide/vue\";\nimport type { Component } from \"vue\";\n\nexport const blockTypeIcons: Record<string, Component> = {\n section: Columns3,\n title: Heading,\n paragraph: Pilcrow,\n image: Image,\n button: RectangleHorizontal,\n divider: Minus,\n video: Play,\n social: Share2,\n menu: Navigation,\n table: Table,\n spacer: MoveVertical,\n countdown: Timer,\n html: Code,\n};\n"],"mappings":";;AAiBA,IAAa,IAA4C;CACvD,SAAS;CACT,OAAO;CACP,WAAW;CACX,OAAO;CACP,QAAQ;CACR,SAAS;CACT,OAAO;CACP,QAAQ;CACR,MAAM;CACN,OAAO;CACP,QAAQ;CACR,WAAW;CACX,MAAM;AACR"}
@@ -53,7 +53,7 @@ function E(e) {
53
53
  let t = f(e);
54
54
  if (t) return s?.(t), null;
55
55
  try {
56
- let { MediaApiClient: t } = await import("./src-CoHDh8Ua.js");
56
+ let { MediaApiClient: t } = await import("./src-BDUi-9js.js");
57
57
  return l(await new t(a).uploadMedia(e));
58
58
  } catch (e) {
59
59
  return s?.(e), null;
@@ -341,4 +341,4 @@ async function k(r) {
341
341
  //#endregion
342
342
  export { k as bootstrapCloud };
343
343
 
344
- //# sourceMappingURL=createCloudRuntime-D75oJ9j-.js.map
344
+ //# sourceMappingURL=createCloudRuntime-DYDf_-rN.js.map