@templatical/editor 0.20.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/README.md +1 -0
  2. package/dist/{AiChatSidebar-ChrE6pUq.js → AiChatSidebar-K_AehWc-.js} +9 -9
  3. package/dist/{AiFeatureMenu-DkQ9HhQ6.js → AiFeatureMenu-CcqQDHzJ.js} +6 -6
  4. package/dist/{BlockIssueBadge-B4QjePax.js → BlockIssueBadge-Dmj9rVra.js} +4 -4
  5. package/dist/{CloudEditor-CfX-aMiV.js → CloudEditor-Dnww6og-.js} +263 -315
  6. package/dist/{CollaboratorBar-DTibhQ1j.js → CollaboratorBar-Bj4NZiie.js} +3 -3
  7. package/dist/{ColorPicker-4vDYhdGe.js → ColorPicker-s9GHXjZs.js} +4 -4
  8. package/dist/CommentsSidebar-DvNEdugN.js +435 -0
  9. package/dist/CountdownBlock-J_Q9JRQM.js +91 -0
  10. package/dist/{CountdownToolbar-D7yQqnA2.js → CountdownToolbar-DPRcv3Fu.js} +3 -4
  11. package/dist/{DesignReferenceSidebar-DnO6ZdwS.js → DesignReferenceSidebar-DNmK3dxp.js} +8 -8
  12. package/dist/{IssuesPanel-X_vkNGrs.js → IssuesPanel-CEnEGFtd.js} +7 -7
  13. package/dist/{MergeTagSuggestion-DCuaSOPQ.js → MergeTagSuggestion-DMe4rqn0.js} +2 -2
  14. package/dist/NumberWithSuffix-CCPN_oCh.js +121 -0
  15. package/dist/{ParagraphEditor-C5ixOIYb.js → ParagraphEditor--_zWfxps.js} +47 -47
  16. package/dist/{RichTextEditorContent-DwhDnMsG.js → RichTextEditorContent-FbnWsh46.js} +6 -6
  17. package/dist/SaveBlockDialog-CYIEHABH.js +264 -0
  18. package/dist/SavedBlockPreviewCanvas-2-mzAnZE.js +109 -0
  19. package/dist/SavedBlocksBrowserModal-D5V5yF_3.js +323 -0
  20. package/dist/SavedBlocksPanels-Dff38YXu.js +36 -0
  21. package/dist/SavedBlocksPickBar-rB6iyji6.js +52 -0
  22. package/dist/{SnapshotHistory-DaVueFv6.js → SnapshotHistory-FtzDq8f0.js} +8 -8
  23. package/dist/{TemplateScoringPanel-B0UHoTLx.js → TemplateScoringPanel-ifGGGWs5.js} +14 -14
  24. package/dist/{TestEmailModal-BkauxF7j.js → TestEmailModal-DL2O1H8M.js} +4 -4
  25. package/dist/{TitleEditor-n6WDVDjW.js → TitleEditor-CPda5lh-.js} +11 -11
  26. package/dist/{TplModal-BDDyvT-C.js → TplModal-C7Koj5gM.js} +3 -3
  27. package/dist/{blockTypeIcons-4D0aFXNg.js → blockTypeIcons-CgwECCut.js} +6 -6
  28. package/dist/bundle-stats.json +8 -8
  29. package/dist/{cdn/chunks/ca-DbWoy4rG.js → ca-BBgad6y5.js} +50 -5
  30. package/dist/cdn/chunks/AiChatSidebar-A1CuWGY0.js +203 -0
  31. package/dist/cdn/chunks/AiChatSidebar-A1CuWGY0.js.map +1 -0
  32. package/dist/cdn/chunks/{AiFeatureMenu-CIBHAGSz.js → AiFeatureMenu-Duwg413F.js} +12 -8
  33. package/dist/cdn/chunks/{AiFeatureMenu-CIBHAGSz.js.map → AiFeatureMenu-Duwg413F.js.map} +1 -1
  34. package/dist/cdn/chunks/{BlockIssueBadge-CxMiLo3p.js → BlockIssueBadge-Da4yR-mh.js} +7 -5
  35. package/dist/cdn/chunks/{BlockIssueBadge-CxMiLo3p.js.map → BlockIssueBadge-Da4yR-mh.js.map} +1 -1
  36. package/dist/cdn/chunks/{CloudEditor-CEa3Xgqh.js → CloudEditor-B3hqbwfP.js} +275 -318
  37. package/dist/cdn/chunks/CloudEditor-B3hqbwfP.js.map +1 -0
  38. package/dist/cdn/chunks/{CollaboratorBar-Bk1gD02G.js → CollaboratorBar-BS3rJy6-.js} +7 -6
  39. package/dist/cdn/chunks/{CollaboratorBar-Bk1gD02G.js.map → CollaboratorBar-BS3rJy6-.js.map} +1 -1
  40. package/dist/cdn/chunks/{ColorPicker-ll8pynws.js → ColorPicker-DZSzZ5ZP.js} +168 -164
  41. package/dist/cdn/chunks/{ColorPicker-ll8pynws.js.map → ColorPicker-DZSzZ5ZP.js.map} +1 -1
  42. package/dist/cdn/chunks/CommentsSidebar-DHdRiGPX.js +412 -0
  43. package/dist/cdn/chunks/CommentsSidebar-DHdRiGPX.js.map +1 -0
  44. package/dist/cdn/chunks/CountdownBlock-Bffpoppw.js +93 -0
  45. package/dist/cdn/chunks/{CountdownBlock-eGUE7hhw.js.map → CountdownBlock-Bffpoppw.js.map} +1 -1
  46. package/dist/cdn/chunks/{CountdownToolbar-C1bkSjUR.js → CountdownToolbar-DAnmIZjq.js} +4 -5
  47. package/dist/cdn/chunks/{CountdownToolbar-C1bkSjUR.js.map → CountdownToolbar-DAnmIZjq.js.map} +1 -1
  48. package/dist/cdn/chunks/DesignReferenceSidebar-Dre99DTH.js +223 -0
  49. package/dist/cdn/chunks/DesignReferenceSidebar-Dre99DTH.js.map +1 -0
  50. package/dist/cdn/chunks/{IssuesPanel-Csasylf_.js → IssuesPanel-D80JedOj.js} +11 -10
  51. package/dist/cdn/chunks/{IssuesPanel-Csasylf_.js.map → IssuesPanel-D80JedOj.js.map} +1 -1
  52. package/dist/cdn/chunks/LoadingTrack-D-CW2tUa.js +12 -0
  53. package/dist/cdn/chunks/LoadingTrack-D-CW2tUa.js.map +1 -0
  54. package/dist/cdn/chunks/{MergeTagSuggestion-BmMmdcRg.js → MergeTagSuggestion-D7TsECll.js} +2 -2
  55. package/dist/cdn/chunks/{MergeTagSuggestion-BmMmdcRg.js.map → MergeTagSuggestion-D7TsECll.js.map} +1 -1
  56. package/dist/cdn/chunks/NumberWithSuffix-CjlVNIEe.js +123 -0
  57. package/dist/cdn/chunks/NumberWithSuffix-CjlVNIEe.js.map +1 -0
  58. package/dist/cdn/chunks/{ParagraphEditor-v0_XEL-v.js → ParagraphEditor-CtaRa1vr.js} +90 -85
  59. package/dist/cdn/chunks/{ParagraphEditor-v0_XEL-v.js.map → ParagraphEditor-CtaRa1vr.js.map} +1 -1
  60. package/dist/cdn/chunks/{RichTextEditorContent-NQExNsaV.js → RichTextEditorContent-BbdgJqWM.js} +9 -6
  61. package/dist/cdn/chunks/{RichTextEditorContent-NQExNsaV.js.map → RichTextEditorContent-BbdgJqWM.js.map} +1 -1
  62. package/dist/cdn/chunks/SaveBlockDialog-Bb3fdUEZ.js +263 -0
  63. package/dist/cdn/chunks/SaveBlockDialog-Bb3fdUEZ.js.map +1 -0
  64. package/dist/cdn/chunks/SavedBlockPreviewCanvas-DZOMgNsz.js +111 -0
  65. package/dist/cdn/chunks/SavedBlockPreviewCanvas-DZOMgNsz.js.map +1 -0
  66. package/dist/cdn/chunks/SavedBlocksBrowserModal-CeUWcPv0.js +322 -0
  67. package/dist/cdn/chunks/SavedBlocksBrowserModal-CeUWcPv0.js.map +1 -0
  68. package/dist/cdn/chunks/SavedBlocksPanels-D-pA_wfk.js +38 -0
  69. package/dist/cdn/chunks/SavedBlocksPanels-D-pA_wfk.js.map +1 -0
  70. package/dist/cdn/chunks/SavedBlocksPickBar-1rf1KpqS.js +54 -0
  71. package/dist/cdn/chunks/SavedBlocksPickBar-1rf1KpqS.js.map +1 -0
  72. package/dist/cdn/chunks/SnapshotHistory-Bf1uovti.js +121 -0
  73. package/dist/cdn/chunks/SnapshotHistory-Bf1uovti.js.map +1 -0
  74. package/dist/cdn/chunks/TemplateScoringPanel-CTk8WwxU.js +231 -0
  75. package/dist/cdn/chunks/TemplateScoringPanel-CTk8WwxU.js.map +1 -0
  76. package/dist/cdn/chunks/TestEmailModal-BJTDxFHh.js +96 -0
  77. package/dist/cdn/chunks/TestEmailModal-BJTDxFHh.js.map +1 -0
  78. package/dist/cdn/chunks/{TitleEditor-CS-_MzYs.js → TitleEditor-BJ7LFykI.js} +18 -15
  79. package/dist/cdn/chunks/{TitleEditor-CS-_MzYs.js.map → TitleEditor-BJ7LFykI.js.map} +1 -1
  80. package/dist/cdn/chunks/TplModal-CH9RzKF7.js +50 -0
  81. package/dist/cdn/chunks/TplModal-CH9RzKF7.js.map +1 -0
  82. package/dist/cdn/chunks/_plugin-vue_export-helper-B3ysoDQm.js +8 -0
  83. package/dist/cdn/chunks/blockTypeIcons-etMMQoVv.js +21 -0
  84. package/dist/cdn/chunks/{blockTypeIcons-B0Hjh42a.js.map → blockTypeIcons-etMMQoVv.js.map} +1 -1
  85. package/dist/{ca-DbWoy4rG.js → cdn/chunks/ca-BBgad6y5.js} +52 -3
  86. package/dist/cdn/chunks/ca-BBgad6y5.js.map +1 -0
  87. package/dist/cdn/chunks/cloud-BJlbXGTJ.js +1787 -0
  88. package/dist/cdn/chunks/cloud-BJlbXGTJ.js.map +1 -0
  89. package/dist/{de-CTYXVU9v.js → cdn/chunks/de-Bw6fB5JU.js} +2 -24
  90. package/dist/cdn/chunks/{de-CTYXVU9v.js.map → de-Bw6fB5JU.js.map} +1 -1
  91. package/dist/cdn/chunks/{de-CgGOnerg.js → de-D7WbpFBR.js} +50 -3
  92. package/dist/cdn/chunks/de-D7WbpFBR.js.map +1 -0
  93. package/dist/cdn/chunks/dist-CiBEt0VR.js +163 -0
  94. package/dist/cdn/chunks/dist-CiBEt0VR.js.map +1 -0
  95. package/dist/cdn/chunks/dist-CxTt8FRE.js +403 -0
  96. package/dist/cdn/chunks/dist-CxTt8FRE.js.map +1 -0
  97. package/dist/{en-DrUV9xth.js → cdn/chunks/en-BrZ0uGK2.js} +51 -2
  98. package/dist/cdn/chunks/en-BrZ0uGK2.js.map +1 -0
  99. package/dist/{en-BtmIaJeb.js → cdn/chunks/en-DAdHJz7h.js} +2 -24
  100. package/dist/cdn/chunks/{en-BtmIaJeb.js.map → en-DAdHJz7h.js.map} +1 -1
  101. package/dist/{es-DwbKjU7q.js → cdn/chunks/es-tLSLysPs.js} +51 -2
  102. package/dist/cdn/chunks/es-tLSLysPs.js.map +1 -0
  103. package/dist/cdn/chunks/{extensions-Di3hdIRT.js → extensions-ZX2oarW6.js} +28 -26
  104. package/dist/cdn/chunks/{extensions-Di3hdIRT.js.map → extensions-ZX2oarW6.js.map} +1 -1
  105. package/dist/cdn/chunks/formatRelativeTime-CtUU-QZ8.js +12 -0
  106. package/dist/cdn/chunks/formatRelativeTime-CtUU-QZ8.js.map +1 -0
  107. package/dist/cdn/chunks/htmlparser-CZa2V5cF.js +1008 -0
  108. package/dist/cdn/chunks/htmlparser-CZa2V5cF.js.map +1 -0
  109. package/dist/cdn/chunks/icons-CYWw8Xfp.js +1190 -0
  110. package/dist/cdn/chunks/icons-CYWw8Xfp.js.map +1 -0
  111. package/dist/cdn/chunks/keys-D7kUmfpE.js +12 -0
  112. package/dist/cdn/chunks/keys-D7kUmfpE.js.map +1 -0
  113. package/dist/cdn/chunks/{pt-BR-Bcc5Tjed.js → pt-BR-BWFokdTU.js} +50 -3
  114. package/dist/cdn/chunks/pt-BR-BWFokdTU.js.map +1 -0
  115. package/dist/{pt-BR-B2ZvFlRL.js → cdn/chunks/pt-BR-w2sGzHNX.js} +2 -24
  116. package/dist/cdn/chunks/{pt-BR-B2ZvFlRL.js.map → pt-BR-w2sGzHNX.js.map} +1 -1
  117. package/dist/cdn/chunks/src-BKI1x1k7.js +546 -0
  118. package/dist/cdn/chunks/src-BKI1x1k7.js.map +1 -0
  119. package/dist/cdn/chunks/src-CM0gCvAS.js +1176 -0
  120. package/dist/cdn/chunks/src-CM0gCvAS.js.map +1 -0
  121. package/dist/cdn/chunks/{media-library-yYAkAagU.js → src-D6F_3XkE.js} +1754 -1252
  122. package/dist/cdn/chunks/src-D6F_3XkE.js.map +1 -0
  123. package/dist/cdn/chunks/{renderer-DpBGiXOg.js → src-DYji-wXB.js} +117 -133
  124. package/dist/cdn/chunks/src-DYji-wXB.js.map +1 -0
  125. package/dist/cdn/chunks/{styles-DHSmjlpX.js → styles-DMOEiSX9.js} +1448 -1354
  126. package/dist/cdn/chunks/styles-DMOEiSX9.js.map +1 -0
  127. package/dist/cdn/chunks/timeouts-Bmi_yePw.js +6 -0
  128. package/dist/cdn/chunks/timeouts-Bmi_yePw.js.map +1 -0
  129. package/dist/cdn/chunks/{tiptap-C2indasq.js → tiptap-BMZ-OENR.js} +2012 -1863
  130. package/dist/cdn/chunks/tiptap-BMZ-OENR.js.map +1 -0
  131. package/dist/cdn/chunks/useAliveFlag-aanU8uqB.js +12 -0
  132. package/dist/cdn/chunks/useAliveFlag-aanU8uqB.js.map +1 -0
  133. package/dist/cdn/chunks/useCloudI18n-BjNENqkM.js +25 -0
  134. package/dist/cdn/chunks/useCloudI18n-BjNENqkM.js.map +1 -0
  135. package/dist/cdn/chunks/useEditorCore-BA6mspzD.js +3019 -0
  136. package/dist/cdn/chunks/useEditorCore-BA6mspzD.js.map +1 -0
  137. package/dist/cdn/chunks/useI18n-8Wd7G-cq.js +19 -0
  138. package/dist/cdn/chunks/useI18n-8Wd7G-cq.js.map +1 -0
  139. package/dist/cdn/chunks/useMergeTag-C7G31KV-.js +46 -0
  140. package/dist/cdn/chunks/useMergeTag-C7G31KV-.js.map +1 -0
  141. package/dist/cdn/chunks/usePopoverPosition-Bx0QewTv.js +61 -0
  142. package/dist/cdn/chunks/usePopoverPosition-Bx0QewTv.js.map +1 -0
  143. package/dist/cdn/editor.css +1 -1
  144. package/dist/cdn/editor.js +132 -120
  145. package/dist/cdn/editor.js.map +1 -1
  146. package/dist/{check-Bl4J_tYV.js → check-BpQDKiPz.js} +1 -1
  147. package/dist/{chevron-down-COEcl2iP.js → chevron-down-j8GrdTyz.js} +1 -1
  148. package/dist/chevron-up-BACyVhyC.js +7 -0
  149. package/dist/{circle-alert-CvHi5etc.js → circle-alert-CgtE46ND.js} +1 -1
  150. package/dist/{clock-CZZw62e8.js → clock-BzKLLW5L.js} +1 -1
  151. package/dist/{cloud-B-RebwxI.js → cloud-Du7mnkz2.js} +19 -47
  152. package/dist/{createLucideIcon-_peTZQtY.js → createLucideIcon-JWHwTI6N.js} +2 -2
  153. package/dist/{cdn/chunks/de-CTYXVU9v.js → de-Bw6fB5JU.js} +0 -26
  154. package/dist/{de-CgGOnerg.js → de-D7WbpFBR.js} +49 -2
  155. package/dist/{dist-CgTKuIUN.js → dist-BEpCh2mG.js} +1158 -1125
  156. package/dist/{dist-Cx7IUM7J.js → dist-BgPYC_8-.js} +14 -6
  157. package/dist/{dist-BKKo5wPC.js → dist-BkM8A17N.js} +2 -2
  158. package/dist/{dist-CcX5sLpz.js → dist-BuNDAAVp.js} +361 -256
  159. package/dist/{dist-COSN3oDJ.js → dist-CBzCU-a-.js} +2 -2
  160. package/dist/{dist-YSCPD13F.js → dist-CDO52Rxy.js} +2 -2
  161. package/dist/{dist-Dk5AdwoQ.js → dist-CrjzhIxB.js} +2 -2
  162. package/dist/{dist-DXAZUjj3.js → dist-CtcgoC_R.js} +2 -2
  163. package/dist/{dist-D6M5FAY7.js → dist-CuXha2_7.js} +2 -2
  164. package/dist/dist-CweLDZrs.js +5 -0
  165. package/dist/dist-DOsdqAEZ.js +5 -0
  166. package/dist/{dist-8TKf-Jpg.js → dist-DYClLqy8.js} +6 -3
  167. package/dist/{cdn/chunks/en-DrUV9xth.js → en-BrZ0uGK2.js} +49 -4
  168. package/dist/{cdn/chunks/en-BtmIaJeb.js → en-DAdHJz7h.js} +0 -26
  169. package/dist/{cdn/chunks/es-DwbKjU7q.js → es-tLSLysPs.js} +49 -4
  170. package/dist/{extensions-BCA9pyer.js → extensions-ClY5Sh7S.js} +5 -5
  171. package/dist/{image-up-D26rNdfX.js → image-up-CQdtq8ge.js} +1 -1
  172. package/dist/index.d.ts +81 -4
  173. package/dist/{info-CE3JSTqk.js → info-BUJBXoE6.js} +1 -1
  174. package/dist/{keys-DFaIbGR8.js → keys-CHPcp-Nz.js} +2 -2
  175. package/dist/{list-checks-BQsLrtBB.js → list-checks-BGHaCSD5.js} +1 -1
  176. package/dist/{loader-circle-s9Rh5lLd.js → loader-circle-C-Z6kgI6.js} +1 -1
  177. package/dist/{message-circle-CI62d690.js → message-circle-CEm5qckV.js} +1 -1
  178. package/dist/pencil-DdwmkKLb.js +10 -0
  179. package/dist/{pt-BR-Bcc5Tjed.js → pt-BR-BWFokdTU.js} +49 -2
  180. package/dist/{cdn/chunks/pt-BR-B2ZvFlRL.js → pt-BR-w2sGzHNX.js} +0 -26
  181. package/dist/{refresh-cw-DlYfl65Y.js → refresh-cw-maKlg0dl.js} +1 -1
  182. package/dist/{scan-line-CHadrYVb.js → scan-line-BFgesTOY.js} +1 -1
  183. package/dist/{send-CbP40otC.js → send-B70aQDrA.js} +1 -1
  184. package/dist/{shield-check-Bnj9aRoJ.js → shield-check-B7x5OKt5.js} +1 -1
  185. package/dist/{sparkles-CncWT57a.js → sparkles-DVlm1Ipp.js} +1 -1
  186. package/dist/style.css +1 -1
  187. package/dist/{styles-DkF_-uX8.js → styles-PcOPXvLO.js} +1235 -1151
  188. package/dist/templatical-editor.js +134 -125
  189. package/dist/{text-align-start-B458vzYw.js → text-align-start-Vay3Kvo2.js} +1 -1
  190. package/dist/{trash-2-DO0yjSU1.js → trash-2-DE8CmxAG.js} +1 -1
  191. package/dist/{triangle-alert-C18_ima6.js → triangle-alert-Djg6IG8N.js} +1 -1
  192. package/dist/{upload-DsCd2zTR.js → upload-BwwE0U6G.js} +1 -1
  193. package/dist/{useCloudI18n-PCDOC2kz.js → useCloudI18n-BmiygEM4.js} +1 -1
  194. package/dist/{useEditorCore-kKUemYY6.js → useEditorCore-CT1slufs.js} +997 -817
  195. package/dist/{useI18n-BNMzZTM5.js → useI18n-D2L9Mkik.js} +1 -1
  196. package/dist/{useMergeTag-DfEY0eK5.js → useMergeTag-BTdDq5DC.js} +1 -1
  197. package/dist/{usePopoverPosition-F9STHRIr.js → usePopoverPosition-BO2LNy5n.js} +1 -1
  198. package/dist/{x-BCFQuE_q.js → x-CkD6A1iB.js} +1 -1
  199. package/package.json +21 -21
  200. package/dist/CommentsSidebar-D-o5Stlg.js +0 -442
  201. package/dist/CountdownBlock-Bn5w7C-p.js +0 -92
  202. package/dist/ModuleBrowserModal-AJt--JPh.js +0 -202
  203. package/dist/ModulePreviewCanvas-BKYOcVCh.js +0 -106
  204. package/dist/NumberWithSuffix-Bf3rNxza.js +0 -89
  205. package/dist/SaveModuleDialog-B4QX9eiv.js +0 -125
  206. package/dist/ToggleSwitch-DUNuUPsZ.js +0 -37
  207. package/dist/cdn/chunks/CloudEditor-CEa3Xgqh.js.map +0 -1
  208. package/dist/cdn/chunks/CountdownBlock-eGUE7hhw.js +0 -93
  209. package/dist/cdn/chunks/ModuleBrowserModal-DznWWtBI.js +0 -198
  210. package/dist/cdn/chunks/ModuleBrowserModal-DznWWtBI.js.map +0 -1
  211. package/dist/cdn/chunks/ModulePreviewCanvas-D-h7fr87.js +0 -107
  212. package/dist/cdn/chunks/ModulePreviewCanvas-D-h7fr87.js.map +0 -1
  213. package/dist/cdn/chunks/NumberWithSuffix-Dt-0odUN.js +0 -91
  214. package/dist/cdn/chunks/NumberWithSuffix-Dt-0odUN.js.map +0 -1
  215. package/dist/cdn/chunks/SaveModuleDialog-BpFhTi-k.js +0 -120
  216. package/dist/cdn/chunks/SaveModuleDialog-BpFhTi-k.js.map +0 -1
  217. package/dist/cdn/chunks/ToggleSwitch-OrmX_w18.js +0 -39
  218. package/dist/cdn/chunks/ToggleSwitch-OrmX_w18.js.map +0 -1
  219. package/dist/cdn/chunks/blockTypeIcons-B0Hjh42a.js +0 -22
  220. package/dist/cdn/chunks/ca-DbWoy4rG.js.map +0 -1
  221. package/dist/cdn/chunks/de-CgGOnerg.js.map +0 -1
  222. package/dist/cdn/chunks/en-DrUV9xth.js.map +0 -1
  223. package/dist/cdn/chunks/es-DwbKjU7q.js.map +0 -1
  224. package/dist/cdn/chunks/features-CLIZ7Q-Y.js +0 -7657
  225. package/dist/cdn/chunks/features-CLIZ7Q-Y.js.map +0 -1
  226. package/dist/cdn/chunks/icons-GX40Qm2W.js +0 -690
  227. package/dist/cdn/chunks/icons-GX40Qm2W.js.map +0 -1
  228. package/dist/cdn/chunks/media-library-yYAkAagU.js.map +0 -1
  229. package/dist/cdn/chunks/pt-BR-Bcc5Tjed.js.map +0 -1
  230. package/dist/cdn/chunks/quality-DffYv9j5.js +0 -2180
  231. package/dist/cdn/chunks/quality-DffYv9j5.js.map +0 -1
  232. package/dist/cdn/chunks/renderer-DpBGiXOg.js.map +0 -1
  233. package/dist/cdn/chunks/src-9K6uFiuK.js +0 -509
  234. package/dist/cdn/chunks/src-9K6uFiuK.js.map +0 -1
  235. package/dist/cdn/chunks/styles-DHSmjlpX.js.map +0 -1
  236. package/dist/cdn/chunks/tiptap-C2indasq.js.map +0 -1
  237. package/dist/dist-BDVm2MrW.js +0 -5
  238. package/dist/dist-DbekZDmJ.js +0 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-BJlbXGTJ.js","names":[],"sources":["../../../../core/src/cloud/auth.ts","../../../../core/src/cloud/url-builder.ts","../../../../core/src/cloud/api.ts","../../../../core/src/cloud/websocket-client.ts","../../../../core/src/cloud/mcp-operation-handler.ts","../../../../core/src/cloud/editor.ts","../../../../core/src/cloud/ai-chat.ts","../../../../core/src/cloud/ai-config.ts","../../../../core/src/cloud/template-scoring.ts","../../../../core/src/cloud/design-reference.ts","../../../../core/src/cloud/comments.ts","../../../../core/src/cloud/comment-listener.ts","../../../../core/src/cloud/collaboration.ts","../../../../core/src/cloud/collaboration-broadcast.ts","../../../../core/src/cloud/web-socket.ts","../../../../core/src/cloud/saved-blocks-provider.ts","../../../../core/src/cloud/snapshots.ts","../../../../core/src/cloud/test-email.ts","../../../../core/src/cloud/export.ts","../../../../core/src/cloud/plan-config.ts","../../../../core/src/cloud/health-check.ts","../../../../core/src/cloud/mcp-listener.ts"],"sourcesContent":["import type {\n AuthConfig,\n AuthRequestOptions,\n SdkAuthConfig,\n TestEmailConfig,\n TokenData,\n UserConfig,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\n\nexport type {\n AuthConfig,\n AuthRequestOptions,\n SdkAuthConfig,\n TestEmailConfig,\n UserConfig,\n};\n\nexport class AuthManager {\n private static readonly DEFAULT_BASE_URL = \"https://templatical.com\";\n\n private accessToken: string | null = null;\n private expiresAt: Date | null = null;\n private _projectId: string | null = null;\n private _tenantId: string | null = null;\n private _tenantSlug: string | null = null;\n private _testEmailConfig: TestEmailConfig | null = null;\n private _userConfig: UserConfig | null = null;\n private readonly url: string;\n private readonly baseUrl: string;\n private readonly requestOptions: AuthRequestOptions;\n private readonly onError?: (error: Error) => void;\n private refreshPromise: Promise<string> | null = null;\n\n private static readonly REFRESH_THRESHOLD_MS = 60 * 1000;\n\n constructor(config: AuthConfig) {\n this.url = config.url;\n this.baseUrl = (config.baseUrl ?? AuthManager.DEFAULT_BASE_URL).replace(\n /\\/$/,\n \"\",\n );\n this.requestOptions = config.requestOptions ?? {};\n this.onError = config.onError;\n }\n\n resolveUrl(path: string): string {\n if (path.startsWith(\"http://\") || path.startsWith(\"https://\")) {\n return path;\n }\n\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${this.baseUrl}${normalizedPath}`;\n }\n\n get projectId(): string {\n if (!this._projectId) {\n throw new Error(\"Project ID not available. Call initialize() first.\");\n }\n return this._projectId;\n }\n\n get tenantId(): string {\n if (!this._tenantId) {\n throw new Error(\"Tenant ID not available. Call initialize() first.\");\n }\n return this._tenantId;\n }\n\n get tenantSlug(): string {\n if (!this._tenantSlug) {\n throw new Error(\"Tenant slug not available. Call initialize() first.\");\n }\n return this._tenantSlug;\n }\n\n get testEmailConfig(): TestEmailConfig | null {\n return this._testEmailConfig;\n }\n\n get userConfig(): UserConfig | null {\n return this._userConfig;\n }\n\n get accessTokenValue(): string | null {\n return this.accessToken;\n }\n\n async initialize(): Promise<void> {\n await this.ensureToken();\n }\n\n private async ensureToken(): Promise<string> {\n if (this.accessToken && !this.isTokenExpiringSoon()) {\n return this.accessToken;\n }\n return this.refreshToken();\n }\n\n private isTokenExpiringSoon(): boolean {\n if (!this.expiresAt) {\n return true;\n }\n const timeUntilExpiry = this.expiresAt.getTime() - Date.now();\n return timeUntilExpiry < AuthManager.REFRESH_THRESHOLD_MS;\n }\n\n async refreshToken(): Promise<string> {\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.performRefresh();\n\n try {\n const token = await this.refreshPromise;\n return token;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async performRefresh(): Promise<string> {\n try {\n const method = this.requestOptions.method ?? \"POST\";\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...this.requestOptions.headers,\n };\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n credentials: this.requestOptions.credentials ?? \"include\",\n };\n\n if (method === \"POST\" && this.requestOptions.body) {\n headers[\"Content-Type\"] = \"application/json\";\n fetchOptions.body = JSON.stringify(this.requestOptions.body);\n }\n\n const response = await fetch(this.url, fetchOptions);\n\n if (!response.ok) {\n throw new SdkError(\n `Token refresh failed: ${response.status}`,\n response.status,\n );\n }\n\n const data: TokenData = await response.json();\n\n if (!data.token || !data.expires_at || !data.project_id || !data.tenant) {\n throw new Error(\n \"Invalid token response: missing token, expires_at, project_id, or tenant\",\n );\n }\n\n this.accessToken = data.token;\n this.expiresAt = new Date(data.expires_at * 1000);\n this._projectId = data.project_id;\n this._tenantSlug = data.tenant;\n\n if (data.test_email?.allowed_emails && data.test_email?.signature) {\n this._testEmailConfig = {\n allowedEmails: data.test_email.allowed_emails,\n signature: data.test_email.signature,\n };\n } else {\n this._testEmailConfig = null;\n }\n\n if (data.user?.id && data.user?.name && data.user?.signature) {\n this._userConfig = {\n id: data.user.id,\n name: data.user.name,\n signature: data.user.signature,\n };\n } else {\n this._userConfig = null;\n }\n\n return this.accessToken;\n } catch (error) {\n const wrappedError =\n error instanceof Error\n ? error\n : new Error(\"Token refresh failed\", { cause: error });\n this.onError?.(wrappedError);\n throw wrappedError;\n }\n }\n\n async authenticatedFetch(\n url: string,\n options: RequestInit = {},\n ): Promise<Response> {\n const token = await this.ensureToken();\n const resolvedUrl = this.resolveUrl(url);\n\n const makeRequest = async (authToken: string): Promise<Response> => {\n return fetch(resolvedUrl, {\n ...options,\n headers: {\n ...options.headers,\n Authorization: `Bearer ${authToken}`,\n },\n });\n };\n\n let response = await makeRequest(token);\n\n if (response.status === 401) {\n const newToken = await this.refreshToken();\n response = await makeRequest(newToken);\n }\n\n return response;\n }\n}\n\nexport function createSdkAuthManager(\n config: SdkAuthConfig,\n onError?: (error: Error) => void,\n): AuthManager {\n if (config.mode === \"direct\") {\n const baseUrl = (config.baseUrl ?? \"https://templatical.com\").replace(\n /\\/$/,\n \"\",\n );\n\n return new AuthManager({\n url: `${baseUrl}/api/v1/auth/token`,\n baseUrl: config.baseUrl,\n requestOptions: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: {\n client_id: config.clientId,\n client_secret: config.clientSecret,\n tenant: config.tenant,\n client_type: \"sdk\",\n },\n },\n onError,\n });\n }\n\n return new AuthManager({\n url: config.url,\n baseUrl: config.baseUrl,\n requestOptions: config.requestOptions,\n onError,\n });\n}\n","export function buildUrl(\n template: string,\n params: Record<string, string>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) =>\n encodeURIComponent(params[key] ?? \"\"),\n );\n}\n\nconst BASE = \"/api/v1/projects/{project}/tenants/{tenant}\";\nconst TEMPLATE = `${BASE}/templates/{template}`;\nconst AI = `${TEMPLATE}/ai`;\nconst MEDIA = `${BASE}/media`;\nconst FOLDERS = `${MEDIA}/folders`;\nconst MODULES = `${BASE}/saved-modules`;\n\nexport const API_ROUTES = {\n health: \"/api/v1/health\",\n \"projects.config\": `${BASE}/config`,\n \"broadcasting.auth\": `${BASE}/broadcasting/auth`,\n \"templates.store\": `${BASE}/templates`,\n \"templates.show\": `${TEMPLATE}`,\n \"templates.update\": `${TEMPLATE}`,\n \"templates.destroy\": `${TEMPLATE}`,\n \"templates.export\": `${TEMPLATE}/export`,\n \"templates.importFromBeefree\": `${BASE}/templates/import/from-beefree`,\n \"templates.sendTestEmail\": `${TEMPLATE}/send-test-email`,\n \"snapshots.index\": `${TEMPLATE}/snapshots`,\n \"snapshots.store\": `${TEMPLATE}/snapshots`,\n \"snapshots.show\": `${TEMPLATE}/snapshots/{snapshot}`,\n \"snapshots.restore\": `${TEMPLATE}/snapshots/{snapshot}/restore`,\n \"comments.index\": `${TEMPLATE}/comments`,\n \"comments.store\": `${TEMPLATE}/comments`,\n \"comments.update\": `${TEMPLATE}/comments/{comment}`,\n \"comments.destroy\": `${TEMPLATE}/comments/{comment}`,\n \"comments.resolve\": `${TEMPLATE}/comments/{comment}/resolve`,\n \"ai.generate\": `${AI}/generate`,\n \"ai.conversationMessages\": `${AI}/conversation-messages`,\n \"ai.suggestions\": `${AI}/suggestions`,\n \"ai.rewriteText\": `${AI}/rewrite-text`,\n \"ai.score\": `${AI}/score`,\n \"ai.fixFinding\": `${AI}/fix-finding`,\n \"ai.generateFromDesign\": `${AI}/generate-from-design`,\n \"media.upload\": `${MEDIA}/upload`,\n \"media.browse\": `${MEDIA}/browse`,\n \"media.delete\": `${MEDIA}/delete`,\n \"media.move\": `${MEDIA}/move`,\n \"media.update\": `${MEDIA}/{media}`,\n \"media.replace\": `${MEDIA}/{media}/replace`,\n \"media.checkUsage\": `${MEDIA}/check-usage`,\n \"media.frequentlyUsed\": `${MEDIA}/frequently-used`,\n \"media.importFromUrl\": `${MEDIA}/import-from-url`,\n \"folders.index\": `${FOLDERS}`,\n \"folders.store\": `${FOLDERS}`,\n \"folders.update\": `${FOLDERS}/{mediaFolder}`,\n \"folders.destroy\": `${FOLDERS}/{mediaFolder}`,\n \"savedModules.index\": `${MODULES}`,\n \"savedModules.store\": `${MODULES}`,\n \"savedModules.update\": `${MODULES}/{savedModule}`,\n \"savedModules.destroy\": `${MODULES}/{savedModule}`,\n} as const;\n","import type {\n ApiError,\n ApiResponse,\n Comment,\n CustomFont,\n PlanConfig,\n SavedBlock,\n Template,\n TemplateContent,\n TemplateSnapshot,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\n\nexport class ApiClient {\n constructor(private readonly authManager: AuthManager) {}\n\n private get projectId(): string {\n return this.authManager.projectId;\n }\n\n private get tenantSlug(): string {\n return this.authManager.tenantSlug;\n }\n\n private get baseParams(): Record<string, string> {\n return { project: this.projectId, tenant: this.tenantSlug };\n }\n\n private async request<T>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const response = await this.authManager.authenticatedFetch(path, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error: ApiError = await response.json().catch(() => ({\n message: `HTTP error ${response.status}`,\n }));\n\n const errorMessage = this.extractFirstValidationError(error);\n throw new SdkError(errorMessage, response.status);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n const json: ApiResponse<T> = await response.json();\n return json.data;\n }\n\n private extractFirstValidationError(error: ApiError): string {\n if (error.errors) {\n const firstField = Object.keys(error.errors)[0];\n if (firstField && error.errors[firstField]?.length > 0) {\n return error.errors[firstField][0];\n }\n }\n return error.message;\n }\n\n async createTemplate(content: TemplateContent): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.store\"], this.baseParams),\n {\n method: \"POST\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async getTemplate(id: string): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.show\"], {\n ...this.baseParams,\n template: id,\n }),\n );\n }\n\n async updateTemplate(\n id: string,\n content: TemplateContent,\n ): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.update\"], {\n ...this.baseParams,\n template: id,\n }),\n {\n method: \"PUT\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async createSnapshot(\n templateId: string,\n content: TemplateContent,\n ): Promise<TemplateSnapshot> {\n return this.request<TemplateSnapshot>(\n buildUrl(API_ROUTES[\"snapshots.store\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async deleteTemplate(id: string): Promise<void> {\n return this.request<void>(\n buildUrl(API_ROUTES[\"templates.destroy\"], {\n ...this.baseParams,\n template: id,\n }),\n {\n method: \"DELETE\",\n },\n );\n }\n\n async getSnapshots(templateId: string): Promise<TemplateSnapshot[]> {\n return this.request<TemplateSnapshot[]>(\n buildUrl(API_ROUTES[\"snapshots.index\"], {\n ...this.baseParams,\n template: templateId,\n }),\n );\n }\n\n async restoreSnapshot(\n templateId: string,\n snapshotId: string,\n ): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"snapshots.restore\"], {\n ...this.baseParams,\n template: templateId,\n snapshot: snapshotId,\n }),\n {\n method: \"POST\",\n },\n );\n }\n\n async exportTemplate(\n templateId: string,\n fontsPayload?: {\n customFonts: CustomFont[];\n defaultFallback: string;\n },\n ): Promise<{ html: string; mjml: string }> {\n const body = fontsPayload\n ? JSON.stringify({\n custom_fonts: fontsPayload.customFonts,\n default_fallback: fontsPayload.defaultFallback,\n })\n : undefined;\n\n return this.request<{ html: string; mjml: string }>(\n buildUrl(API_ROUTES[\"templates.export\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body,\n },\n );\n }\n\n async sendTestEmail(\n templateId: string,\n payload: {\n recipient: string;\n html: string;\n allowed_emails: string[];\n signature: string;\n },\n ): Promise<void> {\n await this.request<void>(\n buildUrl(API_ROUTES[\"templates.sendTestEmail\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify(payload),\n },\n );\n }\n\n private commentsUrl(templateId: string, commentId?: string): string {\n if (commentId) {\n return buildUrl(API_ROUTES[\"comments.update\"], {\n ...this.baseParams,\n template: templateId,\n comment: commentId,\n });\n }\n return buildUrl(API_ROUTES[\"comments.index\"], {\n ...this.baseParams,\n template: templateId,\n });\n }\n\n async getComments(templateId: string): Promise<Comment[]> {\n return this.request<Comment[]>(this.commentsUrl(templateId));\n }\n\n async createComment(\n templateId: string,\n data: {\n body: string;\n block_id?: string;\n parent_id?: string;\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(this.commentsUrl(templateId), {\n method: \"POST\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async updateComment(\n templateId: string,\n commentId: string,\n data: {\n body: string;\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(this.commentsUrl(templateId, commentId), {\n method: \"PUT\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async deleteComment(\n templateId: string,\n commentId: string,\n data: {\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<void> {\n return this.request<void>(this.commentsUrl(templateId, commentId), {\n method: \"DELETE\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async resolveComment(\n templateId: string,\n commentId: string,\n data: {\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(\n buildUrl(API_ROUTES[\"comments.resolve\"], {\n ...this.baseParams,\n template: templateId,\n comment: commentId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify(data),\n headers,\n },\n );\n }\n\n async fetchConfig(): Promise<PlanConfig> {\n return this.request<PlanConfig>(\n buildUrl(API_ROUTES[\"projects.config\"], this.baseParams),\n );\n }\n\n async listModules(search?: string, category?: string): Promise<SavedBlock[]> {\n const url = buildUrl(API_ROUTES[\"savedModules.index\"], this.baseParams);\n const params = new URLSearchParams();\n if (search) params.set(\"search\", search);\n if (category) params.set(\"category\", category);\n const query = params.size > 0 ? `?${params}` : \"\";\n return this.request<SavedBlock[]>(`${url}${query}`);\n }\n\n async createModule(data: {\n name: string;\n content: Block[];\n category?: string;\n }): Promise<SavedBlock> {\n return this.request<SavedBlock>(\n buildUrl(API_ROUTES[\"savedModules.store\"], this.baseParams),\n {\n method: \"POST\",\n body: JSON.stringify(data),\n },\n );\n }\n\n async updateModule(\n id: string,\n data: Partial<{ name: string; content: Block[]; category: string }>,\n ): Promise<SavedBlock> {\n return this.request<SavedBlock>(\n buildUrl(API_ROUTES[\"savedModules.update\"], {\n ...this.baseParams,\n savedModule: id,\n }),\n {\n method: \"PUT\",\n body: JSON.stringify(data),\n },\n );\n }\n\n async deleteModule(id: string): Promise<void> {\n return this.request<void>(\n buildUrl(API_ROUTES[\"savedModules.destroy\"], {\n ...this.baseParams,\n savedModule: id,\n }),\n {\n method: \"DELETE\",\n },\n );\n }\n}\n","import type { WebSocketServerConfig } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel, PresenceChannel } from \"pusher-js\";\n\ntype PusherType = Pusher;\n\nexport interface WebSocketConfig {\n host: string;\n port: number;\n appKey: string;\n}\n\nexport function resolveWebSocketConfig(\n serverConfig: WebSocketServerConfig,\n): WebSocketConfig {\n return {\n host: serverConfig.host,\n port: serverConfig.port,\n appKey: serverConfig.app_key,\n };\n}\n\nexport interface PresenceMember {\n id: string;\n name: string;\n type: \"user\" | \"mcp\";\n}\n\nexport interface WebSocketClientOptions {\n authManager: AuthManager;\n config: WebSocketConfig;\n onError?: (error: Error) => void;\n}\n\nexport class WebSocketClient {\n private pusher: PusherType | null = null;\n private readonly authManager: AuthManager;\n private readonly config: WebSocketConfig;\n private readonly onError?: (error: Error) => void;\n\n constructor(options: WebSocketClientOptions) {\n this.authManager = options.authManager;\n this.config = options.config;\n this.onError = options.onError;\n }\n\n async connect(): Promise<void> {\n if (this.pusher) {\n return;\n }\n\n let Pusher: typeof import(\"pusher-js\").default;\n try {\n ({ default: Pusher } = await import(\"pusher-js\"));\n } catch {\n throw new Error(\n \"Cloud features require the optional peer dependency 'pusher-js'. Install it with: npm install pusher-js\",\n );\n }\n\n const { host, port, appKey } = this.config;\n const authEndpoint = this.authManager.resolveUrl(\n buildUrl(API_ROUTES[\"broadcasting.auth\"], {\n project: this.authManager.projectId,\n tenant: this.authManager.tenantSlug,\n }),\n );\n\n this.pusher = new Pusher(appKey, {\n wsHost: host,\n wsPort: port,\n wssPort: port,\n forceTLS: true,\n disableStats: true,\n enabledTransports: [\"ws\", \"wss\"],\n cluster: \"\",\n channelAuthorization: {\n transport: \"ajax\",\n endpoint: authEndpoint,\n headers: {\n Authorization: `Bearer ${this.authManager.accessTokenValue}`,\n Accept: \"application/json\",\n },\n params: {\n user_id: this.authManager.userConfig?.id ?? \"\",\n user_name: this.authManager.userConfig?.name ?? \"\",\n user_signature: this.authManager.userConfig?.signature ?? \"\",\n },\n },\n });\n\n this.pusher.connection.bind(\"error\", (error: unknown) => {\n this.onError?.(\n error instanceof Error\n ? error\n : new Error(\"WebSocket connection error\"),\n );\n });\n }\n\n subscribePresence(channelName: string): PresenceChannel {\n if (!this.pusher) {\n throw new Error(\"WebSocketClient not connected. Call connect() first.\");\n }\n\n return this.pusher.subscribe(channelName) as PresenceChannel;\n }\n\n unsubscribe(channelName: string): void {\n this.pusher?.unsubscribe(channelName);\n }\n\n getChannel(channelName: string): Channel | undefined {\n return this.pusher?.channel(channelName);\n }\n\n disconnect(): void {\n if (this.pusher) {\n this.pusher.disconnect();\n this.pusher = null;\n }\n }\n\n getSocketId(): string | null {\n return this.pusher?.connection.socket_id ?? null;\n }\n\n get isConnected(): boolean {\n return this.pusher?.connection.state === \"connected\";\n }\n}\n","import type { McpOperationPayload } from \"@templatical/types\";\nimport type {\n Block,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\nimport type { UseEditorReturn } from \"./editor\";\n\nexport function handleOperation(\n editor: UseEditorReturn,\n payload: McpOperationPayload,\n): void {\n const { operation, data } = payload;\n\n switch (operation) {\n case \"add_block\":\n editor.addBlock(\n data.block as Block,\n data.section_id as string | undefined,\n data.column_index as number | undefined,\n data.index as number | undefined,\n );\n break;\n\n case \"update_block\":\n editor.updateBlock(\n data.block_id as string,\n data.updates as Partial<Block>,\n );\n break;\n\n case \"delete_block\":\n editor.removeBlock(data.block_id as string);\n break;\n\n case \"move_block\":\n editor.moveBlock(\n data.block_id as string,\n data.index as number,\n data.section_id as string | undefined,\n data.column_index as number | undefined,\n );\n break;\n\n case \"update_settings\":\n editor.updateSettings(data.updates as Partial<TemplateSettings>);\n break;\n\n case \"set_content\":\n editor.setContent(data.content as TemplateContent);\n break;\n\n case \"update_block_style\":\n editor.updateBlock(\n data.block_id as string,\n {\n styles: data.styles,\n } as Partial<Block>,\n );\n break;\n }\n}\n","import type {\n EditorState,\n Template,\n TemplateDefaults,\n UiTheme,\n ViewportSize,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport type {\n Block,\n ColumnLayout,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\nimport { computed, reactive, readonly, type DeepReadonly, type Ref } from \"vue\";\n\nfunction getColumnCount(layout: ColumnLayout): number {\n if (layout === \"1\") return 1;\n if (layout === \"3\") return 3;\n return 2;\n}\n\nexport interface UseEditorOptions {\n authManager: AuthManager;\n defaultFontFamily?: string;\n templateDefaults?: TemplateDefaults;\n onError?: (error: Error) => void;\n lockedBlocks?: Ref<Map<string, unknown>>;\n}\n\nexport interface UseEditorReturn {\n state: DeepReadonly<EditorState>;\n content: Ref<TemplateContent>;\n selectedBlock: Ref<Block | null>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n selectBlock: (blockId: string | null) => void;\n setViewport: (viewport: ViewportSize) => void;\n setDarkMode: (darkMode: boolean) => void;\n setPreviewMode: (previewMode: boolean) => void;\n setUiTheme: (theme: UiTheme) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n updateSettings: (updates: Partial<TemplateSettings>) => void;\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n index?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n moveBlock: (\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n savedBlockIds: Ref<Set<string>>;\n isBlockLocked: (blockId: string) => boolean;\n findBlockLocation: (blockId: string) => {\n targetSectionId?: string;\n columnIndex?: number;\n index: number;\n } | null;\n create: (content?: TemplateContent) => Promise<Template>;\n load: (templateId: string) => Promise<Template>;\n save: () => Promise<Template>;\n createSnapshot: () => Promise<void>;\n hasTemplate: () => boolean;\n markDirty: () => void;\n}\n\nexport function useEditor(options: UseEditorOptions): UseEditorReturn {\n const api = new ApiClient(options.authManager);\n\n const state = reactive<EditorState>({\n template: null,\n content: createDefaultTemplateContent(\n options.defaultFontFamily,\n options.templateDefaults,\n ),\n selectedBlockId: null,\n viewport: \"desktop\",\n darkMode: false,\n previewMode: false,\n isDirty: false,\n isSaving: false,\n isLoading: false,\n uiTheme: \"auto\",\n });\n\n const content = computed({\n get: () => state.content,\n set: (value: TemplateContent) => {\n state.content = value;\n state.isDirty = true;\n },\n });\n\n const selectedBlock = computed(() => {\n if (!state.selectedBlockId) return null;\n return findBlockById(state.content.blocks, state.selectedBlockId);\n });\n\n const savedBlockIds = computed<Set<string>>(() => {\n const ids = new Set<string>();\n const blocks = state.template?.content?.blocks;\n if (!blocks) {\n return ids;\n }\n for (const block of blocks) {\n ids.add(block.id);\n if (block.type === \"section\") {\n for (const column of block.children) {\n for (const child of column) {\n ids.add(child.id);\n }\n }\n }\n }\n return ids;\n });\n\n function findBlockById(blocks: Block[], id: string): Block | null {\n for (const block of blocks) {\n if (block.id === id) return block;\n if (block.type === \"section\") {\n for (const column of block.children) {\n const found = findBlockById(column, id);\n if (found) return found;\n }\n }\n }\n return null;\n }\n\n function findBlockParent(\n blocks: Block[],\n id: string,\n parent: {\n blocks: Block[];\n sectionId?: string;\n columnIndex?: number;\n } = { blocks },\n ): { blocks: Block[]; sectionId?: string; columnIndex?: number } | null {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block.id === id) return parent;\n if (block.type === \"section\") {\n for (let colIdx = 0; colIdx < block.children.length; colIdx++) {\n const result = findBlockParent(block.children[colIdx], id, {\n blocks: block.children[colIdx],\n sectionId: block.id,\n columnIndex: colIdx,\n });\n if (result) return result;\n }\n }\n }\n return null;\n }\n\n function isBlockLocked(blockId: string): boolean {\n return options.lockedBlocks?.value.has(blockId) ?? false;\n }\n\n function setContent(newContent: TemplateContent, markDirty = true): void {\n state.content = newContent;\n if (markDirty) {\n state.isDirty = true;\n }\n }\n\n function selectBlock(blockId: string | null): void {\n if (blockId && isBlockLocked(blockId)) {\n return;\n }\n state.selectedBlockId = blockId;\n }\n\n function setViewport(viewport: ViewportSize): void {\n state.viewport = viewport;\n }\n\n function setDarkMode(darkMode: boolean): void {\n state.darkMode = darkMode;\n }\n\n function setUiTheme(theme: UiTheme): void {\n state.uiTheme = theme;\n }\n\n function setPreviewMode(previewMode: boolean): void {\n state.previewMode = previewMode;\n if (previewMode) {\n state.selectedBlockId = null;\n }\n }\n\n function updateBlock(blockId: string, updates: Partial<Block>): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const block = findBlockById(state.content.blocks, blockId);\n if (block) {\n Object.assign(block, updates);\n state.isDirty = true;\n }\n }\n\n function updateSettings(updates: Partial<TemplateSettings>): void {\n state.content.settings = { ...state.content.settings, ...updates };\n state.isDirty = true;\n }\n\n function addBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex = 0,\n index?: number,\n ): void {\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n const targetArray = section.children[columnIndex];\n if (index !== undefined && index < targetArray.length) {\n targetArray.splice(index, 0, block);\n } else {\n targetArray.push(block);\n }\n }\n } else {\n if (index !== undefined && index < state.content.blocks.length) {\n state.content.blocks.splice(index, 0, block);\n } else {\n state.content.blocks.push(block);\n }\n }\n state.isDirty = true;\n }\n\n function removeBlock(blockId: string): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const parent = findBlockParent(state.content.blocks, blockId);\n if (parent) {\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index !== -1) {\n parent.blocks.splice(index, 1);\n if (state.selectedBlockId === blockId) {\n state.selectedBlockId = null;\n }\n state.isDirty = true;\n }\n }\n }\n\n function moveBlock(\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex = 0,\n ): void {\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return;\n\n const oldIndex = parent.blocks.findIndex((b) => b.id === blockId);\n if (oldIndex === -1) return;\n\n // Resolve target before mutating the source — otherwise an invalid\n // targetSectionId (stale/deleted id, non-section block, or out-of-range\n // columnIndex) leaves the block spliced-out and unrecoverable. Reachable\n // via untrusted remote move_block payloads (MCP/collaboration), which take\n // no history snapshot, so a dropped block can't even be undone.\n let targetArray: Block[];\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (!section || section.type !== \"section\") return;\n if (columnIndex < 0 || columnIndex >= getColumnCount(section.columns)) {\n return;\n }\n section.children[columnIndex] = section.children[columnIndex] || [];\n targetArray = section.children[columnIndex];\n } else {\n targetArray = state.content.blocks;\n }\n\n const [block] = parent.blocks.splice(oldIndex, 1);\n targetArray.splice(newIndex, 0, block);\n\n state.isDirty = true;\n }\n\n async function create(content?: TemplateContent): Promise<Template> {\n state.isLoading = true;\n try {\n if (content) {\n state.content = content;\n }\n const template = await api.createTemplate(state.content);\n state.template = template;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isLoading = false;\n }\n }\n\n async function load(templateId: string): Promise<Template> {\n state.isLoading = true;\n try {\n const template = await api.getTemplate(templateId);\n state.template = template;\n state.content = template.content;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isLoading = false;\n }\n }\n\n async function save(): Promise<Template> {\n if (!state.template?.id) {\n throw new SdkError(\n \"No template loaded. Call create() or load() before saving.\",\n );\n }\n\n state.isSaving = true;\n try {\n const template = await api.updateTemplate(\n state.template.id,\n state.content,\n );\n state.template = template;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isSaving = false;\n }\n }\n\n async function createSnapshot(): Promise<void> {\n if (!state.template?.id) {\n return;\n }\n\n try {\n await api.createSnapshot(state.template.id, state.content);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n function hasTemplate(): boolean {\n return state.template?.id !== undefined;\n }\n\n function markDirty(): void {\n state.isDirty = true;\n }\n\n function findBlockLocation(blockId: string): {\n targetSectionId?: string;\n columnIndex?: number;\n index: number;\n } | null {\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return null;\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index === -1) return null;\n return {\n targetSectionId: parent.sectionId,\n columnIndex: parent.columnIndex,\n index,\n };\n }\n\n return {\n state: readonly(state),\n content,\n selectedBlock,\n savedBlockIds,\n isBlockLocked,\n findBlockLocation,\n setContent,\n selectBlock,\n setViewport,\n setDarkMode,\n setUiTheme,\n setPreviewMode,\n updateBlock,\n updateSettings,\n addBlock,\n removeBlock,\n moveBlock,\n create,\n load,\n save,\n createSnapshot,\n hasTemplate,\n markDirty,\n };\n}\n","import type { AiChatMessage } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { MergeTag, TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseAiChatOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n onApply?: (content: TemplateContent) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseAiChatReturn {\n messages: ReturnType<typeof ref<AiChatMessage[]>>;\n isGenerating: ReturnType<typeof ref<boolean>>;\n isLoadingHistory: ReturnType<typeof ref<boolean>>;\n isLastChangeReverted: ReturnType<typeof ref<boolean>>;\n lastApplyMessageId: ReturnType<typeof ref<string | null>>;\n error: ReturnType<typeof ref<string | null>>;\n failedPrompt: ReturnType<typeof ref<string | null>>;\n suggestions: ReturnType<typeof ref<string[]>>;\n isLoadingSuggestions: ReturnType<typeof ref<boolean>>;\n sendPrompt: (\n prompt: string,\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<TemplateContent | null>;\n toggleLastRevert: () => void;\n loadConversation: () => Promise<void>;\n loadSuggestions: (\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<void>;\n clearChat: () => void;\n}\n\nlet messageIdCounter = 0;\n\nfunction generateMessageId(): string {\n return `msg_${Date.now()}_${++messageIdCounter}`;\n}\n\nexport function useAiChat(options: UseAiChatOptions): UseAiChatReturn {\n const { authManager, getTemplateId, onApply, onError } = options;\n\n const messages = ref<AiChatMessage[]>([]);\n const isGenerating = ref(false);\n const isLoadingHistory = ref(false);\n const error = ref<string | null>(null);\n const failedPrompt = ref<string | null>(null);\n const conversationId = ref<string | null>(null);\n const lastApplyMessageId = ref<string | null>(null);\n const lastPreviousContent = ref<TemplateContent | null>(null);\n const lastAppliedContent = ref<TemplateContent | null>(null);\n const isLastChangeReverted = ref(false);\n const suggestions = ref<string[]>([]);\n const isLoadingSuggestions = ref(false);\n\n function updateMessage(msgId: string, updates: Partial<AiChatMessage>): void {\n const idx = messages.value.findIndex((m) => m.id === msgId);\n if (idx === -1) {\n return;\n }\n\n const updated = { ...messages.value[idx], ...updates };\n messages.value = [\n ...messages.value.slice(0, idx),\n updated,\n ...messages.value.slice(idx + 1),\n ];\n }\n\n async function loadConversation(): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoadingHistory.value = true;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.conversationMessages\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n },\n });\n\n if (!response.ok) {\n return;\n }\n\n const data = await response.json();\n\n if (data.conversation_id) {\n conversationId.value = data.conversation_id;\n }\n\n if (Array.isArray(data.data) && data.data.length > 0) {\n messages.value = data.data.map(\n (msg: {\n id: string;\n role: \"user\" | \"assistant\";\n content: string;\n created_at: string;\n }) => ({\n id: msg.id,\n role: msg.role,\n content: msg.content,\n timestamp: new Date(msg.created_at).getTime(),\n }),\n );\n }\n } catch {\n // Silently fail - chat will start fresh\n } finally {\n isLoadingHistory.value = false;\n }\n }\n\n async function loadSuggestions(\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoadingSuggestions.value = true;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.suggestions\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n current_content: currentContent,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n return;\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n return;\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"done\" && Array.isArray(event.suggestions)) {\n suggestions.value = event.suggestions.slice(0, 3);\n }\n }\n }\n } catch {\n // Silently fail - suggestions are non-critical\n } finally {\n isLoadingSuggestions.value = false;\n }\n }\n\n async function sendPrompt(\n prompt: string,\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<TemplateContent | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before using AI generation\");\n }\n\n isGenerating.value = true;\n error.value = null;\n failedPrompt.value = null;\n suggestions.value = [];\n\n const userMsgId = generateMessageId();\n messages.value = [\n ...messages.value,\n {\n id: userMsgId,\n role: \"user\",\n content: prompt,\n timestamp: Date.now(),\n },\n ];\n\n const assistantMsgId = generateMessageId();\n messages.value = [\n ...messages.value,\n {\n id: assistantMsgId,\n role: \"assistant\",\n content: \"\",\n timestamp: Date.now(),\n },\n ];\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.generate\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n prompt,\n current_content: currentContent,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n conversation_id: conversationId.value,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => null);\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n throw new Error(errorData?.message || \"Failed to generate template\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: TemplateContent | null = null;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n const jsonStr = line.slice(6);\n\n let event;\n try {\n event = JSON.parse(jsonStr);\n } catch {\n continue;\n }\n\n if (event.type === \"text\") {\n updateMessage(assistantMsgId, {\n content:\n (messages.value.find((m) => m.id === assistantMsgId)\n ?.content ?? \"\") + event.text,\n });\n } else if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to generate template\");\n } else if (event.type === \"done\") {\n if (event.conversation_id) {\n conversationId.value = event.conversation_id;\n }\n\n updateMessage(assistantMsgId, {\n content: event.text,\n });\n\n result = event.content ?? null;\n\n if (result) {\n lastPreviousContent.value = currentContent;\n lastAppliedContent.value = result;\n lastApplyMessageId.value = assistantMsgId;\n isLastChangeReverted.value = false;\n onApply?.(result);\n } else {\n error.value = \"ai_apply_failed\";\n }\n }\n }\n }\n } finally {\n // Release the underlying network resource even on early exit.\n // Without this, throwing out of the loop (e.g. on an `error` SSE\n // event) leaves the socket and read buffer attached until GC.\n reader.cancel().catch(() => {});\n }\n\n return result;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to generate template\", { cause: err });\n error.value = wrappedError.message;\n failedPrompt.value = prompt;\n onError?.(wrappedError);\n\n messages.value = messages.value.filter(\n (m) => m.id !== userMsgId && m.id !== assistantMsgId,\n );\n\n return null;\n } finally {\n isGenerating.value = false;\n }\n }\n\n function toggleLastRevert(): void {\n if (isLastChangeReverted.value) {\n if (lastAppliedContent.value) {\n onApply?.(lastAppliedContent.value);\n }\n isLastChangeReverted.value = false;\n } else {\n if (lastPreviousContent.value) {\n onApply?.(lastPreviousContent.value);\n }\n isLastChangeReverted.value = true;\n }\n }\n\n function clearChat(): void {\n messages.value = [];\n conversationId.value = null;\n error.value = null;\n lastApplyMessageId.value = null;\n lastPreviousContent.value = null;\n lastAppliedContent.value = null;\n isLastChangeReverted.value = false;\n }\n\n return {\n messages,\n isGenerating,\n isLoadingHistory,\n isLastChangeReverted,\n lastApplyMessageId,\n error,\n failedPrompt,\n suggestions,\n isLoadingSuggestions,\n sendPrompt,\n toggleLastRevert,\n loadConversation,\n loadSuggestions,\n clearChat,\n };\n}\n","import type { AiConfig } from \"@templatical/types\";\nimport { computed, type ComputedRef } from \"vue\";\n\nexport interface UseAiConfigReturn {\n isFeatureEnabled: (feature: keyof AiConfig) => boolean;\n hasAnyMenuFeature: ComputedRef<boolean>;\n}\n\nexport function useAiConfig(config?: AiConfig | false): UseAiConfigReturn {\n function isFeatureEnabled(feature: keyof AiConfig): boolean {\n if (config === false) {\n return false;\n }\n\n return config?.[feature] !== false;\n }\n\n const hasAnyMenuFeature = computed(\n () =>\n isFeatureEnabled(\"chat\") ||\n isFeatureEnabled(\"scoring\") ||\n isFeatureEnabled(\"designToTemplate\"),\n );\n\n return {\n isFeatureEnabled,\n hasAnyMenuFeature,\n };\n}\n","import type {\n ScoringCategory,\n ScoringFinding,\n ScoringResult,\n} from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { MergeTag, TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseTemplateScoringOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n}\n\nexport interface UseTemplateScoringReturn {\n isScoring: ReturnType<typeof ref<boolean>>;\n scoringResult: ReturnType<typeof ref<ScoringResult | null>>;\n error: ReturnType<typeof ref<string | null>>;\n fixingFindingId: ReturnType<typeof ref<string | null>>;\n fixStreamingText: ReturnType<typeof ref<string>>;\n fixError: ReturnType<typeof ref<string | null>>;\n score: (\n content: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<ScoringResult | null>;\n fixFinding: (\n blockContent: string,\n finding: ScoringFinding,\n mergeTags: MergeTag[],\n ) => Promise<string | null>;\n removeFinding: (category: ScoringCategory, findingId: string) => void;\n reset: () => void;\n}\n\nexport function useTemplateScoring(\n options: UseTemplateScoringOptions,\n): UseTemplateScoringReturn {\n const { authManager, getTemplateId } = options;\n\n const isScoring = ref(false);\n const scoringResult = ref<ScoringResult | null>(null);\n const error = ref<string | null>(null);\n const fixingFindingId = ref<string | null>(null);\n const fixStreamingText = ref(\"\");\n const fixError = ref<string | null>(null);\n\n async function score(\n content: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<ScoringResult | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isScoring.value = true;\n error.value = null;\n scoringResult.value = null;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.score\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n current_content: content,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n const errorData = await response.json().catch(() => null);\n throw new Error(errorData?.message || \"Failed to score template\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: ScoringResult | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to score template\");\n }\n\n if (event.type === \"done\") {\n result = event.result ?? null;\n }\n }\n }\n\n if (result) {\n for (const [category, categoryData] of Object.entries(\n result.categories,\n )) {\n for (const finding of categoryData.findings) {\n finding.category = category as ScoringCategory;\n }\n }\n }\n\n scoringResult.value = result;\n return result;\n } catch (err) {\n error.value =\n err instanceof Error ? err.message : \"Failed to score template\";\n return null;\n } finally {\n isScoring.value = false;\n }\n }\n\n async function fixFinding(\n blockContent: string,\n finding: ScoringFinding,\n mergeTags: MergeTag[],\n ): Promise<string | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n fixingFindingId.value = finding.id;\n fixStreamingText.value = \"\";\n fixError.value = null;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.fixFinding\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n content: blockContent,\n finding: {\n id: finding.id,\n message: finding.message,\n suggestion: finding.suggestion,\n category: finding.category,\n },\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n const errorData = await response.json().catch(() => null);\n throw new Error(errorData?.message || \"Failed to fix finding\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: string | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"text\") {\n fixStreamingText.value += event.text;\n } else if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to fix finding\");\n } else if (event.type === \"done\") {\n result = event.content ?? null;\n }\n }\n }\n\n return result;\n } catch (err) {\n fixError.value =\n err instanceof Error ? err.message : \"Failed to fix finding\";\n return null;\n } finally {\n fixingFindingId.value = null;\n }\n }\n\n function removeFinding(category: ScoringCategory, findingId: string): void {\n if (!scoringResult.value) {\n return;\n }\n\n const cat = scoringResult.value.categories[category];\n if (!cat) {\n return;\n }\n\n cat.findings = cat.findings.filter((f) => f.id !== findingId);\n }\n\n function reset(): void {\n isScoring.value = false;\n scoringResult.value = null;\n error.value = null;\n fixingFindingId.value = null;\n fixStreamingText.value = \"\";\n fixError.value = null;\n }\n\n return {\n isScoring,\n scoringResult,\n error,\n fixingFindingId,\n fixStreamingText,\n fixError,\n score,\n fixFinding,\n removeFinding,\n reset,\n };\n}\n","import type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseDesignReferenceOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n onApply?: (content: TemplateContent) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseDesignReferenceReturn {\n isGenerating: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<string | null>>;\n generate: (input: DesignReferenceInput) => Promise<TemplateContent | null>;\n reset: () => void;\n}\n\nexport interface DesignReferenceInput {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n}\n\nexport function useDesignReference(\n options: UseDesignReferenceOptions,\n): UseDesignReferenceReturn {\n const { authManager, getTemplateId, onApply, onError } = options;\n\n const isGenerating = ref(false);\n const error = ref<string | null>(null);\n\n async function generate(\n input: DesignReferenceInput,\n ): Promise<TemplateContent | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before using design reference\");\n }\n\n isGenerating.value = true;\n error.value = null;\n\n try {\n const formData = new FormData();\n\n if (input.prompt) {\n formData.append(\"prompt\", input.prompt);\n }\n\n if (input.imageUpload) {\n formData.append(\"image_upload\", input.imageUpload);\n }\n\n if (input.pdfUpload) {\n formData.append(\"pdf_upload\", input.pdfUpload);\n }\n\n const url = buildUrl(API_ROUTES[\"ai.generateFromDesign\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n Accept: \"text/event-stream\",\n },\n body: formData,\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => null);\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n throw new Error(\n errorData?.message || \"Failed to generate template from design\",\n );\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: TemplateContent | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n const jsonStr = line.slice(6);\n\n let event;\n try {\n event = JSON.parse(jsonStr);\n } catch {\n continue;\n }\n\n if (event.type === \"error\") {\n throw new Error(\n event.message || \"Failed to generate template from design\",\n );\n }\n\n if (event.type === \"done\") {\n result = event.content ?? null;\n\n if (result) {\n onApply?.(result);\n }\n }\n }\n }\n\n return result;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to generate template from design\", {\n cause: err,\n });\n error.value = wrappedError.message;\n onError?.(wrappedError);\n\n return null;\n } finally {\n isGenerating.value = false;\n }\n }\n\n function reset(): void {\n isGenerating.value = false;\n error.value = null;\n }\n\n return {\n isGenerating,\n error,\n generate,\n reset,\n };\n}\n","import type {\n Comment,\n CommentEvent,\n CommentThread,\n UserConfig,\n} from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { computed, ref, type ComputedRef, type Ref } from \"vue\";\n\nexport interface UseCommentsOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n getSocketId?: () => string | null;\n onComment?: (event: CommentEvent) => void;\n onError?: (error: Error) => void;\n isAuthReady?: Ref<boolean>;\n hasCommentingFeature?: () => boolean;\n}\n\nexport interface UseCommentsReturn {\n comments: Ref<CommentThread[]>;\n isLoading: Ref<boolean>;\n isSubmitting: Ref<boolean>;\n isEnabled: ComputedRef<boolean>;\n commentCountByBlock: ComputedRef<Map<string, number>>;\n totalCount: ComputedRef<number>;\n unresolvedCount: ComputedRef<number>;\n loadComments: () => Promise<void>;\n addComment: (\n body: string,\n blockId?: string,\n parentId?: string,\n ) => Promise<Comment | null>;\n editComment: (commentId: string, body: string) => Promise<Comment | null>;\n removeComment: (commentId: string) => Promise<boolean>;\n toggleResolve: (commentId: string) => Promise<Comment | null>;\n applyRemoteCreate: (comment: Comment) => void;\n applyRemoteUpdate: (comment: Comment) => void;\n applyRemoteDelete: (commentId: string, parentId: string | null) => void;\n}\n\nexport function useComments(options: UseCommentsOptions): UseCommentsReturn {\n const {\n authManager,\n getTemplateId,\n getSocketId,\n onComment,\n onError,\n hasCommentingFeature,\n } = options;\n\n const api = new ApiClient(authManager);\n const comments = ref<CommentThread[]>([]);\n const isLoading = ref(false);\n const isSubmitting = ref(false);\n\n const isEnabled = computed<boolean>(() => {\n const featureAvailable = hasCommentingFeature?.() ?? false;\n return featureAvailable && authManager.userConfig !== null;\n });\n\n const totalCount = computed<number>(() => {\n let count = 0;\n for (const thread of comments.value) {\n count += 1 + (thread.replies?.length ?? 0);\n }\n return count;\n });\n\n const unresolvedCount = computed<number>(() => {\n return comments.value.filter((c) => !c.resolved_at).length;\n });\n\n const commentCountByBlock = computed<Map<string, number>>(() => {\n const map = new Map<string, number>();\n for (const thread of comments.value) {\n if (thread.block_id) {\n map.set(\n thread.block_id,\n (map.get(thread.block_id) ?? 0) + 1 + (thread.replies?.length ?? 0),\n );\n }\n }\n return map;\n });\n\n function getUserPayload(): {\n user_id: string;\n user_name: string;\n user_signature: string;\n } {\n const user: UserConfig | null = authManager.userConfig;\n if (!user) {\n throw new Error(\"User config not available\");\n }\n return {\n user_id: user.id,\n user_name: user.name,\n user_signature: user.signature,\n };\n }\n\n function socketHeaders(): Record<string, string> | undefined {\n const socketId = getSocketId?.();\n if (!socketId) {\n return undefined;\n }\n return { \"X-Socket-ID\": socketId };\n }\n\n function emitEvent(type: CommentEvent[\"type\"], comment: Comment): void {\n onComment?.({ type, comment });\n }\n\n function findComment(commentId: string): Comment | null {\n for (const thread of comments.value) {\n if (thread.id === commentId) {\n return thread;\n }\n for (const reply of thread.replies ?? []) {\n if (reply.id === commentId) {\n return reply;\n }\n }\n }\n return null;\n }\n\n async function loadComments(): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoading.value = true;\n\n try {\n comments.value = await api.getComments(templateId);\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to load comments\", { cause: err });\n onError?.(wrappedError);\n } finally {\n isLoading.value = false;\n }\n }\n\n async function addComment(\n body: string,\n blockId?: string,\n parentId?: string,\n ): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const comment = await api.createComment(\n templateId,\n {\n body,\n block_id: blockId,\n parent_id: parentId,\n ...getUserPayload(),\n },\n socketHeaders(),\n );\n\n if (parentId) {\n const parent = findComment(parentId);\n if (parent) {\n parent.replies = [...(parent.replies ?? []), comment];\n }\n } else {\n comments.value = [...comments.value, comment];\n }\n\n emitEvent(\"created\", comment);\n return comment;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to create comment\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function editComment(\n commentId: string,\n body: string,\n ): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const updated = await api.updateComment(\n templateId,\n commentId,\n {\n body,\n ...getUserPayload(),\n },\n socketHeaders(),\n );\n\n updateCommentInState(commentId, updated);\n emitEvent(\"updated\", updated);\n return updated;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to update comment\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function removeComment(commentId: string): Promise<boolean> {\n const templateId = getTemplateId();\n if (!templateId) {\n return false;\n }\n\n const comment = findComment(commentId);\n if (!comment) {\n return false;\n }\n\n const commentSnapshot = {\n ...comment,\n replies: [...(comment.replies ?? [])],\n };\n\n isSubmitting.value = true;\n\n try {\n await api.deleteComment(\n templateId,\n commentId,\n getUserPayload(),\n socketHeaders(),\n );\n\n if (comment.parent_id) {\n const parent = findComment(comment.parent_id);\n if (parent) {\n parent.replies = (parent.replies ?? []).filter(\n (r) => r.id !== commentId,\n );\n }\n } else {\n comments.value = comments.value.filter((c) => c.id !== commentId);\n }\n\n emitEvent(\"deleted\", commentSnapshot);\n return true;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to delete comment\", { cause: err });\n onError?.(wrappedError);\n return false;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function toggleResolve(commentId: string): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const updated = await api.resolveComment(\n templateId,\n commentId,\n getUserPayload(),\n socketHeaders(),\n );\n\n updateCommentInState(commentId, updated);\n\n const eventType = updated.resolved_at ? \"resolved\" : \"unresolved\";\n emitEvent(eventType, updated);\n return updated;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to toggle comment resolution\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n function applyRemoteCreate(comment: Comment): void {\n if (comment.parent_id) {\n const parent = findComment(comment.parent_id);\n if (parent) {\n parent.replies = [...(parent.replies ?? []), comment];\n }\n } else {\n comments.value = [...comments.value, comment];\n }\n emitEvent(\"created\", comment);\n }\n\n function applyRemoteUpdate(comment: Comment): void {\n updateCommentInState(comment.id, comment);\n emitEvent(\"updated\", comment);\n }\n\n function applyRemoteDelete(commentId: string, parentId: string | null): void {\n const comment = findComment(commentId);\n const snapshot = comment\n ? { ...comment, replies: [...(comment.replies ?? [])] }\n : null;\n\n if (parentId) {\n const parent = findComment(parentId);\n if (parent) {\n parent.replies = (parent.replies ?? []).filter(\n (r) => r.id !== commentId,\n );\n }\n } else {\n comments.value = comments.value.filter((c) => c.id !== commentId);\n }\n\n if (snapshot) {\n emitEvent(\"deleted\", snapshot);\n }\n }\n\n function updateCommentInState(commentId: string, updated: Comment): void {\n for (let i = 0; i < comments.value.length; i++) {\n if (comments.value[i].id === commentId) {\n comments.value = [\n ...comments.value.slice(0, i),\n { ...updated, replies: comments.value[i].replies },\n ...comments.value.slice(i + 1),\n ];\n return;\n }\n\n const replies = comments.value[i].replies ?? [];\n for (let j = 0; j < replies.length; j++) {\n if (replies[j].id === commentId) {\n const newReplies = [\n ...replies.slice(0, j),\n updated,\n ...replies.slice(j + 1),\n ];\n comments.value = [\n ...comments.value.slice(0, i),\n { ...comments.value[i], replies: newReplies },\n ...comments.value.slice(i + 1),\n ];\n return;\n }\n }\n }\n }\n\n return {\n comments,\n isLoading,\n isSubmitting,\n isEnabled,\n commentCountByBlock,\n totalCount,\n unresolvedCount,\n loadComments,\n addComment,\n editComment,\n removeComment,\n toggleResolve,\n applyRemoteCreate,\n applyRemoteUpdate,\n applyRemoteDelete,\n };\n}\n","import type { UseCommentsReturn } from \"./comments\";\nimport type { Comment } from \"@templatical/types\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { onScopeDispose, watch, type Ref } from \"vue\";\n\nexport interface CommentBroadcastPayload {\n action:\n | \"comment_created\"\n | \"comment_updated\"\n | \"comment_deleted\"\n | \"comment_resolved\"\n | \"comment_unresolved\";\n comment: Comment;\n}\n\nexport interface UseCommentListenerOptions {\n comments: UseCommentsReturn;\n channel: Ref<PresenceChannel | null>;\n}\n\nexport function useCommentListener(options: UseCommentListenerOptions): void {\n const { comments, channel } = options;\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n oldChannel.unbind(\"comment-broadcast\");\n }\n\n if (newChannel) {\n newChannel.bind(\n \"comment-broadcast\",\n (payload: CommentBroadcastPayload) => {\n handleCommentBroadcast(comments, payload);\n },\n );\n }\n });\n\n // The watch only unbinds on channel *transitions*. On scope dispose the\n // currently-bound handler stays attached, processing broadcasts on a\n // dead component. Explicitly tear it down.\n onScopeDispose(() => {\n channel.value?.unbind(\"comment-broadcast\");\n });\n}\n\nfunction handleCommentBroadcast(\n comments: UseCommentsReturn,\n payload: CommentBroadcastPayload,\n): void {\n switch (payload.action) {\n case \"comment_created\":\n comments.applyRemoteCreate(payload.comment);\n break;\n case \"comment_updated\":\n comments.applyRemoteUpdate(payload.comment);\n break;\n case \"comment_deleted\":\n comments.applyRemoteDelete(payload.comment.id, payload.comment.parent_id);\n break;\n case \"comment_resolved\":\n case \"comment_unresolved\":\n comments.applyRemoteUpdate(payload.comment);\n break;\n }\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { AuthManager } from \"./auth\";\nimport type { Collaborator, McpOperationPayload } from \"@templatical/types\";\nimport { handleOperation } from \"./mcp-operation-handler\";\nimport type { PresenceMember } from \"./websocket-client\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { computed, onScopeDispose, ref, watch, type Ref } from \"vue\";\n\nconst COLLAB_EVENTS = [\n \"pusher:member_added\",\n \"pusher:member_removed\",\n \"client-block_locked\",\n \"client-block_unlocked\",\n \"client-operation\",\n \"mcp-operation\",\n] as const;\n\nfunction unbindCollabEvents(channel: PresenceChannel): void {\n for (const event of COLLAB_EVENTS) {\n channel.unbind(event);\n }\n}\n\nconst COLLABORATOR_COLORS = [\n \"#3b82f6\",\n \"#ef4444\",\n \"#10b981\",\n \"#f59e0b\",\n \"#8b5cf6\",\n \"#ec4899\",\n \"#06b6d4\",\n \"#f97316\",\n \"#6366f1\",\n \"#14b8a6\",\n];\n\nexport interface UseCollaborationOptions {\n authManager: AuthManager;\n editor: UseEditorReturn;\n channel: Ref<PresenceChannel | null>;\n onError?: (error: Error) => void;\n onCollaboratorJoined?: (collaborator: Collaborator) => void;\n onCollaboratorLeft?: (collaborator: Collaborator) => void;\n onBlockLocked?: (event: {\n blockId: string;\n collaborator: Collaborator;\n }) => void;\n onBlockUnlocked?: (event: {\n blockId: string;\n collaborator: Collaborator;\n }) => void;\n}\n\nexport interface UseCollaborationReturn {\n collaborators: Ref<Collaborator[]>;\n lockedBlocks: Ref<Map<string, Collaborator>>;\n}\n\nexport function useCollaboration(\n options: UseCollaborationOptions,\n): UseCollaborationReturn & {\n _broadcastOperation: (payload: McpOperationPayload) => void;\n _isProcessingRemoteOperation: () => boolean;\n} {\n const { authManager, editor, channel } = options;\n\n const collaborators = ref<Collaborator[]>([]);\n const lockedBlocks = ref<Map<string, Collaborator>>(new Map());\n\n let colorIndex = 0;\n let isProcessingRemoteOperation = false;\n\n const myUserId = computed(() => authManager.userConfig?.id ?? \"\");\n\n function assignColor(): string {\n const color = COLLABORATOR_COLORS[colorIndex % COLLABORATOR_COLORS.length];\n colorIndex++;\n return color;\n }\n\n function addCollaborator(member: PresenceMember): Collaborator | undefined {\n if (member.id === myUserId.value) {\n return undefined;\n }\n\n if (collaborators.value.some((c) => c.id === member.id)) {\n return undefined;\n }\n\n const collaborator: Collaborator = {\n id: member.id,\n name: member.name,\n color: assignColor(),\n selectedBlockId: null,\n };\n\n collaborators.value = [...collaborators.value, collaborator];\n\n return collaborator;\n }\n\n function removeCollaborator(memberId: string): void {\n const newLockedBlocks = new Map(lockedBlocks.value);\n for (const [blockId, collaborator] of newLockedBlocks) {\n if (collaborator.id === memberId) {\n newLockedBlocks.delete(blockId);\n }\n }\n lockedBlocks.value = newLockedBlocks;\n\n collaborators.value = collaborators.value.filter((c) => c.id !== memberId);\n }\n\n function handleBlockLocked(data: { blockId: string; userId: string }): void {\n const collaborator = collaborators.value.find((c) => c.id === data.userId);\n if (!collaborator) {\n return;\n }\n\n collaborators.value = collaborators.value.map((c) =>\n c.id === data.userId ? { ...c, selectedBlockId: data.blockId } : c,\n );\n\n const newLockedBlocks = new Map(lockedBlocks.value);\n for (const [blockId, holder] of newLockedBlocks) {\n if (holder.id === data.userId) {\n newLockedBlocks.delete(blockId);\n }\n }\n\n newLockedBlocks.set(data.blockId, {\n ...collaborator,\n selectedBlockId: data.blockId,\n });\n lockedBlocks.value = newLockedBlocks;\n\n if (editor.state.selectedBlockId === data.blockId) {\n editor.selectBlock(null);\n }\n }\n\n function handleBlockUnlocked(data: { blockId: string }): void {\n const newLockedBlocks = new Map(lockedBlocks.value);\n const holder = newLockedBlocks.get(data.blockId);\n newLockedBlocks.delete(data.blockId);\n lockedBlocks.value = newLockedBlocks;\n\n if (holder) {\n collaborators.value = collaborators.value.map((c) =>\n c.id === holder.id ? { ...c, selectedBlockId: null } : c,\n );\n }\n }\n\n function handleRemoteOperation(payload: McpOperationPayload): void {\n isProcessingRemoteOperation = true;\n try {\n handleOperation(editor, payload);\n } finally {\n isProcessingRemoteOperation = false;\n }\n }\n\n function broadcastOperation(payload: McpOperationPayload): void {\n if (!channel.value || isProcessingRemoteOperation) {\n return;\n }\n\n channel.value.trigger(\"client-operation\", payload);\n }\n\n function broadcastBlockLocked(blockId: string): void {\n if (!channel.value) {\n return;\n }\n\n channel.value.trigger(\"client-block_locked\", {\n blockId,\n userId: myUserId.value,\n });\n }\n\n function broadcastBlockUnlocked(blockId: string): void {\n if (!channel.value) {\n return;\n }\n\n channel.value.trigger(\"client-block_unlocked\", { blockId });\n }\n\n watch(\n () => editor.state.selectedBlockId,\n (newBlockId, oldBlockId) => {\n if (isProcessingRemoteOperation) {\n return;\n }\n\n if (oldBlockId) {\n broadcastBlockUnlocked(oldBlockId);\n }\n\n if (newBlockId) {\n broadcastBlockLocked(newBlockId);\n }\n },\n );\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n unbindCollabEvents(oldChannel);\n }\n\n if (!newChannel) {\n collaborators.value = [];\n lockedBlocks.value = new Map();\n colorIndex = 0;\n return;\n }\n\n const members = (\n newChannel as PresenceChannel & {\n members: {\n each: (\n callback: (member: { id: string; info: PresenceMember }) => void,\n ) => void;\n };\n }\n ).members;\n if (members) {\n members.each((member: { id: string; info: PresenceMember }) => {\n addCollaborator(member.info);\n });\n }\n\n newChannel.bind(\n \"pusher:member_added\",\n (member: { id: string; info: PresenceMember }) => {\n const collaborator = addCollaborator(member.info);\n if (collaborator) {\n options.onCollaboratorJoined?.(collaborator);\n }\n },\n );\n\n newChannel.bind(\n \"pusher:member_removed\",\n (member: { id: string; info: PresenceMember }) => {\n const collaborator = collaborators.value.find(\n (c) => c.id === member.id,\n );\n removeCollaborator(member.id);\n if (collaborator) {\n options.onCollaboratorLeft?.(collaborator);\n }\n },\n );\n\n newChannel.bind(\n \"client-block_locked\",\n (data: { blockId: string; userId: string }) => {\n handleBlockLocked(data);\n const collaborator = collaborators.value.find(\n (c) => c.id === data.userId,\n );\n if (collaborator) {\n options.onBlockLocked?.({\n blockId: data.blockId,\n collaborator,\n });\n }\n },\n );\n\n newChannel.bind(\"client-block_unlocked\", (data: { blockId: string }) => {\n const holder = lockedBlocks.value.get(data.blockId);\n handleBlockUnlocked(data);\n if (holder) {\n options.onBlockUnlocked?.({\n blockId: data.blockId,\n collaborator: holder,\n });\n }\n });\n\n newChannel.bind(\"client-operation\", (payload: McpOperationPayload) => {\n handleRemoteOperation(payload);\n });\n\n newChannel.bind(\"mcp-operation\", (payload: McpOperationPayload) => {\n handleRemoteOperation(payload);\n });\n });\n\n // The watch above only unbinds when the channel ref *changes*. On scope\n // dispose (component unmount) the watch is auto-stopped but the currently\n // bound listeners stay attached forever — handlers fire on a dead component\n // and accumulate on remount. Tear them down explicitly.\n onScopeDispose(() => {\n if (channel.value) {\n unbindCollabEvents(channel.value);\n }\n });\n\n return {\n collaborators,\n lockedBlocks,\n _broadcastOperation: broadcastOperation,\n _isProcessingRemoteOperation: () => isProcessingRemoteOperation,\n };\n}\n","import type { McpOperationPayload } from \"@templatical/types\";\nimport type { UseEditorReturn } from \"../editor\";\n\ninterface BroadcastTarget {\n _broadcastOperation: (payload: McpOperationPayload) => void;\n}\n\n/**\n * Wraps editor mutation methods to broadcast operations to collaboration\n * peers after each mutation executes. Mutates the editor object in place.\n *\n * Must be applied **before** the history interceptor so the call chain is:\n * history.record() → broadcast + original mutation.\n */\nexport function useCollaborationBroadcast(\n editor: UseEditorReturn,\n collaboration: BroadcastTarget,\n): void {\n const originalAddBlock = editor.addBlock;\n const originalUpdateBlock = editor.updateBlock;\n const originalRemoveBlock = editor.removeBlock;\n const originalMoveBlock = editor.moveBlock;\n const originalUpdateSettings = editor.updateSettings;\n const originalSetContent = editor.setContent;\n\n editor.addBlock = (block, targetSectionId?, columnIndex?, index?) => {\n originalAddBlock(block, targetSectionId, columnIndex, index);\n collaboration._broadcastOperation({\n operation: \"add_block\",\n data: {\n block,\n section_id: targetSectionId,\n column_index: columnIndex,\n index,\n },\n timestamp: Date.now(),\n });\n };\n\n editor.updateBlock = (blockId, updates) => {\n originalUpdateBlock(blockId, updates);\n collaboration._broadcastOperation({\n operation: \"update_block\",\n data: { block_id: blockId, updates },\n timestamp: Date.now(),\n });\n };\n\n editor.removeBlock = (blockId) => {\n originalRemoveBlock(blockId);\n collaboration._broadcastOperation({\n operation: \"delete_block\",\n data: { block_id: blockId },\n timestamp: Date.now(),\n });\n };\n\n editor.moveBlock = (blockId, newIndex, targetSectionId?, columnIndex?) => {\n originalMoveBlock(blockId, newIndex, targetSectionId, columnIndex);\n collaboration._broadcastOperation({\n operation: \"move_block\",\n data: {\n block_id: blockId,\n index: newIndex,\n section_id: targetSectionId,\n column_index: columnIndex,\n },\n timestamp: Date.now(),\n });\n };\n\n editor.updateSettings = (updates) => {\n originalUpdateSettings(updates);\n collaboration._broadcastOperation({\n operation: \"update_settings\",\n data: { updates },\n timestamp: Date.now(),\n });\n };\n\n editor.setContent = (content, markDirty?) => {\n originalSetContent(content, markDirty);\n collaboration._broadcastOperation({\n operation: \"set_content\",\n data: { content },\n timestamp: Date.now(),\n });\n };\n}\n","import type { AuthManager } from \"./auth\";\nimport type { WebSocketConfig } from \"./websocket-client\";\nimport { WebSocketClient } from \"./websocket-client\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { ref, type Ref } from \"vue\";\n\nexport interface UseWebSocketOptions {\n authManager: AuthManager;\n onError?: (error: Error) => void;\n}\n\nexport interface UseWebSocketReturn {\n channel: Ref<PresenceChannel | null>;\n isConnected: Ref<boolean>;\n connect: (templateId: string, config: WebSocketConfig) => Promise<void>;\n disconnect: () => void;\n getSocketId: () => string | null;\n}\n\nexport function useWebSocket(options: UseWebSocketOptions): UseWebSocketReturn {\n const { authManager, onError } = options;\n\n const channel = ref<PresenceChannel | null>(\n null,\n ) as Ref<PresenceChannel | null>;\n const isConnected = ref(false);\n\n let wsClient: WebSocketClient | null = null;\n let channelName: string | null = null;\n\n async function connect(\n templateId: string,\n config: WebSocketConfig,\n ): Promise<void> {\n if (wsClient) {\n return;\n }\n\n wsClient = new WebSocketClient({\n authManager,\n config,\n onError,\n });\n\n await wsClient.connect();\n\n channelName = `presence-template.${templateId}`;\n const presenceChannel = wsClient.subscribePresence(channelName);\n\n presenceChannel.bind(\"pusher:subscription_succeeded\", () => {\n isConnected.value = true;\n channel.value = presenceChannel;\n });\n\n presenceChannel.bind(\"pusher:subscription_error\", (error: unknown) => {\n isConnected.value = false;\n channel.value = null;\n onError?.(\n error instanceof Error\n ? error\n : new Error(\"Failed to subscribe to template channel\"),\n );\n });\n }\n\n function disconnect(): void {\n if (channelName && wsClient) {\n wsClient.unsubscribe(channelName);\n }\n\n wsClient?.disconnect();\n wsClient = null;\n channelName = null;\n channel.value = null;\n isConnected.value = false;\n }\n\n function getSocketId(): string | null {\n return wsClient?.getSocketId() ?? null;\n }\n\n return {\n channel,\n isConnected,\n connect,\n disconnect,\n getSocketId,\n };\n}\n","import type {\n SavedBlock,\n SavedBlockInput,\n SavedBlockPatch,\n SavedBlocksListParams,\n SavedBlocksProvider,\n} from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\n\n/**\n * Cloud-backed {@link SavedBlocksProvider} — the Templatical Cloud adapter for\n * the same contract consumers implement themselves.\n *\n * Auth (JWT via {@link AuthManager}) and project/tenant scoping live entirely\n * on this side of the seam: the shared `useSavedBlocks` composable and the\n * editor UI never see them. Plan gating is applied by the caller before this\n * provider is constructed.\n *\n * Wraps the existing `ApiClient` saved-module endpoints, so the REST contract\n * is unchanged from before saved blocks became an open-source feature.\n *\n * Rows pass straight through, unmapped: the Cloud endpoints speak the same\n * `SavedBlock` shape the contract defines, so this adapter only supplies auth\n * and scoping. That means the payload's field names track the contract — the\n * backend serialises `category`, `canUpdate`, `canDelete`, `createdAt` and\n * `updatedAt`. Until it does, those fields simply arrive absent, which degrades\n * to \"no timestamp label, every action allowed\" rather than breaking.\n */\nexport function createCloudSavedBlocksProvider(\n authManager: AuthManager,\n): SavedBlocksProvider {\n const api = new ApiClient(authManager);\n\n return {\n list(params?: SavedBlocksListParams): Promise<SavedBlock[]> {\n return api.listModules(params?.search, params?.category);\n },\n // All three enabled: Cloud gates saved blocks by plan entitlement above\n // this seam, and row-level permissions arrive as `canUpdate`/`canDelete`\n // on the entries themselves.\n create(input: SavedBlockInput): Promise<SavedBlock> {\n return api.createModule(input);\n },\n update(id: string, patch: SavedBlockPatch): Promise<SavedBlock> {\n return api.updateModule(id, patch);\n },\n delete(id: string): Promise<void> {\n return api.deleteModule(id);\n },\n };\n}\n","import type { Template, TemplateSnapshot } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { ref, type Ref } from \"vue\";\n\nexport interface UseSnapshotHistoryOptions {\n authManager: AuthManager;\n templateId: string;\n onRestore?: (template: Template) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseSnapshotHistoryReturn {\n snapshots: Ref<TemplateSnapshot[]>;\n isLoading: Ref<boolean>;\n isRestoring: Ref<boolean>;\n loadSnapshots: () => Promise<void>;\n restoreSnapshot: (snapshotId: string) => Promise<Template>;\n}\n\nexport function useSnapshotHistory(\n options: UseSnapshotHistoryOptions,\n): UseSnapshotHistoryReturn {\n const api = new ApiClient(options.authManager);\n\n const snapshots = ref<TemplateSnapshot[]>([]);\n const isLoading = ref(false);\n const isRestoring = ref(false);\n\n async function loadSnapshots(): Promise<void> {\n isLoading.value = true;\n try {\n snapshots.value = await api.getSnapshots(options.templateId);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n isLoading.value = false;\n }\n }\n\n async function restoreSnapshot(snapshotId: string): Promise<Template> {\n isRestoring.value = true;\n try {\n const template = await api.restoreSnapshot(\n options.templateId,\n snapshotId,\n );\n options.onRestore?.(template);\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n isRestoring.value = false;\n }\n }\n\n return {\n snapshots,\n isLoading,\n isRestoring,\n loadSnapshots,\n restoreSnapshot,\n };\n}\n","import type {\n ExportResult,\n Template,\n TestEmailConfig,\n} from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { ApiClient } from \"./api\";\nimport type { ComputedRef, Ref } from \"vue\";\nimport { computed, ref, watch } from \"vue\";\n\nexport interface UseTestEmailOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n save: () => Promise<Template>;\n exportHtml: (templateId: string) => Promise<ExportResult>;\n onError?: (error: Error) => void;\n isAuthReady?: Ref<boolean>;\n onBeforeTestEmail?: (html: string) => string | Promise<string>;\n}\n\nexport interface UseTestEmailReturn {\n isEnabled: ComputedRef<boolean>;\n allowedEmails: ComputedRef<string[]>;\n isSending: Ref<boolean>;\n error: Ref<string | null>;\n sendTestEmail: (recipient: string) => Promise<void>;\n}\n\nexport function useTestEmail(options: UseTestEmailOptions): UseTestEmailReturn {\n const {\n authManager,\n getTemplateId,\n save,\n exportHtml,\n onError,\n isAuthReady,\n onBeforeTestEmail,\n } = options;\n const api = new ApiClient(authManager);\n\n const isSending = ref(false);\n const error = ref<string | null>(null);\n\n const testEmailConfig = ref<TestEmailConfig | null>(null);\n\n if (isAuthReady) {\n watch(\n isAuthReady,\n (ready) => {\n if (ready) {\n testEmailConfig.value = authManager.testEmailConfig;\n }\n },\n { immediate: true },\n );\n }\n\n const isEnabled = computed<boolean>(() => testEmailConfig.value !== null);\n\n const allowedEmails = computed<string[]>(\n () => testEmailConfig.value?.allowedEmails ?? [],\n );\n\n async function sendTestEmail(recipient: string): Promise<void> {\n if (!testEmailConfig.value) {\n throw new Error(\"Test email is not enabled for this project\");\n }\n\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before sending a test email\");\n }\n\n isSending.value = true;\n error.value = null;\n\n try {\n await save();\n\n let { html } = await exportHtml(templateId);\n\n if (onBeforeTestEmail) {\n html = await onBeforeTestEmail(html);\n }\n\n await api.sendTestEmail(templateId, {\n recipient,\n html,\n allowed_emails: testEmailConfig.value.allowedEmails,\n signature: testEmailConfig.value.signature,\n });\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to send test email\", { cause: err });\n error.value = wrappedError.message;\n onError?.(wrappedError);\n throw wrappedError;\n } finally {\n isSending.value = false;\n }\n }\n\n return {\n isEnabled,\n allowedEmails,\n isSending,\n error,\n sendTestEmail,\n };\n}\n","import type { CustomFont, ExportResult, FontsConfig } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\n\nexport interface UseExportOptions {\n authManager: AuthManager;\n getFontsConfig?: () => FontsConfig | undefined;\n canUseCustomFonts?: () => boolean;\n}\n\nexport interface UseExportReturn {\n exportHtml: (templateId: string) => Promise<ExportResult>;\n getMjmlSource: (templateId: string) => Promise<string>;\n}\n\nexport function useExport(options: UseExportOptions): UseExportReturn {\n const { authManager, getFontsConfig, canUseCustomFonts } = options;\n const api = new ApiClient(authManager);\n\n function getExportFontsPayload(): {\n customFonts: CustomFont[];\n defaultFallback: string;\n } {\n const fontsConfig = getFontsConfig?.();\n const customFontsAllowed = canUseCustomFonts?.() ?? true;\n\n return {\n customFonts:\n customFontsAllowed && fontsConfig?.customFonts\n ? fontsConfig.customFonts\n : [],\n defaultFallback: fontsConfig?.defaultFallback ?? \"Arial, sans-serif\",\n };\n }\n\n async function exportHtml(templateId: string): Promise<ExportResult> {\n const fontsPayload = getExportFontsPayload();\n const result = await api.exportTemplate(templateId, fontsPayload);\n\n return {\n html: result.html,\n mjml: result.mjml,\n };\n }\n\n async function getMjmlSource(templateId: string): Promise<string> {\n const fontsPayload = getExportFontsPayload();\n const result = await api.exportTemplate(templateId, fontsPayload);\n return result.mjml;\n }\n\n return {\n exportHtml,\n getMjmlSource,\n };\n}\n","import type { PlanConfig, PlanFeatures } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { computed, ref, type ComputedRef, type Ref } from \"vue\";\n\nexport interface UsePlanConfigOptions {\n authManager: AuthManager;\n onError?: (error: Error) => void;\n}\n\nexport interface UsePlanConfigReturn {\n config: Ref<PlanConfig | null>;\n isLoading: Ref<boolean>;\n hasFeature: (feature: keyof PlanFeatures) => boolean;\n features: ComputedRef<PlanFeatures | null>;\n fetchConfig: () => Promise<void>;\n}\n\nexport function usePlanConfig(\n options: UsePlanConfigOptions,\n): UsePlanConfigReturn {\n const { authManager, onError } = options;\n\n const config = ref<PlanConfig | null>(null);\n const isLoading = ref(false);\n\n const apiClient = new ApiClient(authManager);\n\n const features = computed(() => config.value?.features ?? null);\n\n function hasFeature(feature: keyof PlanFeatures): boolean {\n return config.value?.features[feature] ?? false;\n }\n\n async function fetchConfig(): Promise<void> {\n if (isLoading.value) {\n return;\n }\n\n isLoading.value = true;\n\n try {\n config.value = await apiClient.fetchConfig();\n } catch (error) {\n onError?.(\n error instanceof Error\n ? error\n : new Error(\"Failed to fetch config\", { cause: error }),\n );\n } finally {\n isLoading.value = false;\n }\n }\n\n return {\n config,\n isLoading,\n hasFeature,\n features,\n fetchConfig,\n };\n}\n","import type { HealthCheckResult } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES } from \"./url-builder\";\n\ninterface HealthCheckOptions {\n authManager?: AuthManager;\n baseUrl?: string;\n}\n\nconst WS_HANDSHAKE_TIMEOUT = 5000;\n\nfunction resolveHealthUrl(options: HealthCheckOptions): string {\n if (options.authManager) {\n return options.authManager.resolveUrl(API_ROUTES.health);\n }\n\n const base = (options.baseUrl ?? \"https://templatical.com\").replace(\n /\\/$/,\n \"\",\n );\n return `${base}${API_ROUTES.health}`;\n}\n\nasync function checkApiAndAuth(\n url: string,\n authManager?: AuthManager,\n): Promise<{\n api: { ok: boolean; latency: number };\n auth: { ok: boolean; error?: string };\n wsConfig?: { host: string; port: number; app_key: string };\n}> {\n const start = performance.now();\n\n try {\n const response = authManager\n ? await authManager.authenticatedFetch(API_ROUTES.health, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n })\n : await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n });\n\n const latency = Math.round(performance.now() - start);\n\n if (response.status === 401) {\n return {\n api: { ok: true, latency },\n auth: { ok: false, error: \"HTTP 401\" },\n };\n }\n\n if (!response.ok) {\n return {\n api: { ok: false, latency },\n auth: {\n ok: !authManager,\n error: authManager ? `HTTP ${response.status}` : undefined,\n },\n };\n }\n\n const data = await response.json();\n\n return {\n api: { ok: data.status === \"ok\", latency },\n auth: { ok: true },\n wsConfig: data.websocket,\n };\n } catch (error) {\n const latency = Math.round(performance.now() - start);\n\n return {\n api: { ok: false, latency },\n auth: {\n ok: !authManager,\n error: authManager\n ? error instanceof Error\n ? error.message\n : \"Authentication check failed\"\n : undefined,\n },\n };\n }\n}\n\nasync function checkWebSocket(wsConfig?: {\n host: string;\n port: number;\n app_key: string;\n}): Promise<{ ok: boolean; error?: string }> {\n if (!wsConfig?.host || !wsConfig?.app_key) {\n return { ok: false, error: \"WebSocket configuration not available\" };\n }\n\n if (typeof WebSocket === \"undefined\") {\n return {\n ok: false,\n error: \"WebSocket not supported in this environment\",\n };\n }\n\n const protocol = wsConfig.port === 443 ? \"wss\" : \"ws\";\n const url = `${protocol}://${wsConfig.host}:${wsConfig.port}/app/${wsConfig.app_key}?protocol=7&client=js&version=8.4.0-rc2&flash=false`;\n\n return new Promise((resolve) => {\n let ws: WebSocket | null = null;\n\n const timeout = setTimeout(() => {\n ws?.close();\n resolve({ ok: false, error: \"WebSocket connection timed out\" });\n }, WS_HANDSHAKE_TIMEOUT);\n\n try {\n ws = new WebSocket(url);\n } catch (error) {\n // Some browsers throw synchronously from `new WebSocket(...)`\n // (e.g. SecurityError on mixed content, InvalidAccessError on\n // malformed URL). Without this catch the queued timeout would\n // later access `ws` in TDZ and the outer promise would hang.\n clearTimeout(timeout);\n resolve({\n ok: false,\n error:\n error instanceof Error\n ? error.message\n : \"WebSocket connection failed\",\n });\n return;\n }\n\n ws.onopen = () => {\n clearTimeout(timeout);\n ws?.close();\n resolve({ ok: true });\n };\n\n ws.onerror = () => {\n clearTimeout(timeout);\n resolve({ ok: false, error: \"WebSocket connection failed\" });\n };\n });\n}\n\nexport async function performHealthCheck(\n options: HealthCheckOptions = {},\n): Promise<HealthCheckResult> {\n const healthUrl = resolveHealthUrl(options);\n\n const result = await checkApiAndAuth(healthUrl, options.authManager);\n const wsResult = await checkWebSocket(result.wsConfig);\n\n return {\n api: result.api,\n websocket: wsResult,\n auth: result.auth,\n overall: result.api.ok && result.auth.ok,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { McpOperationPayload } from \"@templatical/types\";\nimport { handleOperation } from \"./mcp-operation-handler\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { watch, type Ref } from \"vue\";\n\nexport interface UseMcpListenerOptions {\n editor: UseEditorReturn;\n channel: Ref<PresenceChannel | null>;\n onOperation?: (payload: McpOperationPayload) => void;\n}\n\nexport function useMcpListener(options: UseMcpListenerOptions): void {\n const { editor, channel, onOperation } = options;\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n oldChannel.unbind(\"mcp-operation\");\n }\n\n if (newChannel) {\n newChannel.bind(\"mcp-operation\", (payload: McpOperationPayload) => {\n handleOperation(editor, payload);\n onOperation?.(payload);\n });\n }\n });\n}\n"],"mappings":"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"}
@@ -153,30 +153,6 @@ var e = {
153
153
  blockLockedBy: "Wird bearbeitet von {name}",
154
154
  usersOnline: "{count} Benutzer online"
155
155
  },
156
- modules: {
157
- title: "Gespeicherte Module",
158
- saveAsModule: "Als Modul speichern",
159
- moduleName: "Modulname",
160
- moduleNamePlaceholder: "z.B. Header, Footer, CTA...",
161
- selectBlocks: "Blöcke auswählen",
162
- save: "Modul speichern",
163
- saving: "Wird gespeichert...",
164
- cancel: "Abbrechen",
165
- noModules: "Noch keine gespeicherten Module",
166
- noModulesHint: "Speichern Sie Blöcke aus Ihren Vorlagen, um sie später wiederzuverwenden.",
167
- search: "Module suchen...",
168
- insert: "Einfügen",
169
- delete: "Löschen",
170
- deleteConfirm: "Dieses Modul löschen?",
171
- blockCount: "{count} Block/Blöcke",
172
- browse: "Module durchsuchen",
173
- selectToPreview: "Modul auswählen für Vorschau",
174
- insertAtBeginning: "Am Anfang",
175
- insertAfterBlock: "Nach {block}",
176
- insertAtEnd: "Am Ende",
177
- insertPosition: "Einfügeposition",
178
- close: "Schließen"
179
- },
180
156
  designReference: {
181
157
  title: "Designvorlage",
182
158
  button: "Design",
@@ -205,3 +181,5 @@ var e = {
205
181
  };
206
182
  //#endregion
207
183
  export { e as default };
184
+
185
+ //# sourceMappingURL=de-Bw6fB5JU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"de-CTYXVU9v.js","names":[],"sources":["../../../src/i18n/locales/cloud/de.ts"],"sourcesContent":["import type en from \"./en\";\n\nconst de: typeof en = {\n loading: {\n initializing: \"Initialisieren...\",\n },\n error: {\n title: \"Etwas ist schiefgelaufen\",\n defaultMessage:\n \"Der Editor konnte keine Verbindung zu Templatical herstellen. Überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut.\",\n authFailed:\n \"Authentifizierung fehlgeschlagen. Bitte überprüfen Sie Ihre Anmeldedaten.\",\n templateNotFound:\n \"Die angeforderte Vorlage konnte nicht gefunden werden. Bitte überprüfen Sie die Vorlagen-ID.\",\n retry: \"Erneut versuchen\",\n },\n header: {\n title: \"Templatical\",\n unsaved: \"Nicht gespeichert\",\n saving: \"Speichern...\",\n saved: \"Gespeichert\",\n saveFailed: \"Speichern fehlgeschlagen\",\n save: \"Speichern\",\n templatesUsed: \"{used}/{max} Vorlagen verwendet\",\n },\n snapshotPreview: {\n message: \"Sie sehen einen früheren Snapshot dieser Vorlage.\",\n cancel: \"Abbrechen\",\n restore: \"Diesen Snapshot wiederherstellen\",\n },\n snapshotHistory: {\n tooltip: \"Versionsverlauf\",\n dropdownTitle: \"Versionsverlauf\",\n noSnapshots: \"Noch keine Versionen\",\n auto: \"auto\",\n justNow: \"Gerade eben\",\n minutesAgo: \"vor {minutes} Min.\",\n hoursAgo: \"vor {hours} Std.\",\n daysAgo: \"vor {days} Tagen\",\n olderSnapshot: \"Ältere Version\",\n newerSnapshot: \"Neuere Version\",\n },\n testEmail: {\n title: \"Test-E-Mail senden\",\n recipientLabel: \"Empfänger\",\n send: \"Senden\",\n sending: \"Wird gesendet...\",\n cancel: \"Abbrechen\",\n success: \"Test-E-Mail erfolgreich gesendet\",\n button: \"Test\",\n },\n aiRewrite: {\n title: \"KI-Umschreibung\",\n tone: \"Tonalität\",\n length: \"Länge\",\n clarity: \"Klarheit\",\n professional: \"Professionell\",\n casual: \"Locker\",\n friendly: \"Freundlich\",\n urgent: \"Dringend\",\n persuasive: \"Überzeugend\",\n shorter: \"Kürzer\",\n longer: \"Länger\",\n summarize: \"Zusammenfassen\",\n simplify: \"Vereinfachen\",\n fixGrammar: \"Grammatik korrigieren\",\n improveReadability: \"Lesbarkeit verbessern\",\n customInstruction: \"Eigene Anweisung\",\n customPlaceholder: \"Beschreiben Sie die gewünschte Umschreibung...\",\n rewrite: \"Umschreiben\",\n rewriting: \"Wird umgeschrieben...\",\n undo: \"Rückgängig\",\n redo: \"Wiederholen\",\n refine: \"Weiter verfeinern\",\n error: \"Text konnte nicht umgeschrieben werden\",\n },\n aiChat: {\n title: \"KI-Assistent\",\n button: \"KI\",\n inputPlaceholder: \"Beschreiben Sie Ihre E-Mail-Vorlage...\",\n send: \"Senden\",\n generating: \"Wird generiert...\",\n applied: \"Änderungen auf Vorlage angewendet.\",\n applyFailed:\n \"Änderungen konnten nicht auf die Vorlage angewendet werden. Bitte versuchen Sie es erneut.\",\n revert: \"Änderungen rückgängig\",\n reapply: \"Änderungen erneut anwenden\",\n error: \"Vorlage konnte nicht generiert werden\",\n clear: \"Chat leeren\",\n placeholder:\n \"Beschreiben Sie die E-Mail-Vorlage, die Sie erstellen möchten, oder bitten Sie um Änderungen an der aktuellen.\",\n loadingHistory: \"Konversation wird geladen...\",\n },\n scoring: {\n button: \"Bewertung\",\n title: \"Vorlagenbewertung\",\n rescore: \"Neu bewerten\",\n scoring: \"Vorlage wird analysiert...\",\n overallScore: \"Gesamtbewertung\",\n categories: {\n spam: \"Spam-Risiko\",\n readability: \"Lesbarkeit\",\n accessibility: \"Barrierefreiheit\",\n bestPractices: \"Best Practices\",\n },\n severity: {\n high: \"Hoch\",\n medium: \"Mittel\",\n low: \"Niedrig\",\n },\n fix: \"Mit KI beheben\",\n fixing: \"Wird behoben...\",\n fixed: \"Behoben\",\n findings: \"Ergebnisse\",\n noFindings: \"Keine Probleme gefunden\",\n error: \"Vorlage konnte nicht analysiert werden\",\n fixError: \"Korrektur konnte nicht angewendet werden\",\n emptyState:\n \"Bewerten Sie Ihre Vorlage, um umsetzbare Rückmeldungen zu Spam-Risiko, Lesbarkeit, Barrierefreiheit und Best Practices zu erhalten.\",\n },\n aiMenu: {\n aiAssistant: \"KI-Assistent\",\n aiAssistantDesc:\n \"Mit KI chatten, um Ihre Vorlage zu erstellen oder zu ändern\",\n designToTemplate: \"Design zu Vorlage\",\n designToTemplateDesc: \"Vorlage aus einem Bild oder PDF generieren\",\n templateScore: \"Vorlagenbewertung\",\n templateScoreDesc: \"Qualität, Spam-Risiko und Barrierefreiheit analysieren\",\n disclaimer:\n \"KI kann Fehler machen. Bitte überprüfen Sie die Ergebnisse vor der Genehmigung.\",\n },\n comments: {\n title: \"Kommentare\",\n placeholder: \"Kommentar schreiben...\",\n replyPlaceholder: \"Antwort schreiben...\",\n reply: \"Antworten\",\n resolve: \"Lösen\",\n unresolve: \"Wiedereröffnen\",\n resolved: \"Gelöst\",\n delete: \"Löschen\",\n edit: \"Bearbeiten\",\n cancel: \"Abbrechen\",\n save: \"Speichern\",\n noComments: \"Noch keine Kommentare\",\n noCommentsHint:\n \"Starten Sie eine Konversation, indem Sie einen Kommentar zur Vorlage oder einem bestimmten Block hinzufügen.\",\n addComment: \"Kommentar hinzufügen\",\n deleteConfirm: \"Diesen Kommentar löschen?\",\n filterAll: \"Alle\",\n filterUnresolved: \"Ungelöst\",\n filterBlock: \"Dieser Block\",\n ownedByYou: \"Sie\",\n edited: \"bearbeitet\",\n resolvedBy: \"Gelöst von {name}\",\n replyOne: \"{count} Antwort\",\n replyMany: \"{count} Antworten\",\n missingBlock: \"Fehlender Block\",\n saveTemplateFirst:\n \"Speichern Sie die Vorlage, bevor Sie diesen Block kommentieren.\",\n button: \"Kommentare\",\n },\n collaboration: {\n connected: \"Zusammenarbeit aktiv\",\n disconnected: \"Zusammenarbeit getrennt\",\n reconnecting: \"Verbindung wird wiederhergestellt...\",\n blockLockedBy: \"Wird bearbeitet von {name}\",\n usersOnline: \"{count} Benutzer online\",\n },\n modules: {\n title: \"Gespeicherte Module\",\n saveAsModule: \"Als Modul speichern\",\n moduleName: \"Modulname\",\n moduleNamePlaceholder: \"z.B. Header, Footer, CTA...\",\n selectBlocks: \"Blöcke auswählen\",\n save: \"Modul speichern\",\n saving: \"Wird gespeichert...\",\n cancel: \"Abbrechen\",\n noModules: \"Noch keine gespeicherten Module\",\n noModulesHint:\n \"Speichern Sie Blöcke aus Ihren Vorlagen, um sie später wiederzuverwenden.\",\n search: \"Module suchen...\",\n insert: \"Einfügen\",\n delete: \"Löschen\",\n deleteConfirm: \"Dieses Modul löschen?\",\n blockCount: \"{count} Block/Blöcke\",\n browse: \"Module durchsuchen\",\n selectToPreview: \"Modul auswählen für Vorschau\",\n insertAtBeginning: \"Am Anfang\",\n insertAfterBlock: \"Nach {block}\",\n insertAtEnd: \"Am Ende\",\n insertPosition: \"Einfügeposition\",\n close: \"Schließen\",\n },\n designReference: {\n title: \"Designvorlage\",\n button: \"Design\",\n uploadImage: \"Bild\",\n uploadPdf: \"PDF\",\n dropHint: \"Datei hierher ziehen oder klicken zum Durchsuchen\",\n acceptedImages: \"PNG, JPG, WebP (max. 10 MB)\",\n acceptedPdf: \"PDF (max. 10 MB)\",\n promptLabel: \"Anweisungen (optional)\",\n promptPlaceholder:\n \"Beschreiben Sie Anpassungen oder Wünsche für die generierte Vorlage...\",\n generate: \"Aus Design generieren\",\n generating: \"Design wird analysiert und Vorlage generiert...\",\n replaceWarning:\n \"Die Generierung aus einer Designvorlage ersetzt den vorhandenen Vorlageninhalt.\",\n replaceConfirm: \"Ersetzen und generieren\",\n replaceCancel: \"Abbrechen\",\n error: \"Vorlage konnte nicht aus Design generiert werden\",\n fileTooLarge: \"Datei ist zu groß. Maximale Größe ist 10 MB.\",\n invalidFileType:\n \"Dieser Dateityp wird nicht unterstützt. Laden Sie eine PNG-, JPG-, WebP- oder PDF-Datei hoch.\",\n },\n\n saveGate: {\n title: \"Barrierefreiheitsfehler blockieren das Speichern\",\n body: \"Ihr Plan blockiert das Speichern, solange Fehler bestehen. Beheben Sie die folgenden Punkte oder speichern Sie trotzdem.\",\n cancel: \"Prüfen und beheben\",\n confirm: \"Trotzdem speichern\",\n },\n};\n\nexport default de;\n"],"mappings":"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"}
1
+ {"version":3,"file":"de-Bw6fB5JU.js","names":[],"sources":["../../../src/i18n/locales/cloud/de.ts"],"sourcesContent":["import type en from \"./en\";\n\nconst de: typeof en = {\n loading: {\n initializing: \"Initialisieren...\",\n },\n error: {\n title: \"Etwas ist schiefgelaufen\",\n defaultMessage:\n \"Der Editor konnte keine Verbindung zu Templatical herstellen. Überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut.\",\n authFailed:\n \"Authentifizierung fehlgeschlagen. Bitte überprüfen Sie Ihre Anmeldedaten.\",\n templateNotFound:\n \"Die angeforderte Vorlage konnte nicht gefunden werden. Bitte überprüfen Sie die Vorlagen-ID.\",\n retry: \"Erneut versuchen\",\n },\n header: {\n title: \"Templatical\",\n unsaved: \"Nicht gespeichert\",\n saving: \"Speichern...\",\n saved: \"Gespeichert\",\n saveFailed: \"Speichern fehlgeschlagen\",\n save: \"Speichern\",\n templatesUsed: \"{used}/{max} Vorlagen verwendet\",\n },\n snapshotPreview: {\n message: \"Sie sehen einen früheren Snapshot dieser Vorlage.\",\n cancel: \"Abbrechen\",\n restore: \"Diesen Snapshot wiederherstellen\",\n },\n snapshotHistory: {\n tooltip: \"Versionsverlauf\",\n dropdownTitle: \"Versionsverlauf\",\n noSnapshots: \"Noch keine Versionen\",\n auto: \"auto\",\n justNow: \"Gerade eben\",\n minutesAgo: \"vor {minutes} Min.\",\n hoursAgo: \"vor {hours} Std.\",\n daysAgo: \"vor {days} Tagen\",\n olderSnapshot: \"Ältere Version\",\n newerSnapshot: \"Neuere Version\",\n },\n testEmail: {\n title: \"Test-E-Mail senden\",\n recipientLabel: \"Empfänger\",\n send: \"Senden\",\n sending: \"Wird gesendet...\",\n cancel: \"Abbrechen\",\n success: \"Test-E-Mail erfolgreich gesendet\",\n button: \"Test\",\n },\n aiRewrite: {\n title: \"KI-Umschreibung\",\n tone: \"Tonalität\",\n length: \"Länge\",\n clarity: \"Klarheit\",\n professional: \"Professionell\",\n casual: \"Locker\",\n friendly: \"Freundlich\",\n urgent: \"Dringend\",\n persuasive: \"Überzeugend\",\n shorter: \"Kürzer\",\n longer: \"Länger\",\n summarize: \"Zusammenfassen\",\n simplify: \"Vereinfachen\",\n fixGrammar: \"Grammatik korrigieren\",\n improveReadability: \"Lesbarkeit verbessern\",\n customInstruction: \"Eigene Anweisung\",\n customPlaceholder: \"Beschreiben Sie die gewünschte Umschreibung...\",\n rewrite: \"Umschreiben\",\n rewriting: \"Wird umgeschrieben...\",\n undo: \"Rückgängig\",\n redo: \"Wiederholen\",\n refine: \"Weiter verfeinern\",\n error: \"Text konnte nicht umgeschrieben werden\",\n },\n aiChat: {\n title: \"KI-Assistent\",\n button: \"KI\",\n inputPlaceholder: \"Beschreiben Sie Ihre E-Mail-Vorlage...\",\n send: \"Senden\",\n generating: \"Wird generiert...\",\n applied: \"Änderungen auf Vorlage angewendet.\",\n applyFailed:\n \"Änderungen konnten nicht auf die Vorlage angewendet werden. Bitte versuchen Sie es erneut.\",\n revert: \"Änderungen rückgängig\",\n reapply: \"Änderungen erneut anwenden\",\n error: \"Vorlage konnte nicht generiert werden\",\n clear: \"Chat leeren\",\n placeholder:\n \"Beschreiben Sie die E-Mail-Vorlage, die Sie erstellen möchten, oder bitten Sie um Änderungen an der aktuellen.\",\n loadingHistory: \"Konversation wird geladen...\",\n },\n scoring: {\n button: \"Bewertung\",\n title: \"Vorlagenbewertung\",\n rescore: \"Neu bewerten\",\n scoring: \"Vorlage wird analysiert...\",\n overallScore: \"Gesamtbewertung\",\n categories: {\n spam: \"Spam-Risiko\",\n readability: \"Lesbarkeit\",\n accessibility: \"Barrierefreiheit\",\n bestPractices: \"Best Practices\",\n },\n severity: {\n high: \"Hoch\",\n medium: \"Mittel\",\n low: \"Niedrig\",\n },\n fix: \"Mit KI beheben\",\n fixing: \"Wird behoben...\",\n fixed: \"Behoben\",\n findings: \"Ergebnisse\",\n noFindings: \"Keine Probleme gefunden\",\n error: \"Vorlage konnte nicht analysiert werden\",\n fixError: \"Korrektur konnte nicht angewendet werden\",\n emptyState:\n \"Bewerten Sie Ihre Vorlage, um umsetzbare Rückmeldungen zu Spam-Risiko, Lesbarkeit, Barrierefreiheit und Best Practices zu erhalten.\",\n },\n aiMenu: {\n aiAssistant: \"KI-Assistent\",\n aiAssistantDesc:\n \"Mit KI chatten, um Ihre Vorlage zu erstellen oder zu ändern\",\n designToTemplate: \"Design zu Vorlage\",\n designToTemplateDesc: \"Vorlage aus einem Bild oder PDF generieren\",\n templateScore: \"Vorlagenbewertung\",\n templateScoreDesc: \"Qualität, Spam-Risiko und Barrierefreiheit analysieren\",\n disclaimer:\n \"KI kann Fehler machen. Bitte überprüfen Sie die Ergebnisse vor der Genehmigung.\",\n },\n comments: {\n title: \"Kommentare\",\n placeholder: \"Kommentar schreiben...\",\n replyPlaceholder: \"Antwort schreiben...\",\n reply: \"Antworten\",\n resolve: \"Lösen\",\n unresolve: \"Wiedereröffnen\",\n resolved: \"Gelöst\",\n delete: \"Löschen\",\n edit: \"Bearbeiten\",\n cancel: \"Abbrechen\",\n save: \"Speichern\",\n noComments: \"Noch keine Kommentare\",\n noCommentsHint:\n \"Starten Sie eine Konversation, indem Sie einen Kommentar zur Vorlage oder einem bestimmten Block hinzufügen.\",\n addComment: \"Kommentar hinzufügen\",\n deleteConfirm: \"Diesen Kommentar löschen?\",\n filterAll: \"Alle\",\n filterUnresolved: \"Ungelöst\",\n filterBlock: \"Dieser Block\",\n ownedByYou: \"Sie\",\n edited: \"bearbeitet\",\n resolvedBy: \"Gelöst von {name}\",\n replyOne: \"{count} Antwort\",\n replyMany: \"{count} Antworten\",\n missingBlock: \"Fehlender Block\",\n saveTemplateFirst:\n \"Speichern Sie die Vorlage, bevor Sie diesen Block kommentieren.\",\n button: \"Kommentare\",\n },\n collaboration: {\n connected: \"Zusammenarbeit aktiv\",\n disconnected: \"Zusammenarbeit getrennt\",\n reconnecting: \"Verbindung wird wiederhergestellt...\",\n blockLockedBy: \"Wird bearbeitet von {name}\",\n usersOnline: \"{count} Benutzer online\",\n },\n designReference: {\n title: \"Designvorlage\",\n button: \"Design\",\n uploadImage: \"Bild\",\n uploadPdf: \"PDF\",\n dropHint: \"Datei hierher ziehen oder klicken zum Durchsuchen\",\n acceptedImages: \"PNG, JPG, WebP (max. 10 MB)\",\n acceptedPdf: \"PDF (max. 10 MB)\",\n promptLabel: \"Anweisungen (optional)\",\n promptPlaceholder:\n \"Beschreiben Sie Anpassungen oder Wünsche für die generierte Vorlage...\",\n generate: \"Aus Design generieren\",\n generating: \"Design wird analysiert und Vorlage generiert...\",\n replaceWarning:\n \"Die Generierung aus einer Designvorlage ersetzt den vorhandenen Vorlageninhalt.\",\n replaceConfirm: \"Ersetzen und generieren\",\n replaceCancel: \"Abbrechen\",\n error: \"Vorlage konnte nicht aus Design generiert werden\",\n fileTooLarge: \"Datei ist zu groß. Maximale Größe ist 10 MB.\",\n invalidFileType:\n \"Dieser Dateityp wird nicht unterstützt. Laden Sie eine PNG-, JPG-, WebP- oder PDF-Datei hoch.\",\n },\n\n saveGate: {\n title: \"Barrierefreiheitsfehler blockieren das Speichern\",\n body: \"Ihr Plan blockiert das Speichern, solange Fehler bestehen. Beheben Sie die folgenden Punkte oder speichern Sie trotzdem.\",\n cancel: \"Prüfen und beheben\",\n confirm: \"Trotzdem speichern\",\n },\n};\n\nexport default de;\n"],"mappings":";AAEA,IAAM,IAAgB;CACpB,SAAS,EACP,cAAc,oBAChB;CACA,OAAO;EACL,OAAO;EACP,gBACE;EACF,YACE;EACF,kBACE;EACF,OAAO;CACT;CACA,QAAQ;EACN,OAAO;EACP,SAAS;EACT,QAAQ;EACR,OAAO;EACP,YAAY;EACZ,MAAM;EACN,eAAe;CACjB;CACA,iBAAiB;EACf,SAAS;EACT,QAAQ;EACR,SAAS;CACX;CACA,iBAAiB;EACf,SAAS;EACT,eAAe;EACf,aAAa;EACb,MAAM;EACN,SAAS;EACT,YAAY;EACZ,UAAU;EACV,SAAS;EACT,eAAe;EACf,eAAe;CACjB;CACA,WAAW;EACT,OAAO;EACP,gBAAgB;EAChB,MAAM;EACN,SAAS;EACT,QAAQ;EACR,SAAS;EACT,QAAQ;CACV;CACA,WAAW;EACT,OAAO;EACP,MAAM;EACN,QAAQ;EACR,SAAS;EACT,cAAc;EACd,QAAQ;EACR,UAAU;EACV,QAAQ;EACR,YAAY;EACZ,SAAS;EACT,QAAQ;EACR,WAAW;EACX,UAAU;EACV,YAAY;EACZ,oBAAoB;EACpB,mBAAmB;EACnB,mBAAmB;EACnB,SAAS;EACT,WAAW;EACX,MAAM;EACN,MAAM;EACN,QAAQ;EACR,OAAO;CACT;CACA,QAAQ;EACN,OAAO;EACP,QAAQ;EACR,kBAAkB;EAClB,MAAM;EACN,YAAY;EACZ,SAAS;EACT,aACE;EACF,QAAQ;EACR,SAAS;EACT,OAAO;EACP,OAAO;EACP,aACE;EACF,gBAAgB;CAClB;CACA,SAAS;EACP,QAAQ;EACR,OAAO;EACP,SAAS;EACT,SAAS;EACT,cAAc;EACd,YAAY;GACV,MAAM;GACN,aAAa;GACb,eAAe;GACf,eAAe;EACjB;EACA,UAAU;GACR,MAAM;GACN,QAAQ;GACR,KAAK;EACP;EACA,KAAK;EACL,QAAQ;EACR,OAAO;EACP,UAAU;EACV,YAAY;EACZ,OAAO;EACP,UAAU;EACV,YACE;CACJ;CACA,QAAQ;EACN,aAAa;EACb,iBACE;EACF,kBAAkB;EAClB,sBAAsB;EACtB,eAAe;EACf,mBAAmB;EACnB,YACE;CACJ;CACA,UAAU;EACR,OAAO;EACP,aAAa;EACb,kBAAkB;EAClB,OAAO;EACP,SAAS;EACT,WAAW;EACX,UAAU;EACV,QAAQ;EACR,MAAM;EACN,QAAQ;EACR,MAAM;EACN,YAAY;EACZ,gBACE;EACF,YAAY;EACZ,eAAe;EACf,WAAW;EACX,kBAAkB;EAClB,aAAa;EACb,YAAY;EACZ,QAAQ;EACR,YAAY;EACZ,UAAU;EACV,WAAW;EACX,cAAc;EACd,mBACE;EACF,QAAQ;CACV;CACA,eAAe;EACb,WAAW;EACX,cAAc;EACd,cAAc;EACd,eAAe;EACf,aAAa;CACf;CACA,iBAAiB;EACf,OAAO;EACP,QAAQ;EACR,aAAa;EACb,WAAW;EACX,UAAU;EACV,gBAAgB;EAChB,aAAa;EACb,aAAa;EACb,mBACE;EACF,UAAU;EACV,YAAY;EACZ,gBACE;EACF,gBAAgB;EAChB,eAAe;EACf,OAAO;EACP,cAAc;EACd,iBACE;CACJ;CAEA,UAAU;EACR,OAAO;EACP,MAAM;EACN,QAAQ;EACR,SAAS;CACX;AACF"}
@@ -86,7 +86,7 @@ var e = {
86
86
  duplicate: "Block duplizieren",
87
87
  delete: "Block löschen",
88
88
  hiddenOnViewport: "Ausgeblendet auf {viewport}",
89
- saveAsModule: "Als Modul speichern",
89
+ saveAsBlock: "Als Block speichern",
90
90
  conditionToggle: "Anzeigebedingung umschalten",
91
91
  comments: "Kommentare ({count})",
92
92
  lifted: "{block} angehoben. Position {position} von {total}.",
@@ -522,8 +522,55 @@ var e = {
522
522
  cropOptional: "(optional)",
523
523
  storageTooltip: "{used} von {total} verwendet ({remaining} verfügbar)"
524
524
  },
525
+ savedBlocks: {
526
+ title: "Gespeicherte Blöcke",
527
+ saveAsBlock: "Als Block speichern",
528
+ name: "Name",
529
+ namePlaceholder: "z.B. Header, Footer, CTA...",
530
+ save: "Block speichern",
531
+ saving: "Wird gespeichert...",
532
+ cancel: "Abbrechen",
533
+ empty: "Noch keine gespeicherten Blöcke",
534
+ emptyHint: "Speichern Sie Blöcke aus Ihren Vorlagen, um sie später wiederzuverwenden.",
535
+ noResults: "Keine gespeicherten Blöcke gefunden",
536
+ search: "Gespeicherte Blöcke suchen...",
537
+ loading: "Gespeicherte Blöcke werden geladen…",
538
+ category: "Kategorie",
539
+ categoryPlaceholder: "z. B. Kopfzeilen, Aktionen... (optional)",
540
+ allCategories: "Alle Kategorien",
541
+ filterByCategory: "Nach Kategorie filtern",
542
+ insert: "Einfügen",
543
+ rename: "Umbenennen",
544
+ delete: "Löschen",
545
+ deleteConfirm: "Diesen gespeicherten Block löschen?",
546
+ blockCount: "{count} Block/Blöcke",
547
+ browse: "Gespeicherte Blöcke durchsuchen",
548
+ selectToPreview: "Gespeicherten Block für Vorschau auswählen",
549
+ insertAtBeginning: "Am Anfang",
550
+ insertAfterBlock: "Nach {block}",
551
+ insertAtEnd: "Am Ende",
552
+ insertPosition: "Einfügeposition",
553
+ close: "Schließen",
554
+ pickToolbar: "Auswahl für gespeicherten Block",
555
+ pickCount: "{count} Block/Blöcke ausgewählt",
556
+ pickHint: "Blöcke anklicken, um sie hinzuzufügen oder zu entfernen",
557
+ savingCount: "{count} Block/Blöcke werden gespeichert:",
558
+ reorderHint: "Zum Umsortieren ziehen — in dieser Reihenfolge werden die Blöcke gespeichert",
559
+ reorderHandle: "{block} umsortieren, Position {position} von {total}",
560
+ reorderAnnouncement: "{block} an Position {position} von {total} verschoben",
561
+ expand: "Aufklappen",
562
+ collapse: "Zuklappen",
563
+ expandPreview: "Vorschau von {block} aufklappen",
564
+ collapsePreview: "Vorschau von {block} zuklappen",
565
+ time: {
566
+ justNow: "Gerade eben",
567
+ minutesAgo: "vor {minutes} Min.",
568
+ hoursAgo: "vor {hours} Std.",
569
+ daysAgo: "vor {days} Tagen"
570
+ }
571
+ },
525
572
  sidebarNav: {
526
- browseModules: "Gespeicherte Module durchsuchen",
573
+ browseSavedBlocks: "Gespeicherte Blöcke durchsuchen",
527
574
  expandSidebar: "Block-Seitenleiste erweitern",
528
575
  palette: "Blockpalette",
529
576
  insertBlock: "{block}-Block einfügen"
@@ -560,4 +607,4 @@ var e = {
560
607
  //#endregion
561
608
  export { e as default };
562
609
 
563
- //# sourceMappingURL=de-CgGOnerg.js.map
610
+ //# sourceMappingURL=de-D7WbpFBR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"de-D7WbpFBR.js","names":[],"sources":["../../../src/i18n/locales/de.ts"],"sourcesContent":["import type en from \"./en\";\n\nconst de: typeof en = {\n // Footer (OSS only)\n footer: {\n poweredBy: \"Erstellt mit\",\n openSource: \"Open Source\",\n },\n\n // History (undo/redo)\n history: {\n undo: \"Rückgängig\",\n redo: \"Wiederholen\",\n collabWarning:\n \"Rückgängig machen kann die Änderungen anderer Mitarbeiter beeinflussen\",\n },\n\n // Viewport toggle\n viewport: {\n label: \"Ansichtsgröße\",\n desktop: \"Desktop\",\n mobile: \"Mobil\",\n },\n\n // Dark mode preview\n darkMode: {\n enable: \"Dunkelmodus-Vorschau\",\n disable: \"Hellmodus-Vorschau\",\n },\n\n // Preview mode\n previewMode: {\n enable: \"Vorschaumodus\",\n disable: \"Vorschau beenden\",\n },\n\n // Sidebar - Block types\n blocks: {\n section: \"Abschnitt\",\n image: \"Bild\",\n title: \"Titel\",\n paragraph: \"Absatz\",\n button: \"Schaltfläche\",\n divider: \"Trennlinie\",\n video: \"Video\",\n social: \"Sozial\",\n spacer: \"Abstand\",\n html: \"HTML\",\n menu: \"Menü\",\n table: \"Tabelle\",\n countdown: \"Countdown\",\n },\n\n // Right sidebar\n sidebar: {\n content: \"Inhalt\",\n settings: \"Einstellungen\",\n noSelection: \"Kein Element ausgewählt\",\n noSelectionHint:\n \"Wählen Sie einen Block auf der Leinwand aus, um ihn zu bearbeiten\",\n },\n\n // Toolbar - Common\n toolbar: {\n duplicate: \"Duplizieren\",\n delete: \"Löschen\",\n },\n\n // Title editor toolbar\n titleEditor: {\n toolbar: \"Titelformatierung\",\n bold: \"Fett (Strg+B)\",\n italic: \"Kursiv (Strg+I)\",\n addLink: \"Link hinzufügen\",\n },\n\n // Paragraph editor toolbar\n paragraphEditor: {\n toolbar: \"Textformatierung\",\n bold: \"Fett (Strg+B)\",\n italic: \"Kursiv (Strg+I)\",\n underline: \"Unterstrichen (Strg+U)\",\n strikethrough: \"Durchgestrichen\",\n subscript: \"Tiefgestellt\",\n superscript: \"Hochgestellt\",\n addLink: \"Link hinzufügen\",\n bulletList: \"Aufzählungsliste\",\n numberedList: \"Nummerierte Liste\",\n alignLeft: \"Linksbündig\",\n alignCenter: \"Zentriert\",\n alignRight: \"Rechtsbündig\",\n clearFormatting: \"Formatierung entfernen\",\n insertEmoji: \"Emoji einfügen\",\n fontFamily: \"Schriftart\",\n defaultFont: \"Standard\",\n fontSize: \"Schriftgröße\",\n defaultSize: \"Standard\",\n textColor: \"Textfarbe\",\n highlightColor: \"Hervorhebungsfarbe\",\n lineHeight: \"Zeilenhöhe\",\n letterSpacing: \"Zeichenabstand\",\n emojiItemLabel: \"Emoji {emoji} einfügen\",\n closeEmojiPicker: \"Emoji-Auswahl schließen\",\n },\n\n // Block actions (BlockWrapper)\n blockActions: {\n drag: \"Zum Sortieren ziehen oder Leertaste drücken, um mit der Tastatur zu verschieben\",\n dragLifted:\n \"{block} wird verschoben. Pfeiltasten zum Positionieren, Leer- oder Eingabetaste zum Ablegen, Esc zum Abbrechen.\",\n duplicate: \"Block duplizieren\",\n delete: \"Block löschen\",\n hiddenOnViewport: \"Ausgeblendet auf {viewport}\",\n saveAsBlock: \"Als Block speichern\",\n conditionToggle: \"Anzeigebedingung umschalten\",\n comments: \"Kommentare ({count})\",\n lifted: \"{block} angehoben. Position {position} von {total}.\",\n moved: \"{block} auf Position {position} von {total} verschoben.\",\n dropped: \"{block} auf Position {position} von {total} abgelegt.\",\n cancelled:\n \"Verschieben abgebrochen. {block} auf Position {position} zurückgesetzt.\",\n },\n\n // Toolbar - Section\n section: {\n dropHere: \"Blöcke hierher ziehen\",\n columns: \"Spalten\",\n column1: \"1 Spalte\",\n column2: \"2 Spalten\",\n column3: \"3 Spalten\",\n ratio12: \"1:2 Verhältnis\",\n ratio21: \"2:1 Verhältnis\",\n borderRadius: \"Eckenradius\",\n wrapperEnable: \"Wrapper hinzufügen\",\n stackOnMobile: \"Auf Mobilgeräten stapeln\",\n },\n\n // Text editor link dialog\n linkDialog: {\n editLink: \"Link bearbeiten\",\n insertLink: \"Link einfügen\",\n updateLink: \"Link aktualisieren\",\n removeLink: \"Link entfernen\",\n cancel: \"Abbrechen\",\n urlPlaceholder: \"https://beispiel.de\",\n urlLabel: \"URL\",\n colorLabel: \"Linkfarbe\",\n },\n\n // Toolbar - Title\n title: {\n level: \"Überschriftenebene\",\n heading1: \"Überschrift 1 (36px)\",\n heading2: \"Überschrift 2 (28px)\",\n heading3: \"Überschrift 3 (22px)\",\n heading4: \"Überschrift 4 (18px)\",\n fontFamily: \"Schriftart\",\n inheritFont: \"Vorlagenschrift verwenden\",\n color: \"Farbe\",\n align: \"Ausrichtung\",\n alignLeft: \"Links\",\n alignCenter: \"Zentriert\",\n alignRight: \"Rechts\",\n },\n\n // Emoji picker\n emoji: {\n smileys: \"Smileys\",\n gestures: \"Gesten\",\n objects: \"Objekte\",\n },\n\n // Toolbar - Image\n image: {\n imageUrl: \"Bild-URL\",\n imageUrlPlaceholder: \"https://...\",\n altText: \"Alternativtext\",\n altTextPlaceholder: \"Bildbeschreibung\",\n width: \"Breite\",\n fullWidth: \"Volle Breite\",\n widthCustom: \"Benutzerdefiniert\",\n linkUrl: \"Link-URL\",\n openInNewTab: \"In neuem Tab öffnen\",\n placeholderUrl: \"Platzhalterbild\",\n placeholderUrlPlaceholder: \"https://... (nur zur Gestaltung)\",\n placeholderUrlTooltip:\n \"Da die Bild-URL ein Merge-Tag verwendet, können Sie hier ein echtes Bild angeben, um das Layout während der Gestaltung in der Vorschau anzuzeigen. Dies wird nicht in die endgültige Ausgabe aufgenommen.\",\n clickToAdd: \"Klicken Sie, um eine Bild-URL hinzuzufügen\",\n browseMedia: \"Medien durchsuchen\",\n dropToUpload: \"Bild zum Hochladen ablegen\",\n uploading: \"Wird hochgeladen…\",\n decorative: \"Dekoratives Bild\",\n decorativeHint:\n \"Wird von Bildschirmlesern ignoriert. Nur für Abstandshalter und visuelle Verzierungen verwenden.\",\n },\n\n // Toolbar - Video\n video: {\n videoUrl: \"Video-URL\",\n videoUrlPlaceholder: \"https://youtube.com/...\",\n youtube: \"YouTube\",\n vimeo: \"Vimeo\",\n detected: \"Video erkannt — Vorschaubild wird automatisch generiert\",\n openInNewTab: \"In neuem Tab öffnen\",\n customThumbnail: \"Eigenes Vorschaubild\",\n optional: \"(optional)\",\n thumbnailPlaceholder: \"Automatisch aus Video-URL generiert\",\n altText: \"Alternativtext\",\n altTextPlaceholder: \"Videobeschreibung\",\n width: \"Breite\",\n fullWidth: \"Volle Breite\",\n placeholderUrl: \"Platzhalter-Thumbnail\",\n placeholderUrlPlaceholder: \"https://... (nur zur Gestaltung)\",\n placeholderUrlTooltip:\n \"Da die Video-URL ein Merge-Tag verwendet, können Sie hier ein echtes Thumbnail angeben, um das Layout während der Gestaltung in der Vorschau anzuzeigen. Dies wird nicht in die endgültige Ausgabe aufgenommen.\",\n addVideo: \"Video-URL hinzufügen\",\n },\n\n // Toolbar - Button\n button: {\n fontFamily: \"Schriftart\",\n inheritFont: \"Vorlagenschrift verwenden\",\n text: \"Text\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n openInNewTab: \"In neuem Tab öffnen\",\n background: \"Hintergrund\",\n textColor: \"Textfarbe\",\n borderRadius: \"Eckenradius\",\n fontSize: \"Schriftgröße\",\n width: \"Breite\",\n widthAuto: \"An Inhalt anpassen\",\n fullWidth: \"Volle Breite\",\n widthCustom: \"Benutzerdefiniert\",\n },\n\n // Toolbar - Divider\n divider: {\n style: \"Stil\",\n solid: \"Durchgehend\",\n dashed: \"Gestrichelt\",\n dotted: \"Gepunktet\",\n color: \"Farbe\",\n thickness: \"Stärke\",\n },\n\n // Toolbar - Social Icons\n social: {\n icons: \"Symbole\",\n addIcon: \"Symbol hinzufügen\",\n addIcons: \"Soziale Symbole hinzufügen\",\n removeIcon: \"Entfernen\",\n platform: \"Plattform\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n style: \"Stil\",\n styleSolid: \"Gefüllt\",\n styleOutlined: \"Umrandet\",\n styleRounded: \"Abgerundet\",\n styleSquare: \"Eckig\",\n styleCircle: \"Rund\",\n size: \"Größe\",\n sizeSmall: \"K\",\n sizeMedium: \"M\",\n sizeLarge: \"G\",\n spacing: \"Abstand\",\n align: \"Ausrichtung\",\n platforms: {\n facebook: \"Facebook\",\n twitter: \"X (Twitter)\",\n instagram: \"Instagram\",\n linkedin: \"LinkedIn\",\n youtube: \"YouTube\",\n tiktok: \"TikTok\",\n pinterest: \"Pinterest\",\n email: \"E-Mail\",\n website: \"Website\",\n whatsapp: \"WhatsApp\",\n telegram: \"Telegram\",\n discord: \"Discord\",\n snapchat: \"Snapchat\",\n reddit: \"Reddit\",\n github: \"GitHub\",\n dribbble: \"Dribbble\",\n behance: \"Behance\",\n },\n },\n\n // Toolbar - Menu\n menu: {\n items: \"Menüpunkte\",\n addItem: \"Punkt hinzufügen\",\n removeItem: \"Entfernen\",\n text: \"Text\",\n url: \"URL\",\n urlPlaceholder: \"https://beispiel.de\",\n openInNewTab: \"In neuem Tab öffnen\",\n bold: \"Fett\",\n underline: \"Unterstrichen\",\n color: \"Farbe\",\n linkColor: \"Linkfarbe\",\n fontSize: \"Schriftgröße\",\n fontFamily: \"Schriftfamilie\",\n separator: \"Trennzeichen\",\n separatorColor: \"Trennzeichenfarbe\",\n spacing: \"Abstand\",\n textAlign: \"Ausrichtung\",\n addLinks: \"Menülinks hinzufügen\",\n },\n\n // Toolbar - Table\n table: {\n dimensions: \"Abmessungen\",\n rows: \"Zeilen\",\n columns: \"Spalten\",\n addRow: \"Zeile hinzufügen\",\n removeRow: \"Zeile entfernen\",\n addColumn: \"Spalte hinzufügen\",\n removeColumn: \"Spalte entfernen\",\n hasHeaderRow: \"Kopfzeile\",\n headerBackgroundColor: \"Kopfzeilen-Hintergrund\",\n noHeaderBg: \"Kein Hintergrund\",\n borderColor: \"Rahmenfarbe\",\n borderWidth: \"Rahmenbreite\",\n cellPadding: \"Zellenabstand\",\n fontFamily: \"Schriftart\",\n fontSize: \"Schriftgröße\",\n color: \"Textfarbe\",\n textAlign: \"Ausrichtung\",\n cellPlaceholder: \"Text eingeben...\",\n empty: \"Tabelle hinzufügen\",\n },\n\n // Toolbar - Spacer\n spacer: {\n height: \"Höhe\",\n },\n\n // Toolbar - Countdown\n countdown: {\n targetDate: \"Zieldatum\",\n timezone: \"Zeitzone\",\n display: \"Anzeige\",\n days: \"Tage\",\n hours: \"Stunden\",\n minutes: \"Minuten\",\n seconds: \"Sekunden\",\n separator: \"Trennzeichen\",\n fontFamily: \"Schriftart\",\n inheritFont: \"Standard\",\n digitFontSize: \"Zifferngröße\",\n digitColor: \"Ziffernfarbe\",\n labelColor: \"Beschriftungsfarbe\",\n labelFontSize: \"Beschriftungsgröße\",\n background: \"Hintergrund\",\n labels: \"Beschriftungen\",\n expiry: \"Ablaufnachricht\",\n expiredMessagePlaceholder: \"Dieses Angebot ist abgelaufen\",\n expiredImageUrl: \"Ablaufbild-URL\",\n hideOnExpiry: \"Bei Ablauf ausblenden\",\n setDate: \"Legen Sie ein Zieldatum im Einstellungsbereich fest\",\n hidden: \"Ausgeblendet (abgelaufen)\",\n },\n\n // Custom Blocks\n customBlocks: {\n definitionNotFound:\n \"Unbekannter Blocktyp — dieser Block ist nicht registriert\",\n renderError:\n \"Dieser Block konnte nicht gerendert werden. Überprüfen Sie die Block-Vorlage auf Fehler.\",\n fields: {\n required: \"Pflichtfeld\",\n addItem: \"Element hinzufügen\",\n removeItem: \"Entfernen\",\n maxItemsReached: \"Maximale Anzahl erreicht\",\n minItemsRequired: \"Mindestens {count} Elemente erforderlich\",\n },\n toolbar: {\n noDefinition:\n \"Registrieren Sie diesen Blocktyp in Ihrer SDK-Konfiguration, um seine Eigenschaften zu bearbeiten\",\n },\n dataSource: {\n fetchButton: \"Inhalt laden\",\n changeButton: \"Ändern\",\n fetching: \"Wird geladen...\",\n readOnlyTooltip: \"Dieser Wert wird aus Ihrer Datenquelle geladen\",\n fetchError: \"Inhalt konnte nicht geladen werden\",\n },\n },\n\n // Toolbar - HTML\n html: {\n content: \"HTML-Inhalt\",\n preview: \"Benutzerdefinierter HTML-Block\",\n empty: \"HTML-Inhalt im Bereich hinzufügen\",\n sanitizationHint:\n \"HTML wird unverändert exportiert und nicht bereinigt – stellen Sie sicher, dass der Inhalt sicher ist.\",\n },\n\n // Toolbar - Common block settings\n blockSettings: {\n spacing: \"Abstände\",\n padding: \"Innenabstand\",\n background: \"Hintergrund\",\n color: \"Farbe\",\n display: \"Anzeige\",\n showOnDesktop: \"Auf Desktop anzeigen\",\n showOnMobile: \"Auf Mobilgerät anzeigen\",\n hiddenOnDevice: \"Ausgeblendet auf {device}\",\n displayCondition: \"Anzeigebedingung\",\n selectCondition: \"Bedingung auswählen\",\n removeCondition: \"Bedingung entfernen\",\n noCondition: \"Immer sichtbar\",\n conditionApplied: \"Bedingung angewendet\",\n customCondition: \"Eigene Bedingung\",\n customConditionLabel: \"Bedingungsname\",\n customConditionBefore: \"Vorher (öffnende Logik)\",\n customConditionAfter: \"Nachher (schließende Logik)\",\n applyCondition: \"Anwenden\",\n cancelCondition: \"Abbrechen\",\n customBadge: \"Eigene\",\n restoreHiddenBlocks: \"Alle ausgeblendeten Blöcke anzeigen\",\n },\n\n // Template settings\n templateSettings: {\n layout: \"Layout\",\n widthPreset: \"Breitenvoreinstellung\",\n customWidth: \"Benutzerdefinierte Breite\",\n appearance: \"Erscheinungsbild\",\n backgroundColor: \"Hintergrundfarbe\",\n textColor: \"Textfarbe\",\n linkColor: \"Linkfarbe\",\n linkUnderline: \"Links unterstreichen\",\n fontFamily: \"Schriftfamilie\",\n preheaderText: \"Preheader-Text\",\n preheaderTextPlaceholder:\n \"Vorschautext, der nach der Betreffzeile im Posteingang angezeigt wird...\",\n preheaderTextHint:\n \"Dieser Text erscheint nach der Betreffzeile in der E-Mail-Vorschau. Unterstützt Merge-Tags.\",\n language: \"Sprache\",\n contentLocale: \"Inhaltssprache\",\n contentLocaleHint:\n \"BCP-47-Code (z. B. en, de, pt-BR). Setzt das lang-Attribut der gerenderten E-Mail, damit Screenreader den Inhalt korrekt aussprechen.\",\n tips: \"Tipps\",\n tip1: \"600px ist die Standardbreite für E-Mail-Vorlagen\",\n tip2: \"Verwenden Sie websichere Schriften für beste Kompatibilität\",\n tip3: \"Helle Hintergründe eignen sich am besten für die Lesbarkeit\",\n },\n\n // Spacing control\n spacingControl: {\n lockAll: \"Alle Seiten sperren\",\n unlock: \"Seiten entsperren\",\n top: \"Oben\",\n right: \"Rechts\",\n bottom: \"Unten\",\n left: \"Links\",\n decreaseTop: \"Oben verringern\",\n increaseTop: \"Oben erhöhen\",\n decreaseLeft: \"Links verringern\",\n increaseLeft: \"Links erhöhen\",\n decreaseRight: \"Rechts verringern\",\n increaseRight: \"Rechts erhöhen\",\n decreaseBottom: \"Unten verringern\",\n increaseBottom: \"Unten erhöhen\",\n },\n\n // Color Picker\n colorPicker: {\n pickColor: \"Farbe auswählen\",\n hexValue: \"Hex-Farbwert\",\n notSet: \"Nicht festgelegt\",\n clear: \"Farbe entfernen\",\n presetColors: \"Vordefinierte Farben\",\n },\n\n // Merge-Tag\n mergeTag: {\n clickToEdit: \"Zum Bearbeiten klicken\",\n remove: \"Merge-Tag entfernen\",\n insert: \"Merge-Tag einfügen\",\n insertShort: \"Merge-Tag\",\n editValue: \"Merge-Tag-Wert bearbeiten\",\n deleteMergeTag: \"Merge-Tag löschen\",\n suggestionEmpty: \"Keine passenden Merge-Tags\",\n picker: {\n title: \"Merge-Tag einfügen\",\n searchPlaceholder: \"Merge-Tags suchen\",\n searchAriaLabel: \"Merge-Tags suchen\",\n noResults: \"Keine passenden Merge-Tags\",\n empty: \"Keine Merge-Tags konfiguriert\",\n otherGroup: \"Sonstige\",\n cancel: \"Abbrechen\",\n close: \"Schließen\",\n groupCount: \"{count}\",\n },\n },\n\n // Logic tags (standalone, separate from merge tags)\n logicTag: {\n insert: \"Logik einfügen\",\n insertShort: \"Logik\",\n picker: {\n title: \"Logik einfügen\",\n searchPlaceholder: \"Logik-Tags suchen\",\n searchAriaLabel: \"Logik-Tags suchen\",\n noResults: \"Keine passenden Logik-Tags\",\n empty: \"Keine Logik-Tags konfiguriert\",\n otherGroup: \"Sonstige\",\n close: \"Schließen\",\n },\n },\n\n // Canvas\n canvas: {\n noBlocks: \"Noch keine Blöcke\",\n dragHint:\n \"Beginnen Sie von Grund auf, indem Sie Blöcke aus der Seitenleiste ziehen\",\n dropHere: \"Hier ablegen\",\n aiHintChat: \"oder lassen Sie\",\n aiHintChatSuffix: \"in Sekunden eine komplette Vorlage für Sie erstellen\",\n aiHintDesign:\n \"Haben Sie ein bestehendes Design? Laden Sie einen Screenshot, ein Bild oder PDF hoch und\",\n aiHintDesignSuffix: \"erstellt es sofort nach\",\n },\n\n // Media Library (cloud)\n mediaLibrary: {\n title: \"Medienbibliothek\",\n searchPlaceholder: \"Dateien suchen...\",\n allFiles: \"Alle Dateien\",\n filterAll: \"Alle Typen\",\n filterImages: \"Bilder\",\n filterDocuments: \"Dokumente\",\n filterVideos: \"Videos\",\n filterAudio: \"Audio\",\n newFolder: \"Neuer Ordner\",\n folderName: \"Ordnername\",\n noFiles: \"Keine Dateien gefunden\",\n dropOrClick: \"Dateien hierher ziehen oder klicken zum Hochladen\",\n acceptedFormats: \"Bilder, PDF, Video, Audio, Dokumente (max. 10 MB)\",\n uploading: \"Wird hochgeladen...\",\n uploadingProgress: \"{current} von {total} wird hochgeladen...\",\n selectImage: \"Bild auswählen\",\n selectFile: \"Datei auswählen\",\n deleteSelected: \"Löschen\",\n copyUrl: \"URL kopieren\",\n copied: \"Kopiert!\",\n browseMedia: \"Medienbibliothek durchsuchen\",\n renameFolder: \"Ordner umbenennen\",\n addSubfolder: \"Unterordner hinzufügen\",\n subfolderName: \"Unterordnername\",\n sortNewest: \"Neueste zuerst\",\n sortOldest: \"Älteste zuerst\",\n sortNameAsc: \"Name A-Z\",\n sortNameDesc: \"Name Z-A\",\n sortSizeAsc: \"Kleinste zuerst\",\n sortSizeDesc: \"Größte zuerst\",\n moveSelected: \"Verschieben\",\n moveToRoot: \"Alle Dateien\",\n currentFolder: \"(aktuell)\",\n confirmDelete: \"Diese Datei löschen?\",\n renameFile: \"Umbenennen\",\n editFile: \"Datei bearbeiten\",\n fileName: \"Dateiname\",\n altText: \"Alternativtext\",\n altTextPlaceholder: \"Bildbeschreibung für Barrierefreiheit\",\n saveChanges: \"Speichern\",\n cancel: \"Abbrechen\",\n frequentlyUsed: \"Häufig verwendet\",\n deleteWarningTitle: \"Datei löschen\",\n deleteWarningMessage:\n \"Diese Datei wird dauerhaft gelöscht und kann nicht wiederhergestellt werden.\",\n deleteWarningUsageNote:\n \"Die folgenden Dateien werden in Vorlagen verwendet. Das Löschen kann diese Vorlagen beschädigen.\",\n deleteAnyway: \"Datei löschen\",\n usedInTemplates: \"In {count} Vorlage(n) verwendet\",\n viewGrid: \"Rasteransicht\",\n viewList: \"Listenansicht\",\n showFolders: \"Ordner anzeigen\",\n hideFolders: \"Ordner ausblenden\",\n importFromUrl: \"Von URL importieren\",\n importUrlPlaceholder: \"https://example.com/image.jpg\",\n import: \"Importieren\",\n importing: \"Wird importiert...\",\n importError: \"Import von URL fehlgeschlagen\",\n conversionLabel: \"Groesse\",\n conversionOriginal: \"Original\",\n conversionSmall: \"Klein (150px)\",\n conversionMedium: \"Mittel (600px)\",\n conversionLarge: \"Gross (1200px)\",\n replaceFile: \"Datei ersetzen\",\n replaceWarningTitle: \"Datei ersetzen\",\n replaceWarningMessage:\n \"Sie sind dabei, diese Datei zu ersetzen. Die Ersatzdatei muss dieselbe Dateierweiterung haben ({extension}).\",\n replaceWarningUsageNote:\n \"Diese Datei wird in {count} Vorlage(n) verwendet. Das Ersetzen aktualisiert alle Verweise.\",\n replaceSelectFile: \"Ersatzdatei auswählen\",\n replace: \"Ersetzen\",\n replacing: \"Wird ersetzt...\",\n replaceError: \"Ersetzen der Datei fehlgeschlagen\",\n saving: \"Wird gespeichert...\",\n cropAspectRatio: \"Seitenverhältnis\",\n cropFree: \"Frei\",\n cropSquare: \"1:1\",\n cropLandscape43: \"4:3\",\n cropLandscape169: \"16:9\",\n cropOriginal: \"Original\",\n cropMaxWidth: \"Max. Breite\",\n cropMaxHeight: \"Max. Höhe\",\n cropOutputSize: \"Ausgabegröße\",\n cropPixels: \"px\",\n cropOptional: \"(optional)\",\n storageTooltip: \"{used} von {total} verwendet ({remaining} verfügbar)\",\n },\n\n // Seitenleiste\n savedBlocks: {\n title: \"Gespeicherte Blöcke\",\n saveAsBlock: \"Als Block speichern\",\n name: \"Name\",\n namePlaceholder: \"z.B. Header, Footer, CTA...\",\n save: \"Block speichern\",\n saving: \"Wird gespeichert...\",\n cancel: \"Abbrechen\",\n empty: \"Noch keine gespeicherten Blöcke\",\n emptyHint:\n \"Speichern Sie Blöcke aus Ihren Vorlagen, um sie später wiederzuverwenden.\",\n noResults: \"Keine gespeicherten Blöcke gefunden\",\n search: \"Gespeicherte Blöcke suchen...\",\n loading: \"Gespeicherte Blöcke werden geladen…\",\n category: \"Kategorie\",\n categoryPlaceholder: \"z. B. Kopfzeilen, Aktionen... (optional)\",\n allCategories: \"Alle Kategorien\",\n filterByCategory: \"Nach Kategorie filtern\",\n insert: \"Einfügen\",\n rename: \"Umbenennen\",\n delete: \"Löschen\",\n deleteConfirm: \"Diesen gespeicherten Block löschen?\",\n blockCount: \"{count} Block/Blöcke\",\n browse: \"Gespeicherte Blöcke durchsuchen\",\n selectToPreview: \"Gespeicherten Block für Vorschau auswählen\",\n insertAtBeginning: \"Am Anfang\",\n insertAfterBlock: \"Nach {block}\",\n insertAtEnd: \"Am Ende\",\n insertPosition: \"Einfügeposition\",\n close: \"Schließen\",\n pickToolbar: \"Auswahl für gespeicherten Block\",\n pickCount: \"{count} Block/Blöcke ausgewählt\",\n pickHint: \"Blöcke anklicken, um sie hinzuzufügen oder zu entfernen\",\n savingCount: \"{count} Block/Blöcke werden gespeichert:\",\n reorderHint:\n \"Zum Umsortieren ziehen — in dieser Reihenfolge werden die Blöcke gespeichert\",\n reorderHandle: \"{block} umsortieren, Position {position} von {total}\",\n reorderAnnouncement:\n \"{block} an Position {position} von {total} verschoben\",\n expand: \"Aufklappen\",\n collapse: \"Zuklappen\",\n expandPreview: \"Vorschau von {block} aufklappen\",\n collapsePreview: \"Vorschau von {block} zuklappen\",\n time: {\n justNow: \"Gerade eben\",\n minutesAgo: \"vor {minutes} Min.\",\n hoursAgo: \"vor {hours} Std.\",\n daysAgo: \"vor {days} Tagen\",\n },\n },\n sidebarNav: {\n browseSavedBlocks: \"Gespeicherte Blöcke durchsuchen\",\n expandSidebar: \"Block-Seitenleiste erweitern\",\n palette: \"Blockpalette\",\n insertBlock: \"{block}-Block einfügen\",\n },\n\n // Landmark-Bezeichnungen für Hilfstechnologien\n landmarks: {\n canvas: \"E-Mail-Leinwand\",\n blockToolbar: \"Blockeigenschaften\",\n rightSidebar: \"Blockeigenschaften und Vorlageneinstellungen\",\n reorderAnnouncements: \"Block-Neuanordnungsmeldungen\",\n },\n\n // Design Reference (cloud)\n errors: {\n editorLoading: \"Editor wird geladen...\",\n editorLoadFailed: \"Editor konnte nicht geladen werden.\",\n retry: \"Erneut versuchen\",\n },\n\n issues: {\n panelTitle: \"Probleme\",\n panelTabLabel: \"Probleme\",\n groupErrors: \"Fehler\",\n groupWarnings: \"Warnungen\",\n groupInfo: \"Hinweise\",\n jump: \"Zum Block springen\",\n fix: \"Beheben\",\n emptyState: \"Keine Probleme — sieht gut aus.\",\n badgeError: \"Hat Fehler\",\n badgeWarning: \"Hat Warnungen\",\n issueCountTooltip: \"{count} Problem(e)\",\n },\n\n smallScreen: {\n title: \"Größerer Bildschirm erforderlich\",\n message:\n \"Der Editor benötigt mehr Platz, als dieser Bildschirm bietet. Öffnen Sie ihn auf einem Tablet oder Desktop, um mit der Bearbeitung zu beginnen.\",\n },\n};\n\nexport default de;\n"],"mappings":"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"}