@templatical/editor 0.31.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/dist/{AiChatSidebar-DYDtzTDd.js → AiChatSidebar-J7WsHRDS.js} +15 -15
  2. package/dist/{AiFeatureMenu-BJ882XCi.js → AiFeatureMenu-C9mxL_7U.js} +7 -7
  3. package/dist/{BlockIssueBadge-D6y8vQpL.js → BlockIssueBadge-BI6v_eol.js} +5 -5
  4. package/dist/{BlockPreviewCanvas-DQNxLy7u.js → BlockPreviewCanvas-mZIr9mY2.js} +20 -19
  5. package/dist/{CloudHeaderExtras-CqG3RaKw.js → CloudHeaderExtras-CLtTtK12.js} +5 -5
  6. package/dist/{CloudPanels-B6xrk7kN.js → CloudPanels-BbLAX1jH.js} +7 -7
  7. package/dist/{CollaboratorBar-by16gXQH.js → CollaboratorBar-OBbLOhLK.js} +4 -4
  8. package/dist/{ColorPicker-E5gqlCZE.js → ColorPicker-Cs7iK01u.js} +7 -7
  9. package/dist/{CommentsPanel-B_kzvTHR.js → CommentsPanel-G_uNzi1a.js} +2 -2
  10. package/dist/{CommentsSidebar-gfzUX7cd.js → CommentsSidebar-DlFlpfkU.js} +14 -14
  11. package/dist/{CountdownBlock-BgNK7fZY.js → CountdownBlock-Bdt8qZi1.js} +3 -3
  12. package/dist/{CountdownToolbar-DU8UHx9A.js → CountdownToolbar-BWLYViOm.js} +4 -4
  13. package/dist/{DesignReferenceSidebar-DgndMB4H.js → DesignReferenceSidebar-CK_xTLh2.js} +11 -11
  14. package/dist/{FieldRow-0-UbQR4a.js → FieldRow-BWt7ECqo.js} +1 -1
  15. package/dist/{IssuesPanel-DmJTb_SZ.js → IssuesPanel-DIbJ_jaa.js} +8 -8
  16. package/dist/{LoadingTrack-5KBr5cE8.js → LoadingTrack-SQXoZVf2.js} +1 -1
  17. package/dist/{MergeTagModeToggle-CZnJ2Gz_.js → MergeTagModeToggle-DeI65T5k.js} +6 -6
  18. package/dist/{MergeTagSuggestion-DyUcY_9e.js → MergeTagSuggestion-CoCuzEmW.js} +4 -4
  19. package/dist/{ParagraphEditor-CnB4kXle.js → ParagraphEditor-Dr-u72hu.js} +26 -26
  20. package/dist/{RestoreVersionDialog-BpOphPiE.js → RestoreVersionDialog-6sBYYt9f.js} +5 -5
  21. package/dist/{RichTextEditorContent-ChPNgHQ_.js → RichTextEditorContent-DKLVe6Io.js} +8 -8
  22. package/dist/{SaveBlockDialog-CKw4Va6j.js → SaveBlockDialog-DABN4-Jf.js} +25 -25
  23. package/dist/SavedBlocksBrowserModal-BoylzTEq.js +322 -0
  24. package/dist/{SavedBlocksPanels-ChV8bOgM.js → SavedBlocksPanels-2np4Yu1H.js} +2 -2
  25. package/dist/{SavedBlocksPickBar-BbEeD5RB.js → SavedBlocksPickBar-BM7aTSK2.js} +4 -4
  26. package/dist/{TemplateScoringPanel-De8BZpRU.js → TemplateScoringPanel-CzWoSM1V.js} +15 -15
  27. package/dist/{TestEmailModal-4d2pXeHU.js → TestEmailModal-Cb0n7Dhj.js} +11 -11
  28. package/dist/{TestEmailPanel-DEgCesNP.js → TestEmailPanel-52HjvuU7.js} +2 -2
  29. package/dist/{TitleEditor-89pmKLVY.js → TitleEditor-_taBpBfB.js} +13 -13
  30. package/dist/{TplModal-DswccJRJ.js → TplModal-CEYnwBBk.js} +5 -5
  31. package/dist/VersionHistoryMenu-CsGlLSO8.js +157 -0
  32. package/dist/{VersionHistoryPanels-CFLHDH9P.js → VersionHistoryPanels-DPmYk00L.js} +2 -2
  33. package/dist/{VersionPreviewBanner-DhG5RcRt.js → VersionPreviewBanner-VGJbEoXj.js} +3 -3
  34. package/dist/{blockTypeIcons-dpKs5GQc.js → blockTypeIcons-IhdBwbxp.js} +2 -2
  35. package/dist/bundle-stats.json +7 -7
  36. package/dist/{ca-DZSrLNXK.js → ca-C0hfqt4U.js} +5 -0
  37. package/dist/cdn/chunks/{AiChatSidebar-DmYDRmvX.js → AiChatSidebar-6S5LPyRW.js} +9 -9
  38. package/dist/cdn/chunks/{AiChatSidebar-DmYDRmvX.js.map → AiChatSidebar-6S5LPyRW.js.map} +1 -1
  39. package/dist/cdn/chunks/{AiFeatureMenu-C0Rt08qb.js → AiFeatureMenu-BHCtjIfV.js} +6 -6
  40. package/dist/cdn/chunks/{AiFeatureMenu-C0Rt08qb.js.map → AiFeatureMenu-BHCtjIfV.js.map} +1 -1
  41. package/dist/cdn/chunks/{BlockIssueBadge-BBog2CMy.js → BlockIssueBadge-2-os120N.js} +5 -5
  42. package/dist/cdn/chunks/{BlockIssueBadge-BBog2CMy.js.map → BlockIssueBadge-2-os120N.js.map} +1 -1
  43. package/dist/cdn/chunks/{BlockPreviewCanvas-DNBjBKBI.js → BlockPreviewCanvas-CYNs-Yn-.js} +21 -20
  44. package/dist/cdn/chunks/BlockPreviewCanvas-CYNs-Yn-.js.map +1 -0
  45. package/dist/cdn/chunks/{CloudHeaderExtras-Ditfv7y9.js → CloudHeaderExtras-DrbFk6Fy.js} +5 -5
  46. package/dist/cdn/chunks/{CloudHeaderExtras-Ditfv7y9.js.map → CloudHeaderExtras-DrbFk6Fy.js.map} +1 -1
  47. package/dist/cdn/chunks/{CloudPanels-C4U5bJO6.js → CloudPanels-CpzYrAPQ.js} +7 -7
  48. package/dist/cdn/chunks/{CloudPanels-C4U5bJO6.js.map → CloudPanels-CpzYrAPQ.js.map} +1 -1
  49. package/dist/cdn/chunks/{CollaboratorBar-B79JR9NH.js → CollaboratorBar-VMTCYn_z.js} +5 -5
  50. package/dist/cdn/chunks/{CollaboratorBar-B79JR9NH.js.map → CollaboratorBar-VMTCYn_z.js.map} +1 -1
  51. package/dist/cdn/chunks/{ColorPicker-C-ZiwUV3.js → ColorPicker-B0l_UF8G.js} +7 -7
  52. package/dist/cdn/chunks/{ColorPicker-C-ZiwUV3.js.map → ColorPicker-B0l_UF8G.js.map} +1 -1
  53. package/dist/cdn/chunks/{CommentsPanel-D1Ke8PbO.js → CommentsPanel-CXMMdLrO.js} +3 -3
  54. package/dist/cdn/chunks/{CommentsPanel-D1Ke8PbO.js.map → CommentsPanel-CXMMdLrO.js.map} +1 -1
  55. package/dist/cdn/chunks/{CommentsSidebar-B-UyhIZN.js → CommentsSidebar-CGkhAJUW.js} +5 -5
  56. package/dist/cdn/chunks/{CommentsSidebar-B-UyhIZN.js.map → CommentsSidebar-CGkhAJUW.js.map} +1 -1
  57. package/dist/cdn/chunks/{CountdownBlock-CWeJBC0L.js → CountdownBlock-CPe1ulzk.js} +4 -4
  58. package/dist/cdn/chunks/{CountdownBlock-CWeJBC0L.js.map → CountdownBlock-CPe1ulzk.js.map} +1 -1
  59. package/dist/cdn/chunks/{CountdownToolbar-DyOHOu44.js → CountdownToolbar-D5xyNd5V.js} +5 -5
  60. package/dist/cdn/chunks/{CountdownToolbar-DyOHOu44.js.map → CountdownToolbar-D5xyNd5V.js.map} +1 -1
  61. package/dist/cdn/chunks/{DesignReferenceSidebar-BCCX1FtP.js → DesignReferenceSidebar-D1NH1WRv.js} +7 -7
  62. package/dist/cdn/chunks/{DesignReferenceSidebar-BCCX1FtP.js.map → DesignReferenceSidebar-D1NH1WRv.js.map} +1 -1
  63. package/dist/cdn/chunks/{FieldRow-CbcpsxZ4.js → FieldRow-D9OJhYeb.js} +2 -2
  64. package/dist/cdn/chunks/{FieldRow-CbcpsxZ4.js.map → FieldRow-D9OJhYeb.js.map} +1 -1
  65. package/dist/cdn/chunks/{IssuesPanel-3vD3ImHF.js → IssuesPanel-07SBSZVN.js} +6 -6
  66. package/dist/cdn/chunks/{IssuesPanel-3vD3ImHF.js.map → IssuesPanel-07SBSZVN.js.map} +1 -1
  67. package/dist/cdn/chunks/{LoadingTrack-Cz1sT0wP.js → LoadingTrack-Cm3TDKb3.js} +2 -2
  68. package/dist/cdn/chunks/{LoadingTrack-Cz1sT0wP.js.map → LoadingTrack-Cm3TDKb3.js.map} +1 -1
  69. package/dist/cdn/chunks/{MergeTagModeToggle-BU0SDRow.js → MergeTagModeToggle-Bg8eO5nc.js} +6 -6
  70. package/dist/cdn/chunks/{MergeTagModeToggle-BU0SDRow.js.map → MergeTagModeToggle-Bg8eO5nc.js.map} +1 -1
  71. package/dist/cdn/chunks/{MergeTagSuggestion-B9vL0VaG.js → MergeTagSuggestion-t8Uj00Er.js} +3 -3
  72. package/dist/cdn/chunks/{MergeTagSuggestion-B9vL0VaG.js.map → MergeTagSuggestion-t8Uj00Er.js.map} +1 -1
  73. package/dist/cdn/chunks/{ParagraphEditor-CSwIuvoF.js → ParagraphEditor-x2LTi6DN.js} +23 -23
  74. package/dist/cdn/chunks/{ParagraphEditor-CSwIuvoF.js.map → ParagraphEditor-x2LTi6DN.js.map} +1 -1
  75. package/dist/cdn/chunks/{RestoreVersionDialog-Bvg2WvJN.js → RestoreVersionDialog--SjTV0_4.js} +5 -5
  76. package/dist/cdn/chunks/{RestoreVersionDialog-Bvg2WvJN.js.map → RestoreVersionDialog--SjTV0_4.js.map} +1 -1
  77. package/dist/cdn/chunks/{RichTextEditorContent-DdkmEEpK.js → RichTextEditorContent-CzdMJ1c9.js} +7 -7
  78. package/dist/cdn/chunks/{RichTextEditorContent-DdkmEEpK.js.map → RichTextEditorContent-CzdMJ1c9.js.map} +1 -1
  79. package/dist/cdn/chunks/{SaveBlockDialog-D-QO3LuR.js → SaveBlockDialog-CS1lqdsQ.js} +9 -9
  80. package/dist/cdn/chunks/{SaveBlockDialog-D-QO3LuR.js.map → SaveBlockDialog-CS1lqdsQ.js.map} +1 -1
  81. package/dist/cdn/chunks/{SavedBlocksBrowserModal-BRdN56r7.js → SavedBlocksBrowserModal-D6nDZ4rq.js} +110 -111
  82. package/dist/cdn/chunks/SavedBlocksBrowserModal-D6nDZ4rq.js.map +1 -0
  83. package/dist/cdn/chunks/{SavedBlocksPanels-D9GTlLgb.js → SavedBlocksPanels-DdkwvYRR.js} +3 -3
  84. package/dist/cdn/chunks/{SavedBlocksPanels-D9GTlLgb.js.map → SavedBlocksPanels-DdkwvYRR.js.map} +1 -1
  85. package/dist/cdn/chunks/{SavedBlocksPickBar-DSRcUeIo.js → SavedBlocksPickBar-BLQr_6WM.js} +5 -5
  86. package/dist/cdn/chunks/{SavedBlocksPickBar-DSRcUeIo.js.map → SavedBlocksPickBar-BLQr_6WM.js.map} +1 -1
  87. package/dist/cdn/chunks/{TemplateScoringPanel-Dy5oOVhB.js → TemplateScoringPanel-CDC-JC6C.js} +50 -50
  88. package/dist/cdn/chunks/{TemplateScoringPanel-Dy5oOVhB.js.map → TemplateScoringPanel-CDC-JC6C.js.map} +1 -1
  89. package/dist/cdn/chunks/{TestEmailModal-B4L2lmIV.js → TestEmailModal-B2LcU11Y.js} +10 -10
  90. package/dist/cdn/chunks/{TestEmailModal-B4L2lmIV.js.map → TestEmailModal-B2LcU11Y.js.map} +1 -1
  91. package/dist/cdn/chunks/{TestEmailPanel-cTPgEf-D.js → TestEmailPanel-ByqDSx8B.js} +3 -3
  92. package/dist/cdn/chunks/{TestEmailPanel-cTPgEf-D.js.map → TestEmailPanel-ByqDSx8B.js.map} +1 -1
  93. package/dist/cdn/chunks/{TitleEditor-BKjL2Zs1.js → TitleEditor-DCoulgN8.js} +13 -13
  94. package/dist/cdn/chunks/{TitleEditor-BKjL2Zs1.js.map → TitleEditor-DCoulgN8.js.map} +1 -1
  95. package/dist/cdn/chunks/{TplModal-DxrgNmt9.js → TplModal-CxQDl-tN.js} +5 -5
  96. package/dist/cdn/chunks/{TplModal-DxrgNmt9.js.map → TplModal-CxQDl-tN.js.map} +1 -1
  97. package/dist/cdn/chunks/VersionHistoryMenu-BOy8aMB6.js +150 -0
  98. package/dist/cdn/chunks/VersionHistoryMenu-BOy8aMB6.js.map +1 -0
  99. package/dist/cdn/chunks/{VersionHistoryPanels-CxIFBJsz.js → VersionHistoryPanels-BPLhzW9c.js} +3 -3
  100. package/dist/cdn/chunks/{VersionHistoryPanels-CxIFBJsz.js.map → VersionHistoryPanels-BPLhzW9c.js.map} +1 -1
  101. package/dist/cdn/chunks/{VersionPreviewBanner-CdsZvVYF.js → VersionPreviewBanner-CYC9qP2i.js} +4 -4
  102. package/dist/cdn/chunks/{VersionPreviewBanner-CdsZvVYF.js.map → VersionPreviewBanner-CYC9qP2i.js.map} +1 -1
  103. package/dist/cdn/chunks/{blockTypeIcons-DXPd_hd1.js → blockTypeIcons-ZEzEpCti.js} +2 -2
  104. package/dist/cdn/chunks/{blockTypeIcons-DXPd_hd1.js.map → blockTypeIcons-ZEzEpCti.js.map} +1 -1
  105. package/dist/cdn/chunks/{ca-DZSrLNXK.js → ca-C0hfqt4U.js} +6 -1
  106. package/dist/cdn/chunks/ca-C0hfqt4U.js.map +1 -0
  107. package/dist/cdn/chunks/{cloud-CITqEHEc.js → cloud-BP5-6__d.js} +4 -4
  108. package/dist/cdn/chunks/{cloud-CITqEHEc.js.map → cloud-BP5-6__d.js.map} +1 -1
  109. package/dist/cdn/chunks/{createCloudRuntime-DwIXvrb0.js → createCloudRuntime-CbSqoOba.js} +10 -10
  110. package/dist/cdn/chunks/{createCloudRuntime-DwIXvrb0.js.map → createCloudRuntime-CbSqoOba.js.map} +1 -1
  111. package/dist/{de-DbayqpK-.js → cdn/chunks/de-C6J2Iae8.js} +7 -0
  112. package/dist/cdn/chunks/de-C6J2Iae8.js.map +1 -0
  113. package/dist/cdn/chunks/{dist-CgR3inPR.js → dist-BW6Y49zE.js} +2 -2
  114. package/dist/cdn/chunks/{dist-CgR3inPR.js.map → dist-BW6Y49zE.js.map} +1 -1
  115. package/dist/cdn/chunks/{dist-El3fQnfk.js → dist-CAFTQ6Y2.js} +5 -5
  116. package/dist/cdn/chunks/{dist-El3fQnfk.js.map → dist-CAFTQ6Y2.js.map} +1 -1
  117. package/dist/cdn/chunks/{draggable-D2vo-aQI.js → draggable-kbOhCgnk.js} +12 -13
  118. package/dist/cdn/chunks/{draggable-D2vo-aQI.js.map → draggable-kbOhCgnk.js.map} +1 -1
  119. package/dist/cdn/chunks/{en-l0ib5X0f.js → en-BaUYOQi8.js} +6 -1
  120. package/dist/cdn/chunks/en-BaUYOQi8.js.map +1 -0
  121. package/dist/cdn/chunks/en-mEKGL1PX.js +2 -0
  122. package/dist/cdn/chunks/{es-CMQ-5PJP.js → es-CKDYfJYn.js} +6 -1
  123. package/dist/cdn/chunks/es-CKDYfJYn.js.map +1 -0
  124. package/dist/cdn/chunks/{extensions-C87Z6_23.js → extensions-CeP0iOPC.js} +7 -7
  125. package/dist/cdn/chunks/{extensions-C87Z6_23.js.map → extensions-CeP0iOPC.js.map} +1 -1
  126. package/dist/cdn/chunks/formatAbsoluteDateTime-DMmop3C-.js +15 -0
  127. package/dist/cdn/chunks/formatAbsoluteDateTime-DMmop3C-.js.map +1 -0
  128. package/dist/{fr-DNXmZWAq.js → cdn/chunks/fr-L8DR73mK.js} +7 -0
  129. package/dist/cdn/chunks/fr-L8DR73mK.js.map +1 -0
  130. package/dist/cdn/chunks/{icons-ciivb5BS.js → icons-SP5Itd-A.js} +9 -9
  131. package/dist/cdn/chunks/icons-SP5Itd-A.js.map +1 -0
  132. package/dist/cdn/chunks/keys-O8clwJ41.js +12 -0
  133. package/dist/cdn/chunks/keys-O8clwJ41.js.map +1 -0
  134. package/dist/cdn/chunks/{liquid.browser-BPvKXNfO.js → liquid.browser-BypTT2oc.js} +4 -4
  135. package/dist/cdn/chunks/{liquid.browser-BPvKXNfO.js.map → liquid.browser-BypTT2oc.js.map} +1 -1
  136. package/dist/{nl-BylRRHYJ.js → cdn/chunks/nl-GDWeuX18.js} +7 -0
  137. package/dist/cdn/chunks/nl-GDWeuX18.js.map +1 -0
  138. package/dist/cdn/chunks/{preRenderCustomBlocks-DyCIgmqJ.js → preRenderCustomBlocks-LFB-e-0m.js} +2 -2
  139. package/dist/cdn/chunks/{preRenderCustomBlocks-DyCIgmqJ.js.map → preRenderCustomBlocks-LFB-e-0m.js.map} +1 -1
  140. package/dist/cdn/chunks/{pt-BR-BVoJhpie.js → pt-BR-B1AVVhWj.js} +6 -1
  141. package/dist/cdn/chunks/pt-BR-B1AVVhWj.js.map +1 -0
  142. package/dist/cdn/chunks/{src-6J-yyZoD.js → src-BM3f9I7t.js} +268 -268
  143. package/dist/cdn/chunks/{src-6J-yyZoD.js.map → src-BM3f9I7t.js.map} +1 -1
  144. package/dist/cdn/chunks/{src-Cf0ohOog.js → src-C1lP5sIe.js} +19 -19
  145. package/dist/cdn/chunks/src-C1lP5sIe.js.map +1 -0
  146. package/dist/cdn/chunks/{src-BD60gqPW.js → src-CLoCCDfs.js} +26 -26
  147. package/dist/cdn/chunks/{src-BD60gqPW.js.map → src-CLoCCDfs.js.map} +1 -1
  148. package/dist/cdn/chunks/{src-Bid3cmHa.js → src-Cxl-9O-L.js} +699 -684
  149. package/dist/cdn/chunks/src-Cxl-9O-L.js.map +1 -0
  150. package/dist/cdn/chunks/{tiptap-Ey0FpaX7.js → tiptap-Epe8m3Vo.js} +2636 -2629
  151. package/dist/cdn/chunks/tiptap-Epe8m3Vo.js.map +1 -0
  152. package/dist/cdn/chunks/{useAliveFlag-DrXxPV8V.js → useAliveFlag-CT9gjvO_.js} +2 -2
  153. package/dist/cdn/chunks/{useAliveFlag-DrXxPV8V.js.map → useAliveFlag-CT9gjvO_.js.map} +1 -1
  154. package/dist/cdn/chunks/{useCloudI18n-D0AoLV0a.js → useCloudI18n-ZBEJvkf4.js} +3 -3
  155. package/dist/cdn/chunks/{useCloudI18n-D0AoLV0a.js.map → useCloudI18n-ZBEJvkf4.js.map} +1 -1
  156. package/dist/cdn/chunks/{useEditorCore-CTNB2Mkl.js → useEditorCore-CZxGbZmY.js} +591 -413
  157. package/dist/cdn/chunks/useEditorCore-CZxGbZmY.js.map +1 -0
  158. package/dist/cdn/chunks/useEditorRoot-DVV-EsNI.js +10 -0
  159. package/dist/cdn/chunks/{useEditorRoot-BFGRBGts.js.map → useEditorRoot-DVV-EsNI.js.map} +1 -1
  160. package/dist/cdn/chunks/{useI18n-DIhawILp.js → useI18n-DCbvHv6W.js} +3 -3
  161. package/dist/cdn/chunks/{useI18n-DIhawILp.js.map → useI18n-DCbvHv6W.js.map} +1 -1
  162. package/dist/cdn/chunks/{useMergeTag-lWo7So18.js → useMergeTag-CbuagYNK.js} +4 -4
  163. package/dist/cdn/chunks/{useMergeTag-lWo7So18.js.map → useMergeTag-CbuagYNK.js.map} +1 -1
  164. package/dist/cdn/chunks/{usePopoverPosition-DkiTLnBm.js → usePopoverPosition-Ozg5iU3y.js} +3 -3
  165. package/dist/cdn/chunks/{usePopoverPosition-DkiTLnBm.js.map → usePopoverPosition-Ozg5iU3y.js.map} +1 -1
  166. package/dist/cdn/chunks/{useScrollToBlock-KcSAuXKz.js → useScrollToBlock-CrUCYsIc.js} +3 -3
  167. package/dist/cdn/chunks/{useScrollToBlock-KcSAuXKz.js.map → useScrollToBlock-CrUCYsIc.js.map} +1 -1
  168. package/dist/cdn/editor.css +1 -1
  169. package/dist/cdn/editor.js +1191 -1181
  170. package/dist/cdn/editor.js.map +1 -1
  171. package/dist/{check-80E6ZGin.js → check-JK8Uacq0.js} +1 -1
  172. package/dist/{chevron-down-BmkLsn2c.js → chevron-down-a-fb_Ijn.js} +1 -1
  173. package/dist/{chevron-up-DJSAzlUU.js → chevron-up-x4l0et_Y.js} +1 -1
  174. package/dist/{circle-alert-BsCfZryY.js → circle-alert-CJDW5LZo.js} +1 -1
  175. package/dist/{clock-BcLIngSK.js → clock-BW6rXk2f.js} +1 -1
  176. package/dist/{cloud-DwJ8ebNl.js → cloud-BMzRKCbk.js} +3 -3
  177. package/dist/{createCloudRuntime-CdXQdl34.js → createCloudRuntime-j6a9Z-vL.js} +8 -8
  178. package/dist/{createLucideIcon-eeetEgBb.js → createLucideIcon-Bvw1Zx56.js} +3 -3
  179. package/dist/{cdn/chunks/de-DbayqpK-.js → de-C6J2Iae8.js} +5 -2
  180. package/dist/{dist-BFcAowKZ.js → dist-BxFbxpgW.js} +5 -5
  181. package/dist/{dist-Do83S47T.js → dist-ByT5fgKq.js} +2 -2
  182. package/dist/{dist-CQ9T1yi-.js → dist-C1tsW_99.js} +2 -2
  183. package/dist/{dist-Cd0LvUlh.js → dist-CtF9STPS.js} +2 -2
  184. package/dist/{dist-CvW1nNzy.js → dist-CtMXAH7a.js} +2 -2
  185. package/dist/dist-D08oVYhr.js +5 -0
  186. package/dist/{dist-prgdllHG.js → dist-D7WY8VPq.js} +2 -2
  187. package/dist/{dist-D8MekYFl.js → dist-DC-3T0ED.js} +2 -2
  188. package/dist/{dist-BC1y_U2m.js → dist-DL9334yz.js} +1418 -1411
  189. package/dist/{dist-BkAVGSRr.js → dist-DkcA6epL.js} +7 -7
  190. package/dist/dist-DzdeVn-W.js +5 -0
  191. package/dist/{dist-CzVIVbSa.js → dist-PL6vP4SC.js} +61 -61
  192. package/dist/{dist-CuuPnIMy.js → dist-dNiknO7j.js} +4 -4
  193. package/dist/{dist-CWC5t5J3.js → dist-f7HXo6j6.js} +2 -2
  194. package/dist/{dist-BUpBA58N.js → dist-heatwAdo.js} +1 -1
  195. package/dist/{en-l0ib5X0f.js → en-BaUYOQi8.js} +5 -0
  196. package/dist/{es-CMQ-5PJP.js → es-CKDYfJYn.js} +5 -0
  197. package/dist/{extensions-BYImwYeO.js → extensions-5xeZR9U9.js} +21 -21
  198. package/dist/formatAbsoluteDateTime-DMmop3C-.js +13 -0
  199. package/dist/{cdn/chunks/fr-DNXmZWAq.js → fr-L8DR73mK.js} +5 -2
  200. package/dist/{image-up-BfxY85ar.js → image-up-CuzFc1mu.js} +1 -1
  201. package/dist/index.d.ts +41 -0
  202. package/dist/{info-LX4QFBr6.js → info-DybAwcA3.js} +1 -1
  203. package/dist/keys-BJJ4hJ4z.js +10 -0
  204. package/dist/{liquid.browser-CJgDDvQz.js → liquid.browser-wPG0n4Cs.js} +3 -3
  205. package/dist/{loader-circle-Bwima0v8.js → loader-circle-t-SVgmJ3.js} +1 -1
  206. package/dist/{message-circle-Box-mf2k.js → message-circle-DtwKrlhN.js} +1 -1
  207. package/dist/{cdn/chunks/nl-BylRRHYJ.js → nl-GDWeuX18.js} +5 -2
  208. package/dist/{pencil-BM9gSq_J.js → pencil-2qhC-Y4q.js} +1 -1
  209. package/dist/{preRenderCustomBlocks-2KyBJocY.js → preRenderCustomBlocks-CSIF-HyJ.js} +1 -1
  210. package/dist/{pt-BR-BVoJhpie.js → pt-BR-B1AVVhWj.js} +5 -0
  211. package/dist/{refresh-cw-BuzFX0wH.js → refresh-cw-C8SBuPdg.js} +1 -1
  212. package/dist/{runtime-dom.esm-bundler-Co_SPqAz.js → runtime-dom.esm-bundler-BuG03jBM.js} +3 -3
  213. package/dist/{scan-line-Duq1WXoG.js → scan-line-E7w4yQyv.js} +1 -1
  214. package/dist/{send-DZ4nOnIA.js → send-BoqJliF6.js} +1 -1
  215. package/dist/{shield-check-Cz4BRYdv.js → shield-check-D0dMaHtE.js} +1 -1
  216. package/dist/{sparkles-DP8RqOeL.js → sparkles-Dy2BJjiX.js} +1 -1
  217. package/dist/style.css +1 -1
  218. package/dist/templatical-editor.js +1031 -1022
  219. package/dist/{text-align-start-D7tXhjUP.js → text-align-start-DrxjxvIy.js} +1 -1
  220. package/dist/{trash-2-BS7lZeyb.js → trash-rYMzzHZd.js} +2 -2
  221. package/dist/{triangle-alert-Cx4mQGjx.js → triangle-alert-DxnFj4-B.js} +1 -1
  222. package/dist/{upload-L8tLVM10.js → upload-DZu1adQz.js} +1 -1
  223. package/dist/{useAliveFlag-AFbwfHlJ.js → useAliveFlag-PVmp95MT.js} +1 -1
  224. package/dist/{useCloudI18n-BA69BpQ_.js → useCloudI18n-DaKcDMDz.js} +2 -2
  225. package/dist/{useEditorCore-CtR46sbJ.js → useEditorCore-BWrxHVKW.js} +1246 -1067
  226. package/dist/{useEditorRoot-Cdo8Vhxa.js → useEditorRoot-E-oxHaEI.js} +2 -2
  227. package/dist/{useI18n-B135ASaG.js → useI18n-DUVIAju4.js} +2 -2
  228. package/dist/{useMergeTag-Cx36rtrt.js → useMergeTag-CuZZeiSE.js} +3 -3
  229. package/dist/{usePopoverPosition-DAOHr_iM.js → usePopoverPosition-APlWgXoQ.js} +2 -2
  230. package/dist/{useScrollToBlock-tndC8vKo.js → useScrollToBlock--AzCOzlg.js} +3 -3
  231. package/dist/{vue.runtime.esm-bundler-BhOUdXMi.js → vue.runtime.esm-bundler-D9JUcKrV.js} +4 -4
  232. package/dist/{x-ChIQ7HwK.js → x-DJOd1hS4.js} +1 -1
  233. package/package.json +23 -23
  234. package/dist/SavedBlocksBrowserModal-SST-7EMK.js +0 -323
  235. package/dist/VersionHistoryMenu-DBxSJR1k.js +0 -155
  236. package/dist/cdn/chunks/BlockPreviewCanvas-DNBjBKBI.js.map +0 -1
  237. package/dist/cdn/chunks/SavedBlocksBrowserModal-BRdN56r7.js.map +0 -1
  238. package/dist/cdn/chunks/VersionHistoryMenu-CMqZFUHE.js +0 -148
  239. package/dist/cdn/chunks/VersionHistoryMenu-CMqZFUHE.js.map +0 -1
  240. package/dist/cdn/chunks/ca-DZSrLNXK.js.map +0 -1
  241. package/dist/cdn/chunks/de-DbayqpK-.js.map +0 -1
  242. package/dist/cdn/chunks/en-BzFt4b80.js +0 -2
  243. package/dist/cdn/chunks/en-l0ib5X0f.js.map +0 -1
  244. package/dist/cdn/chunks/es-CMQ-5PJP.js.map +0 -1
  245. package/dist/cdn/chunks/fr-DNXmZWAq.js.map +0 -1
  246. package/dist/cdn/chunks/icons-ciivb5BS.js.map +0 -1
  247. package/dist/cdn/chunks/keys-BJ770Mwm.js +0 -12
  248. package/dist/cdn/chunks/keys-BJ770Mwm.js.map +0 -1
  249. package/dist/cdn/chunks/nl-BylRRHYJ.js.map +0 -1
  250. package/dist/cdn/chunks/pt-BR-BVoJhpie.js.map +0 -1
  251. package/dist/cdn/chunks/src-Bid3cmHa.js.map +0 -1
  252. package/dist/cdn/chunks/src-Cf0ohOog.js.map +0 -1
  253. package/dist/cdn/chunks/tiptap-Ey0FpaX7.js.map +0 -1
  254. package/dist/cdn/chunks/useEditorCore-CTNB2Mkl.js.map +0 -1
  255. package/dist/cdn/chunks/useEditorRoot-BFGRBGts.js +0 -10
  256. package/dist/dist-BQqIUwvB.js +0 -5
  257. package/dist/dist-waDcdb1l.js +0 -5
  258. package/dist/keys-BJtoezGU.js +0 -10
@@ -58,6 +58,11 @@ var e = {
58
58
  table: "Table",
59
59
  countdown: "Countdown"
60
60
  },
61
+ blockDefaults: {
62
+ title: "Enter your title",
63
+ paragraph: "Enter your text here",
64
+ button: "Click Here"
65
+ },
61
66
  sidebar: {
62
67
  content: "Content",
63
68
  settings: "Settings",
@@ -609,4 +614,4 @@ var e = {
609
614
  //#endregion
610
615
  export { e as default };
611
616
 
612
- //# sourceMappingURL=en-l0ib5X0f.js.map
617
+ //# sourceMappingURL=en-BaUYOQi8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en-BaUYOQi8.js","names":[],"sources":["../../../src/i18n/locales/en.ts"],"sourcesContent":["export default {\n // Footer (OSS only)\n footer: {\n poweredBy: \"Powered by\",\n openSource: \"Open Source\",\n },\n\n // Header — template name + save state. Shown only when a templates provider\n // is configured.\n header: {\n save: \"Save\",\n saving: \"Saving...\",\n saved: \"Saved\",\n unsaved: \"Unsaved\",\n saveFailed: \"Save failed\",\n saveNoTemplate: \"Load or create a template first\",\n templateName: \"Template name\",\n rename: \"Rename template\",\n untitled: \"Untitled\",\n updatedAt: \"Updated {time}\",\n createdAt: \"Created {time}\",\n updatedJustNow: \"Updated just now\",\n createdJustNow: \"Created just now\",\n },\n\n // Relative timestamps, shared by every surface that shows one: the header's\n // updated line, saved blocks, comments and version history.\n time: {\n justNow: \"Just now\",\n minutesAgo: \"{minutes}m ago\",\n hoursAgo: \"{hours}h ago\",\n daysAgo: \"{days}d ago\",\n },\n\n // History (undo/redo)\n history: {\n collabWarning: \"Undo may affect collaborators' recent changes\",\n undo: \"Undo\",\n redo: \"Redo\",\n },\n\n // Viewport toggle\n viewport: {\n label: \"Viewport\",\n desktop: \"Desktop\",\n mobile: \"Mobile\",\n },\n\n // Dark mode preview\n darkMode: {\n enable: \"Dark Mode Preview\",\n disable: \"Light Mode Preview\",\n },\n\n // Preview mode\n previewMode: {\n enable: \"Preview Mode\",\n disable: \"Exit Preview\",\n },\n\n // Sidebar - Block types\n blocks: {\n section: \"Section\",\n image: \"Image\",\n title: \"Title\",\n paragraph: \"Paragraph\",\n button: \"Button\",\n divider: \"Divider\",\n video: \"Video\",\n social: \"Social\",\n spacer: \"Spacer\",\n html: \"HTML\",\n menu: \"Menu\",\n table: \"Table\",\n countdown: \"Countdown\",\n },\n\n // Placeholder text a newly inserted block starts with. Author-facing\n // prompts, meant to be overwritten — so they follow the editor UI locale.\n // Recipient-facing defaults live in `i18n/contentDefaults.ts` and follow\n // the template's own `settings.locale` instead.\n blockDefaults: {\n title: \"Enter your title\",\n paragraph: \"Enter your text here\",\n button: \"Click Here\",\n },\n\n // Right sidebar\n sidebar: {\n content: \"Content\",\n settings: \"Settings\",\n noSelection: \"No element selected\",\n noSelectionHint: \"Select a block on the canvas to edit it\",\n },\n\n // Toolbar - Common\n toolbar: {\n duplicate: \"Duplicate\",\n delete: \"Delete\",\n },\n\n // Title editor toolbar\n titleEditor: {\n toolbar: \"Title formatting\",\n bold: \"Bold (Ctrl+B)\",\n italic: \"Italic (Ctrl+I)\",\n addLink: \"Add Link\",\n },\n\n // Paragraph editor toolbar\n paragraphEditor: {\n toolbar: \"Text formatting\",\n bold: \"Bold (Ctrl+B)\",\n italic: \"Italic (Ctrl+I)\",\n underline: \"Underline (Ctrl+U)\",\n strikethrough: \"Strikethrough\",\n subscript: \"Subscript\",\n superscript: \"Superscript\",\n addLink: \"Add Link\",\n bulletList: \"Bullet List\",\n numberedList: \"Numbered List\",\n alignLeft: \"Align Left\",\n alignCenter: \"Align Center\",\n alignRight: \"Align Right\",\n alignJustify: \"Justify\",\n clearFormatting: \"Clear Formatting\",\n insertEmoji: \"Insert Emoji\",\n fontFamily: \"Font Family\",\n defaultFont: \"Default\",\n fontSize: \"Font Size\",\n defaultSize: \"Default\",\n textColor: \"Text Color\",\n highlightColor: \"Highlight Color\",\n lineHeight: \"Line Height\",\n letterSpacing: \"Letter Spacing\",\n emojiItemLabel: \"Insert emoji {emoji}\",\n },\n\n // Block actions (BlockWrapper)\n blockActions: {\n drag: \"Drag to reorder, or press Space to move with keyboard\",\n dragLifted:\n \"Moving {block}. Use up and down arrow keys to reposition, Space or Enter to drop, Escape to cancel.\",\n duplicate: \"Duplicate block\",\n delete: \"Delete block\",\n hiddenOnViewport: \"Hidden on {viewport}\",\n saveAsBlock: \"Save as Block\",\n conditionToggle: \"Toggle display condition\",\n comments: \"Comments ({count})\",\n lifted: \"{block} lifted. Position {position} of {total}.\",\n moved: \"{block} moved to position {position} of {total}.\",\n dropped: \"{block} dropped at position {position} of {total}.\",\n cancelled: \"Move cancelled. {block} returned to position {position}.\",\n },\n\n // Toolbar - Section\n section: {\n dropHere: \"Drop blocks here\",\n columns: \"Columns\",\n column1: \"1 Column\",\n column2: \"2 Columns\",\n column3: \"3 Columns\",\n ratio12: \"1:2 Ratio\",\n ratio21: \"2:1 Ratio\",\n borderRadius: \"Border Radius\",\n wrapperEnable: \"Add wrapper\",\n stackOnMobile: \"Stack on mobile\",\n },\n\n // Text editor link dialog\n linkDialog: {\n editLink: \"Edit Link\",\n insertLink: \"Insert Link\",\n updateLink: \"Update Link\",\n removeLink: \"Remove Link\",\n cancel: \"Cancel\",\n urlPlaceholder: \"https://example.com\",\n urlLabel: \"URL\",\n colorLabel: \"Link Color\",\n },\n\n // Toolbar - Title\n title: {\n level: \"Heading Level\",\n heading1: \"Heading 1 (36px)\",\n heading2: \"Heading 2 (28px)\",\n heading3: \"Heading 3 (22px)\",\n heading4: \"Heading 4 (18px)\",\n fontFamily: \"Font Family\",\n inheritFont: \"Use template font\",\n color: \"Color\",\n align: \"Align\",\n alignLeft: \"Left\",\n alignCenter: \"Center\",\n alignRight: \"Right\",\n },\n\n // Emoji picker\n emoji: {\n smileys: \"Smileys\",\n gestures: \"Gestures\",\n objects: \"Objects\",\n },\n\n // Toolbar - Image\n image: {\n imageUrl: \"Image URL\",\n imageUrlPlaceholder: \"https://...\",\n altText: \"Alt Text\",\n altTextPlaceholder: \"Image description\",\n width: \"Width\",\n fullWidth: \"Full Width\",\n widthCustom: \"Custom\",\n height: \"Height\",\n heightAuto: \"Auto\",\n heightCustom: \"Custom\",\n borderRadius: \"Border Radius\",\n linkUrl: \"Link URL\",\n openInNewTab: \"Open in new tab\",\n placeholderUrl: \"Placeholder Image\",\n optional: \"(optional)\",\n placeholderUrlPlaceholder: \"https://... (design-time only)\",\n placeholderUrlTooltip:\n \"Since the image URL uses a merge tag, you can provide a real image here to preview the layout while designing. This is not included in the final output.\",\n clickToAdd: \"Click to add image URL\",\n browseMedia: \"Browse Media\",\n dropToUpload: \"Drop image to upload\",\n uploading: \"Uploading…\",\n decorative: \"Decorative image\",\n decorativeHint:\n \"Hidden from screen readers. Use only for spacers and visual flourishes.\",\n },\n\n // Toolbar - Video\n video: {\n videoUrl: \"Video URL\",\n videoUrlPlaceholder: \"https://youtube.com/...\",\n openInNewTab: \"Open in new tab\",\n customThumbnail: \"Custom Thumbnail\",\n optional: \"(optional)\",\n thumbnailPlaceholder: \"Auto-generated from video URL\",\n altText: \"Alt Text\",\n altTextPlaceholder: \"Video description\",\n width: \"Width\",\n fullWidth: \"Full Width\",\n height: \"Height\",\n heightAuto: \"Auto\",\n heightCustom: \"Custom\",\n placeholderUrl: \"Placeholder Thumbnail\",\n placeholderUrlPlaceholder: \"https://... (design-time only)\",\n placeholderUrlTooltip:\n \"Since the video URL uses a merge tag, you can provide a real thumbnail here to preview the layout while designing. This is not included in the final output.\",\n addVideo: \"Add a video URL\",\n },\n\n // Toolbar - Button\n button: {\n fontFamily: \"Font Family\",\n inheritFont: \"Use template font\",\n text: \"Text\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n openInNewTab: \"Open in new tab\",\n background: \"Background\",\n textColor: \"Text Color\",\n borderRadius: \"Border Radius\",\n fontSize: \"Font Size\",\n width: \"Width\",\n widthAuto: \"Fit to content\",\n fullWidth: \"Full Width\",\n widthCustom: \"Custom\",\n },\n\n // Toolbar - Divider\n divider: {\n style: \"Style\",\n solid: \"Solid\",\n dashed: \"Dashed\",\n dotted: \"Dotted\",\n color: \"Color\",\n thickness: \"Thickness\",\n },\n\n // Toolbar - Social Icons\n social: {\n icons: \"Icons\",\n addIcon: \"Add Icon\",\n addIcons: \"Add social icons\",\n removeIcon: \"Remove\",\n urlPlaceholder: \"https://...\",\n style: \"Style\",\n styleSolid: \"Solid\",\n styleOutlined: \"Outlined\",\n styleRounded: \"Rounded\",\n styleSquare: \"Square\",\n styleCircle: \"Circle\",\n size: \"Size\",\n sizeSmall: \"S\",\n sizeMedium: \"M\",\n sizeLarge: \"L\",\n spacing: \"Spacing\",\n align: \"Alignment\",\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: \"Email\",\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: \"Menu Items\",\n addItem: \"Add Item\",\n removeItem: \"Remove\",\n text: \"Text\",\n urlPlaceholder: \"https://example.com\",\n openInNewTab: \"Open in new tab\",\n bold: \"Bold\",\n underline: \"Underline\",\n color: \"Color\",\n linkColor: \"Link Color\",\n fontSize: \"Font Size\",\n fontFamily: \"Font Family\",\n separator: \"Separator\",\n separatorColor: \"Separator Color\",\n spacing: \"Spacing\",\n textAlign: \"Alignment\",\n addLinks: \"Add menu links\",\n },\n\n // Toolbar - Table\n table: {\n dimensions: \"Dimensions\",\n rows: \"Rows\",\n columns: \"Columns\",\n hasHeaderRow: \"Header row\",\n headerBackgroundColor: \"Header Background\",\n noHeaderBg: \"No background\",\n borderColor: \"Border Color\",\n borderWidth: \"Border Width\",\n cellPadding: \"Cell Padding\",\n fontFamily: \"Font Family\",\n fontSize: \"Font Size\",\n color: \"Text Color\",\n textAlign: \"Alignment\",\n cellPlaceholder: \"Enter text...\",\n empty: \"Add a table\",\n },\n\n // Toolbar - Paragraph\n paragraph: {\n paragraphSpacing: \"Paragraph Spacing\",\n },\n\n // Toolbar - Spacer\n spacer: {\n height: \"Height\",\n },\n\n // Toolbar - Countdown\n countdown: {\n targetDate: \"Target Date\",\n timezone: \"Timezone\",\n display: \"Display\",\n days: \"Days\",\n hours: \"Hours\",\n minutes: \"Minutes\",\n seconds: \"Seconds\",\n separator: \"Separator\",\n fontFamily: \"Font Family\",\n inheritFont: \"Default\",\n digitFontSize: \"Digit Size\",\n digitColor: \"Digit Color\",\n labelColor: \"Label Color\",\n labelFontSize: \"Label Size\",\n background: \"Background\",\n labels: \"Labels\",\n expiry: \"Expired Message\",\n expiredMessagePlaceholder: \"This offer has expired\",\n expiredImageUrl: \"Expired Image URL\",\n hideOnExpiry: \"Hide when expired\",\n setDate: \"Set a target date in the settings panel\",\n hidden: \"Hidden (expired)\",\n },\n\n // Custom Blocks\n customBlocks: {\n definitionNotFound: \"Unknown block type — this block is not registered\",\n renderError:\n \"This block could not be rendered. Check the block template for errors.\",\n fields: {\n required: \"Required\",\n addItem: \"Add item\",\n removeItem: \"Remove\",\n maxItemsReached: \"Maximum items reached\",\n minItemsRequired: \"Minimum {count} items required\",\n },\n toolbar: {\n noDefinition:\n \"Register this block type in your SDK configuration to edit its properties\",\n },\n dataSource: {\n fetchButton: \"Load content\",\n changeButton: \"Change\",\n fetching: \"Loading...\",\n readOnlyTooltip: \"This value is loaded from your data source\",\n fetchError: \"Failed to load content\",\n },\n },\n\n // Toolbar - HTML\n html: {\n content: \"HTML Content\",\n preview: \"Custom HTML block\",\n empty: \"Add HTML content in the panel\",\n sanitizationHint:\n \"HTML is exported as-is and isn't sanitized — make sure the content is safe.\",\n },\n\n // Toolbar - Common block settings\n blockSettings: {\n spacing: \"Spacing\",\n padding: \"Padding\",\n background: \"Background\",\n color: \"Color\",\n display: \"Display\",\n showOnDesktop: \"Show on desktop\",\n showOnMobile: \"Show on mobile\",\n hiddenOnDevice: \"Hidden on {device}\",\n displayCondition: \"Display Condition\",\n selectCondition: \"Select condition\",\n removeCondition: \"Remove condition\",\n noCondition: \"Always visible\",\n conditionApplied: \"Condition applied\",\n customCondition: \"Custom condition\",\n customConditionLabel: \"Condition name\",\n customConditionBefore: \"Before (opening logic)\",\n customConditionAfter: \"After (closing logic)\",\n applyCondition: \"Apply\",\n cancelCondition: \"Cancel\",\n customBadge: \"Custom\",\n restoreHiddenBlocks: \"Show all hidden blocks\",\n },\n\n // Template settings\n templateSettings: {\n layout: \"Layout\",\n widthPreset: \"Width Preset\",\n customWidth: \"Custom Width\",\n appearance: \"Appearance\",\n backgroundColor: \"Background Color\",\n textColor: \"Text Color\",\n linkColor: \"Link Color\",\n linkUnderline: \"Underline Links\",\n fontFamily: \"Font Family\",\n preheaderText: \"Preheader Text\",\n preheaderTextPlaceholder:\n \"Preview text shown after subject line in inbox...\",\n preheaderTextHint:\n \"This text appears after the subject line in email client previews. Supports merge tags.\",\n language: \"Language\",\n contentLocale: \"Content language\",\n contentLocaleHint:\n \"BCP 47 code (e.g. en, de, pt-BR). Sets the rendered email's lang attribute so screen readers pronounce content correctly.\",\n tips: \"Tips\",\n tip1: \"600px is the standard width for email templates\",\n tip2: \"Use web-safe fonts for best compatibility\",\n tip3: \"Light backgrounds work best for readability\",\n },\n\n // Spacing control\n spacingControl: {\n lockAll: \"Lock all sides\",\n unlock: \"Unlock sides\",\n top: \"Top\",\n right: \"Right\",\n bottom: \"Bottom\",\n left: \"Left\",\n decreaseTop: \"Decrease top\",\n increaseTop: \"Increase top\",\n decreaseLeft: \"Decrease left\",\n increaseLeft: \"Increase left\",\n decreaseRight: \"Decrease right\",\n increaseRight: \"Increase right\",\n decreaseBottom: \"Decrease bottom\",\n increaseBottom: \"Increase bottom\",\n },\n\n // Color Picker\n colorPicker: {\n pickColor: \"Pick a color\",\n hexValue: \"Hex color value\",\n notSet: \"Not set\",\n clear: \"Clear color\",\n presetColors: \"Preset colors\",\n },\n\n // Merge Tag\n mergeTag: {\n clickToEdit: \"Click to edit\",\n remove: \"Remove merge tag\",\n insert: \"Insert merge tag\",\n insertShort: \"Merge tag\",\n editValue: \"Edit merge tag value\",\n deleteMergeTag: \"Delete merge tag\",\n suggestionEmpty: \"No matching merge tags\",\n picker: {\n title: \"Insert merge tag\",\n searchPlaceholder: \"Search merge tags\",\n searchAriaLabel: \"Search merge tags\",\n noResults: \"No matching merge tags\",\n empty: \"No merge tags configured\",\n otherGroup: \"Other\",\n close: \"Close\",\n groupCount: \"{count}\",\n sample: \"Preview: {sample}\",\n },\n },\n\n // Logic tags (standalone, separate from merge tags)\n logicTag: {\n insert: \"Insert logic\",\n insertShort: \"Logic\",\n picker: {\n title: \"Insert logic\",\n searchPlaceholder: \"Search logic tags\",\n searchAriaLabel: \"Search logic tags\",\n noResults: \"No matching logic tags\",\n empty: \"No logic tags configured\",\n otherGroup: \"Other\",\n close: \"Close\",\n },\n },\n\n // Canvas\n canvas: {\n noBlocks: \"No blocks yet\",\n dragHint: \"Start from scratch by dragging blocks from the sidebar\",\n dropHere: \"Drop here\",\n aiHintChat: \"or let\",\n aiHintChatSuffix: \"generate a complete template for you in seconds\",\n aiHintDesign:\n \"Have an existing design? Upload a screenshot, image, or PDF and\",\n aiHintDesignSuffix: \"will instantly recreate it\",\n },\n\n // Sidebar\n savedBlocks: {\n title: \"Saved Blocks\",\n saveAsBlock: \"Save as Block\",\n name: \"Name\",\n namePlaceholder: \"e.g. Header, Footer, CTA...\",\n save: \"Save Block\",\n saving: \"Saving...\",\n cancel: \"Cancel\",\n empty: \"No saved blocks yet\",\n emptyHint: \"Save blocks from your templates to reuse them later.\",\n noResults: \"No saved blocks match your search\",\n search: \"Search saved blocks...\",\n loading: \"Loading saved blocks…\",\n category: \"Category\",\n categoryPlaceholder: \"e.g. Headers, Promos... (optional)\",\n allCategories: \"All categories\",\n filterByCategory: \"Filter by category\",\n insert: \"Insert\",\n rename: \"Rename\",\n delete: \"Delete\",\n deleteConfirm: \"Delete this saved block?\",\n blockCount: \"{count} block(s)\",\n browse: \"Browse Saved Blocks\",\n selectToPreview: \"Select a saved block to preview\",\n insertAtBeginning: \"At beginning\",\n insertAfterBlock: \"After {block}\",\n insertAtEnd: \"At end\",\n insertPosition: \"Insert position\",\n close: \"Close\",\n pickToolbar: \"Saved block selection\",\n pickCount: \"{count} block(s) selected\",\n pickHint: \"Click blocks to add or remove them\",\n savingCount: \"Saving {count} block(s):\",\n reorderHint: \"Drag to reorder — blocks are saved in this order\",\n reorderHandle: \"Reorder {block}, position {position} of {total}\",\n reorderAnnouncement: \"{block} moved to position {position} of {total}\",\n expand: \"Expand\",\n collapse: \"Collapse\",\n expandPreview: \"Expand {block} preview\",\n collapsePreview: \"Collapse {block} preview\",\n },\n comments: {\n button: \"Comments\",\n title: \"Comments\",\n placeholder: \"Write a comment...\",\n replyPlaceholder: \"Write a reply...\",\n reply: \"Reply\",\n resolve: \"Resolve\",\n unresolve: \"Unresolve\",\n delete: \"Delete\",\n edit: \"Edit\",\n cancel: \"Cancel\",\n save: \"Save\",\n noComments: \"No comments yet\",\n noCommentsHint:\n \"Start a conversation by adding a comment to the template or a specific block.\",\n deleteConfirm: \"Delete this comment?\",\n filterAll: \"All\",\n filterUnresolved: \"Unresolved\",\n filterBlock: \"This block\",\n jumpToBlock: \"Block\",\n ownedByYou: \"You\",\n edited: \"edited\",\n resolvedBy: \"Resolved by {name}\",\n replyOne: \"{count} Reply\",\n replyMany: \"{count} Replies\",\n missingBlock: \"Missing block\",\n saveTemplateFirst: \"Save the template before commenting on this block.\",\n },\n versionHistory: {\n tooltip: \"Version history\",\n dropdownTitle: \"Version history\",\n empty: \"No versions yet\",\n auto: \"auto\",\n olderVersion: \"Older version\",\n newerVersion: \"Newer version\",\n },\n versionPreview: {\n message: \"You are previewing an earlier version of this template.\",\n cancel: \"Cancel\",\n restore: \"Restore this version\",\n restoreConfirm: {\n title: \"Restore this version?\",\n unsavedWithSave:\n \"You have unsaved changes. Save them first and they stay in your history — restore without saving and they are lost.\",\n unsavedNoSave:\n \"You have unsaved changes and nowhere to save them. Restoring this version will lose them.\",\n saveAndRestore: \"Save, then restore\",\n restoreAnyway: \"Restore anyway\",\n cancel: \"Cancel\",\n },\n },\n previewResolution: {\n resolving: \"Resolving preview…\",\n failed: \"Preview couldn't be resolved — showing the unresolved template.\",\n hint: \"Preview uses resolved data from your backend.\",\n },\n mergeTagPreview: {\n label: \"Merge tag view\",\n sample: \"Sample\",\n labelView: \"Label\",\n },\n testEmail: {\n title: \"Send Test Email\",\n recipientLabel: \"Recipient\",\n recipientPlaceholder: \"you@example.com\",\n invalidAddress: \"Enter a valid email address.\",\n preview: \"Preview\",\n previewHint:\n \"Merge tags are shown unresolved — your backend fills them in.\",\n previewHintSample:\n \"Merge tags show example values — your backend fills in the real data.\",\n recipientNotAllowed: \"That address isn't in the allowed list.\",\n send: \"Send\",\n sending: \"Sending...\",\n cancel: \"Cancel\",\n success: \"Test email sent successfully\",\n button: \"Test\",\n },\n sidebarNav: {\n browseSavedBlocks: \"Browse saved blocks\",\n palette: \"Block palette\",\n insertBlock: \"Insert {block} block\",\n },\n\n // Landmark region labels for assistive technology\n landmarks: {\n canvas: \"Email canvas\",\n blockToolbar: \"Block properties\",\n rightSidebar: \"Block properties and template settings\",\n reorderAnnouncements: \"Block reorder announcements\",\n },\n\n // Design Reference (cloud)\n errors: {\n editorLoading: \"Loading editor...\",\n editorLoadFailed: \"Failed to load editor.\",\n retry: \"Retry\",\n },\n\n issues: {\n panelTitle: \"Issues\",\n panelTabLabel: \"Issues\",\n groupErrors: \"Errors\",\n groupWarnings: \"Warnings\",\n groupInfo: \"Info\",\n jump: \"Jump to block\",\n fix: \"Fix\",\n emptyState: \"No issues — looking good.\",\n badgeError: \"Has errors\",\n badgeWarning: \"Has warnings\",\n issueCountTooltip: \"{count} issue(s)\",\n },\n\n smallScreen: {\n title: \"Larger screen required\",\n message:\n \"The editor needs more space than this screen offers. Open it on a tablet or desktop to start editing.\",\n },\n};\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./src-Cxl-9O-L.js";
2
+ export { e as default };
@@ -58,6 +58,11 @@ var e = {
58
58
  table: "Tabla",
59
59
  countdown: "Cuenta atrás"
60
60
  },
61
+ blockDefaults: {
62
+ title: "Escribe tu título",
63
+ paragraph: "Escribe tu texto aquí",
64
+ button: "Haz clic aquí"
65
+ },
61
66
  sidebar: {
62
67
  content: "Contenido",
63
68
  settings: "Configuración",
@@ -609,4 +614,4 @@ var e = {
609
614
  //#endregion
610
615
  export { e as default };
611
616
 
612
- //# sourceMappingURL=es-CMQ-5PJP.js.map
617
+ //# sourceMappingURL=es-CKDYfJYn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"es-CKDYfJYn.js","names":[],"sources":["../../../src/i18n/locales/es.ts"],"sourcesContent":["import type en from \"./en\";\n\nconst es: typeof en = {\n // Footer (OSS only)\n footer: {\n poweredBy: \"Con la tecnología de\",\n openSource: \"Código abierto\",\n },\n\n // Header — nombre de la plantilla + estado de guardado. Solo se muestra cuando\n // hay un proveedor de plantillas configurado.\n header: {\n save: \"Guardar\",\n saving: \"Guardando...\",\n saved: \"Guardado\",\n unsaved: \"Sin guardar\",\n saveFailed: \"Error al guardar\",\n saveNoTemplate: \"Carga o crea una plantilla primero\",\n templateName: \"Nombre de la plantilla\",\n rename: \"Cambiar el nombre de la plantilla\",\n untitled: \"Sin título\",\n updatedAt: \"Actualizado {time}\",\n createdAt: \"Creado {time}\",\n updatedJustNow: \"Actualizado ahora mismo\",\n createdJustNow: \"Creado ahora mismo\",\n },\n\n // Relative timestamps, shared by every surface that shows one: the header's\n // updated line, saved blocks, comments and version history.\n time: {\n justNow: \"Ahora mismo\",\n minutesAgo: \"hace {minutes} min\",\n hoursAgo: \"hace {hours} h\",\n daysAgo: \"hace {days} d\",\n },\n\n // History (undo/redo)\n history: {\n collabWarning:\n \"Deshacer puede afectar a los cambios recientes de los colaboradores\",\n undo: \"Deshacer\",\n redo: \"Rehacer\",\n },\n\n // Viewport toggle\n viewport: {\n label: \"Área de visualización\",\n desktop: \"Escritorio\",\n mobile: \"Móvil\",\n },\n\n // Dark mode preview\n darkMode: {\n enable: \"Vista previa en modo oscuro\",\n disable: \"Vista previa en modo claro\",\n },\n\n // Preview mode\n previewMode: {\n enable: \"Modo vista previa\",\n disable: \"Salir de la vista previa\",\n },\n\n // Sidebar - Block types\n blocks: {\n section: \"Sección\",\n image: \"Imagen\",\n title: \"Título\",\n paragraph: \"Párrafo\",\n button: \"Botón\",\n divider: \"Divisor\",\n video: \"Vídeo\",\n social: \"Redes sociales\",\n spacer: \"Espaciador\",\n html: \"HTML\",\n menu: \"Menú\",\n table: \"Tabla\",\n countdown: \"Cuenta atrás\",\n },\n\n // Placeholder text a newly inserted block starts with. Author-facing\n // prompts, meant to be overwritten — so they follow the editor UI locale.\n // Recipient-facing defaults live in `i18n/contentDefaults.ts` and follow\n // the template's own `settings.locale` instead.\n blockDefaults: {\n title: \"Escribe tu título\",\n paragraph: \"Escribe tu texto aquí\",\n button: \"Haz clic aquí\",\n },\n\n // Right sidebar\n sidebar: {\n content: \"Contenido\",\n settings: \"Configuración\",\n noSelection: \"Ningún elemento seleccionado\",\n noSelectionHint: \"Selecciona un bloque en el lienzo para editarlo\",\n },\n\n // Toolbar - Common\n toolbar: {\n duplicate: \"Duplicar\",\n delete: \"Eliminar\",\n },\n\n // Title editor toolbar\n titleEditor: {\n toolbar: \"Formato del título\",\n bold: \"Negrita (Ctrl+B)\",\n italic: \"Cursiva (Ctrl+I)\",\n addLink: \"Añadir enlace\",\n },\n\n // Paragraph editor toolbar\n paragraphEditor: {\n toolbar: \"Formato del texto\",\n bold: \"Negrita (Ctrl+B)\",\n italic: \"Cursiva (Ctrl+I)\",\n underline: \"Subrayado (Ctrl+U)\",\n strikethrough: \"Tachado\",\n subscript: \"Subíndice\",\n superscript: \"Superíndice\",\n addLink: \"Añadir enlace\",\n bulletList: \"Lista con viñetas\",\n numberedList: \"Lista numerada\",\n alignLeft: \"Alinear a la izquierda\",\n alignCenter: \"Alinear al centro\",\n alignRight: \"Alinear a la derecha\",\n alignJustify: \"Justificar\",\n clearFormatting: \"Borrar formato\",\n insertEmoji: \"Insertar emoji\",\n fontFamily: \"Familia tipográfica\",\n defaultFont: \"Por defecto\",\n fontSize: \"Tamaño de fuente\",\n defaultSize: \"Por defecto\",\n textColor: \"Color del texto\",\n highlightColor: \"Color de resaltado\",\n lineHeight: \"Interlineado\",\n letterSpacing: \"Espaciado entre letras\",\n emojiItemLabel: \"Insertar emoji {emoji}\",\n },\n\n // Block actions (BlockWrapper)\n blockActions: {\n drag: \"Arrastra para reordenar o pulsa Espacio para mover con el teclado\",\n dragLifted:\n \"Moviendo {block}. Usa las flechas arriba y abajo para reposicionar, Espacio o Intro para soltar, Esc para cancelar.\",\n duplicate: \"Duplicar bloque\",\n delete: \"Eliminar bloque\",\n hiddenOnViewport: \"Oculto en {viewport}\",\n saveAsBlock: \"Guardar como bloque\",\n conditionToggle: \"Alternar condición de visualización\",\n comments: \"Comentarios ({count})\",\n lifted: \"{block} levantado. Posición {position} de {total}.\",\n moved: \"{block} movido a la posición {position} de {total}.\",\n dropped: \"{block} soltado en la posición {position} de {total}.\",\n cancelled: \"Movimiento cancelado. {block} volvió a la posición {position}.\",\n },\n\n // Toolbar - Section\n section: {\n dropHere: \"Suelta los bloques aquí\",\n columns: \"Columnas\",\n column1: \"1 columna\",\n column2: \"2 columnas\",\n column3: \"3 columnas\",\n ratio12: \"Proporción 1:2\",\n ratio21: \"Proporción 2:1\",\n borderRadius: \"Radio del borde\",\n wrapperEnable: \"Añadir contenedor\",\n stackOnMobile: \"Apilar en móvil\",\n },\n\n // Text editor link dialog\n linkDialog: {\n editLink: \"Editar enlace\",\n insertLink: \"Insertar enlace\",\n updateLink: \"Actualizar enlace\",\n removeLink: \"Eliminar enlace\",\n cancel: \"Cancelar\",\n urlPlaceholder: \"https://example.com\",\n urlLabel: \"URL\",\n colorLabel: \"Color del enlace\",\n },\n\n // Toolbar - Title\n title: {\n level: \"Nivel de encabezado\",\n heading1: \"Encabezado 1 (36px)\",\n heading2: \"Encabezado 2 (28px)\",\n heading3: \"Encabezado 3 (22px)\",\n heading4: \"Encabezado 4 (18px)\",\n fontFamily: \"Familia tipográfica\",\n inheritFont: \"Usar fuente de la plantilla\",\n color: \"Color\",\n align: \"Alineación\",\n alignLeft: \"Izquierda\",\n alignCenter: \"Centro\",\n alignRight: \"Derecha\",\n },\n\n // Emoji picker\n emoji: {\n smileys: \"Emoticonos\",\n gestures: \"Gestos\",\n objects: \"Objetos\",\n },\n\n // Toolbar - Image\n image: {\n imageUrl: \"URL de la imagen\",\n imageUrlPlaceholder: \"https://...\",\n altText: \"Texto alternativo\",\n altTextPlaceholder: \"Descripción de la imagen\",\n width: \"Ancho\",\n fullWidth: \"Ancho completo\",\n widthCustom: \"Personalizado\",\n height: \"Altura\",\n heightAuto: \"Automática\",\n heightCustom: \"Personalizada\",\n borderRadius: \"Radio del borde\",\n linkUrl: \"URL del enlace\",\n openInNewTab: \"Abrir en una nueva pestaña\",\n placeholderUrl: \"Imagen de muestra\",\n optional: \"(opcional)\",\n placeholderUrlPlaceholder: \"https://... (solo para diseño)\",\n placeholderUrlTooltip:\n \"Dado que la URL de la imagen utiliza una etiqueta de combinación, puedes proporcionar una imagen real aquí para previsualizar el diseño mientras diseñas. Esto no se incluirá en el resultado final.\",\n clickToAdd: \"Haz clic para añadir la URL de la imagen\",\n browseMedia: \"Explorar archivos multimedia\",\n dropToUpload: \"Suelta la imagen para subirla\",\n uploading: \"Subiendo...\",\n decorative: \"Imagen decorativa\",\n decorativeHint:\n \"Oculto para los lectores de pantalla. Utilízalo solo para espaciadores y adornos visuales.\",\n },\n\n // Toolbar - Video\n video: {\n videoUrl: \"URL del vídeo\",\n videoUrlPlaceholder: \"https://youtube.com/...\",\n openInNewTab: \"Abrir en una nueva pestaña\",\n customThumbnail: \"Miniatura personalizada\",\n optional: \"(opcional)\",\n thumbnailPlaceholder: \"Generada automáticamente desde la URL del vídeo\",\n altText: \"Texto alternativo\",\n altTextPlaceholder: \"Descripción del vídeo\",\n width: \"Ancho\",\n fullWidth: \"Ancho completo\",\n height: \"Altura\",\n heightAuto: \"Automática\",\n heightCustom: \"Personalizada\",\n placeholderUrl: \"Miniatura de muestra\",\n placeholderUrlPlaceholder: \"https://... (solo para diseño)\",\n placeholderUrlTooltip:\n \"Dado que la URL del vídeo utiliza una etiqueta de combinación, puedes proporcionar una miniatura real aquí para previsualizar el diseño mientras diseñas. Esto no se incluirá en el resultado final.\",\n addVideo: \"Añadir una URL de vídeo\",\n },\n\n // Toolbar - Button\n button: {\n fontFamily: \"Familia tipográfica\",\n inheritFont: \"Usar fuente de la plantilla\",\n text: \"Texto\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n openInNewTab: \"Abrir en una nueva pestaña\",\n background: \"Fondo\",\n textColor: \"Color del texto\",\n borderRadius: \"Radio del borde\",\n fontSize: \"Tamaño de fuente\",\n width: \"Ancho\",\n widthAuto: \"Ajustar al contenido\",\n fullWidth: \"Ancho completo\",\n widthCustom: \"Personalizado\",\n },\n\n // Toolbar - Divider\n divider: {\n style: \"Estilo\",\n solid: \"Sólido\",\n dashed: \"Discontinuo\",\n dotted: \"Punteado\",\n color: \"Color\",\n thickness: \"Grosor\",\n },\n\n // Toolbar - Social Icons\n social: {\n icons: \"Iconos\",\n addIcon: \"Añadir icono\",\n addIcons: \"Añadir iconos de redes sociales\",\n removeIcon: \"Eliminar\",\n urlPlaceholder: \"https://...\",\n style: \"Estilo\",\n styleSolid: \"Sólido\",\n styleOutlined: \"Contorneado\",\n styleRounded: \"Redondeado\",\n styleSquare: \"Cuadrado\",\n styleCircle: \"Círculo\",\n size: \"Tamaño\",\n sizeSmall: \"S\",\n sizeMedium: \"M\",\n sizeLarge: \"L\",\n spacing: \"Espaciado\",\n align: \"Alineación\",\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: \"Correo electrónico\",\n website: \"Sitio web\",\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: \"Elementos del menú\",\n addItem: \"Añadir elemento\",\n removeItem: \"Eliminar\",\n text: \"Texto\",\n urlPlaceholder: \"https://example.com\",\n openInNewTab: \"Abrir en una nueva pestaña\",\n bold: \"Negrita\",\n underline: \"Subrayado\",\n color: \"Color\",\n linkColor: \"Color del enlace\",\n fontSize: \"Tamaño de fuente\",\n fontFamily: \"Familia tipográfica\",\n separator: \"Separador\",\n separatorColor: \"Color del separador\",\n spacing: \"Espaciado\",\n textAlign: \"Alineación\",\n addLinks: \"Añadir enlaces al menú\",\n },\n\n // Toolbar - Table\n table: {\n dimensions: \"Dimensiones\",\n rows: \"Filas\",\n columns: \"Columnas\",\n hasHeaderRow: \"Fila de encabezado\",\n headerBackgroundColor: \"Fondo del encabezado\",\n noHeaderBg: \"Sin fondo\",\n borderColor: \"Color del borde\",\n borderWidth: \"Grosor del borde\",\n cellPadding: \"Relleno de la celda\",\n fontFamily: \"Familia tipográfica\",\n fontSize: \"Tamaño de fuente\",\n color: \"Color del texto\",\n textAlign: \"Alineación\",\n cellPlaceholder: \"Introduce el texto...\",\n empty: \"Añadir una tabla\",\n },\n\n // Toolbar - Paragraph\n paragraph: {\n paragraphSpacing: \"Espaciado entre párrafos\",\n },\n\n // Toolbar - Spacer\n spacer: {\n height: \"Altura\",\n },\n\n // Toolbar - Countdown\n countdown: {\n targetDate: \"Fecha límite\",\n timezone: \"Zona horaria\",\n display: \"Visualización\",\n days: \"Días\",\n hours: \"Horas\",\n minutes: \"Minutos\",\n seconds: \"Segundos\",\n separator: \"Separador\",\n fontFamily: \"Familia tipográfica\",\n inheritFont: \"Por defecto\",\n digitFontSize: \"Tamaño de los dígitos\",\n digitColor: \"Color de los dígitos\",\n labelColor: \"Color de la etiqueta\",\n labelFontSize: \"Tamaño de la etiqueta\",\n background: \"Fondo\",\n labels: \"Etiquetas\",\n expiry: \"Mensaje de expiración\",\n expiredMessagePlaceholder: \"Esta oferta ha expirado\",\n expiredImageUrl: \"URL de la imagen caducada\",\n hideOnExpiry: \"Ocultar al expirar\",\n setDate: \"Establece una fecha límite en el panel de configuración\",\n hidden: \"Oculto (expirado)\",\n },\n\n // Custom Blocks\n customBlocks: {\n definitionNotFound:\n \"Tipo de bloque desconocido: este bloque no está registrado\",\n renderError:\n \"No se pudo renderizar este bloque. Comprueba si hay errores en la plantilla del bloque.\",\n fields: {\n required: \"Obligatorio\",\n addItem: \"Añadir elemento\",\n removeItem: \"Eliminar\",\n maxItemsReached: \"Se ha alcanzado el máximo de elementos\",\n minItemsRequired: \"Se requiere un mínimo de {count} elementos\",\n },\n toolbar: {\n noDefinition:\n \"Registra este tipo de bloque en la configuración de tu SDK para editar sus propiedades\",\n },\n dataSource: {\n fetchButton: \"Cargar contenido\",\n changeButton: \"Cambiar\",\n fetching: \"Cargando...\",\n readOnlyTooltip: \"Este valor se carga desde tu fuente de datos\",\n fetchError: \"Error al cargar el contenido\",\n },\n },\n\n // Toolbar - HTML\n html: {\n content: \"Contenido HTML\",\n preview: \"Bloque HTML personalizado\",\n empty: \"Añadir contenido HTML en el panel\",\n sanitizationHint:\n \"El HTML se exporta tal cual y no se sanea — asegúrate de que el contenido sea seguro.\",\n },\n\n // Toolbar - Common block settings\n blockSettings: {\n spacing: \"Espaciado\",\n padding: \"Relleno\",\n background: \"Fondo\",\n color: \"Color\",\n display: \"Visualización\",\n showOnDesktop: \"Mostrar en escritorio\",\n showOnMobile: \"Mostrar en móvil\",\n hiddenOnDevice: \"Oculto en {device}\",\n displayCondition: \"Condición de visualización\",\n selectCondition: \"Seleccionar condición\",\n removeCondition: \"Eliminar condición\",\n noCondition: \"Siempre visible\",\n conditionApplied: \"Condición aplicada\",\n customCondition: \"Condición personalizada\",\n customConditionLabel: \"Nombre de la condición\",\n customConditionBefore: \"Antes (lógica de apertura)\",\n customConditionAfter: \"Después (lógica de cierre)\",\n applyCondition: \"Aplicar\",\n cancelCondition: \"Cancelar\",\n customBadge: \"Personalizado\",\n restoreHiddenBlocks: \"Mostrar todos los bloques ocultos\",\n },\n\n // Template settings\n templateSettings: {\n layout: \"Diseño\",\n widthPreset: \"Ancho predefinido\",\n customWidth: \"Ancho personalizado\",\n appearance: \"Apariencia\",\n backgroundColor: \"Color de fondo\",\n textColor: \"Color del texto\",\n linkColor: \"Color del enlace\",\n linkUnderline: \"Subrayar enlaces\",\n fontFamily: \"Familia tipográfica\",\n preheaderText: \"Texto del preencabezado\",\n preheaderTextPlaceholder:\n \"Texto de vista previa que se muestra después del asunto en la bandeja de entrada...\",\n preheaderTextHint:\n \"Este texto aparece después del asunto en las vistas previas de los clientes de correo electrónico. Admite etiquetas de combinación.\",\n language: \"Idioma\",\n contentLocale: \"Idioma del contenido\",\n contentLocaleHint:\n \"Código BCP 47 (por ejemplo, es, en, de). Establece el atributo lang del correo electrónico renderizado para que los lectores de pantalla pronuncien el contenido correctamente.\",\n tips: \"Consejos\",\n tip1: \"600px es el ancho estándar para las plantillas de correo electrónico\",\n tip2: \"Usa fuentes seguras para la web para una mejor compatibilidad\",\n tip3: \"Los fondos claros funcionan mejor para la legibilidad\",\n },\n\n // Spacing control\n spacingControl: {\n lockAll: \"Bloquear todos los lados\",\n unlock: \"Desbloquear lados\",\n top: \"Superior\",\n right: \"Derecho\",\n bottom: \"Inferior\",\n left: \"Izquierdo\",\n decreaseTop: \"Disminuir superior\",\n increaseTop: \"Aumentar superior\",\n decreaseLeft: \"Disminuir izquierdo\",\n increaseLeft: \"Aumentar izquierdo\",\n decreaseRight: \"Disminuir derecho\",\n increaseRight: \"Aumentar derecho\",\n decreaseBottom: \"Disminuir inferior\",\n increaseBottom: \"Aumentar inferior\",\n },\n\n // Color Picker\n colorPicker: {\n pickColor: \"Elegir un color\",\n hexValue: \"Valor de color Hex\",\n notSet: \"No establecido\",\n clear: \"Limpiar color\",\n presetColors: \"Colores predefinidos\",\n },\n\n // Merge Tag\n mergeTag: {\n clickToEdit: \"Haz clic para editar\",\n remove: \"Eliminar etiqueta de combinación\",\n insert: \"Insertar etiqueta de combinación\",\n insertShort: \"Etiqueta de combinación\",\n editValue: \"Editar valor de la etiqueta de combinación\",\n deleteMergeTag: \"Eliminar etiqueta de combinación\",\n suggestionEmpty: \"No hay etiquetas de combinación coincidentes\",\n picker: {\n title: \"Insertar etiqueta de combinación\",\n searchPlaceholder: \"Buscar etiquetas de combinación\",\n searchAriaLabel: \"Buscar etiquetas de combinación\",\n noResults: \"No hay etiquetas de combinación coincidentes\",\n empty: \"No hay etiquetas de combinación configuradas\",\n otherGroup: \"Otro\",\n close: \"Cerrar\",\n groupCount: \"{count}\",\n sample: \"Vista previa: {sample}\",\n },\n },\n\n // Logic tags (standalone, separate from merge tags)\n logicTag: {\n insert: \"Insertar lógica\",\n insertShort: \"Lógica\",\n picker: {\n title: \"Insertar lógica\",\n searchPlaceholder: \"Buscar etiquetas de lógica\",\n searchAriaLabel: \"Buscar etiquetas de lógica\",\n noResults: \"No hay etiquetas de lógica coincidentes\",\n empty: \"No hay etiquetas de lógica configuradas\",\n otherGroup: \"Otro\",\n close: \"Cerrar\",\n },\n },\n\n // Canvas\n canvas: {\n noBlocks: \"Aún no hay bloques\",\n dragHint: \"Comienza desde cero arrastrando bloques desde la barra lateral\",\n dropHere: \"Suelta aquí\",\n aiHintChat: \"o deja que\",\n aiHintChatSuffix: \"genere una plantilla completa para ti en segundos\",\n aiHintDesign:\n \"¿Tienes un diseño existente? Sube una captura de pantalla, imagen o PDF y\",\n aiHintDesignSuffix: \"lo recreará instantáneamente\",\n },\n\n // Sidebar\n savedBlocks: {\n title: \"Bloques guardados\",\n saveAsBlock: \"Guardar como bloque\",\n name: \"Nombre\",\n namePlaceholder: \"p. ej. Encabezado, Pie de página, CTA...\",\n save: \"Guardar bloque\",\n saving: \"Guardando...\",\n cancel: \"Cancelar\",\n empty: \"Aún no hay bloques guardados\",\n emptyHint: \"Guarda bloques de tus plantillas para reutilizarlos más tarde.\",\n noResults: \"Ningún bloque guardado coincide con tu búsqueda\",\n search: \"Buscar bloques guardados...\",\n loading: \"Cargando bloques guardados…\",\n category: \"Categoría\",\n categoryPlaceholder: \"p. ej. Cabeceras, Promociones... (opcional)\",\n allCategories: \"Todas las categorías\",\n filterByCategory: \"Filtrar por categoría\",\n insert: \"Insertar\",\n rename: \"Cambiar nombre\",\n delete: \"Eliminar\",\n deleteConfirm: \"¿Eliminar este bloque guardado?\",\n blockCount: \"{count} bloque(s)\",\n browse: \"Explorar bloques guardados\",\n selectToPreview: \"Selecciona un bloque guardado para previsualizarlo\",\n insertAtBeginning: \"Al principio\",\n insertAfterBlock: \"Después de {block}\",\n insertAtEnd: \"Al final\",\n insertPosition: \"Posición de inserción\",\n close: \"Cerrar\",\n pickToolbar: \"Selección de bloque guardado\",\n pickCount: \"{count} bloque(s) seleccionado(s)\",\n pickHint: \"Haz clic en los bloques para añadirlos o quitarlos\",\n savingCount: \"Guardando {count} bloque(s):\",\n reorderHint:\n \"Arrastra para reordenar: los bloques se guardan en este orden\",\n reorderHandle: \"Reordenar {block}, posición {position} de {total}\",\n reorderAnnouncement: \"{block} movido a la posición {position} de {total}\",\n expand: \"Expandir\",\n collapse: \"Contraer\",\n expandPreview: \"Expandir la vista previa de {block}\",\n collapsePreview: \"Contraer la vista previa de {block}\",\n },\n comments: {\n button: \"Comentarios\",\n title: \"Comentarios\",\n placeholder: \"Escribe un comentario...\",\n replyPlaceholder: \"Escribe una respuesta...\",\n reply: \"Responder\",\n resolve: \"Resolver\",\n unresolve: \"Reabrir\",\n delete: \"Eliminar\",\n edit: \"Editar\",\n cancel: \"Cancelar\",\n save: \"Guardar\",\n noComments: \"Aún no hay comentarios\",\n noCommentsHint:\n \"Inicia una conversación añadiendo un comentario a la plantilla o a un bloque concreto.\",\n deleteConfirm: \"¿Eliminar este comentario?\",\n filterAll: \"Todos\",\n filterUnresolved: \"Sin resolver\",\n filterBlock: \"Este bloque\",\n jumpToBlock: \"Bloque\",\n ownedByYou: \"Tú\",\n edited: \"editado\",\n resolvedBy: \"Resuelto por {name}\",\n replyOne: \"{count} respuesta\",\n replyMany: \"{count} respuestas\",\n missingBlock: \"Bloque no encontrado\",\n saveTemplateFirst: \"Guarda la plantilla antes de comentar en este bloque.\",\n },\n versionHistory: {\n tooltip: \"Historial de versiones\",\n dropdownTitle: \"Historial de versiones\",\n empty: \"Todavía no hay versiones\",\n auto: \"auto\",\n olderVersion: \"Versión anterior\",\n newerVersion: \"Versión más reciente\",\n },\n versionPreview: {\n message: \"Estás viendo una versión anterior de esta plantilla.\",\n cancel: \"Cancelar\",\n restore: \"Restaurar esta versión\",\n restoreConfirm: {\n title: \"¿Restaurar esta versión?\",\n unsavedWithSave:\n \"Tienes cambios sin guardar. Guárdalos primero y se conservarán en el historial; si restauras sin guardar, se perderán.\",\n unsavedNoSave:\n \"Tienes cambios sin guardar y no hay dónde guardarlos. Al restaurar esta versión se perderán.\",\n saveAndRestore: \"Guardar y restaurar\",\n restoreAnyway: \"Restaurar de todos modos\",\n cancel: \"Cancelar\",\n },\n },\n previewResolution: {\n resolving: \"Resolviendo la vista previa…\",\n failed:\n \"No se pudo resolver la vista previa; se muestra la plantilla sin resolver.\",\n hint: \"La vista previa usa datos resueltos por tu backend.\",\n },\n mergeTagPreview: {\n label: \"Vista de etiquetas de combinación\",\n sample: \"Ejemplo\",\n labelView: \"Etiqueta\",\n },\n testEmail: {\n title: \"Enviar correo de prueba\",\n recipientLabel: \"Destinatario\",\n recipientPlaceholder: \"tu@ejemplo.com\",\n invalidAddress: \"Introduce una dirección de correo válida.\",\n preview: \"Vista previa\",\n previewHint:\n \"Las etiquetas de combinación se muestran sin resolver — tu backend las rellena.\",\n previewHintSample:\n \"Las etiquetas de combinación muestran valores de ejemplo; tu backend inserta los datos reales.\",\n recipientNotAllowed:\n \"Esa dirección no está en la lista de destinatarios permitidos.\",\n send: \"Enviar\",\n sending: \"Enviando...\",\n cancel: \"Cancelar\",\n success: \"Correo de prueba enviado correctamente\",\n button: \"Prueba\",\n },\n sidebarNav: {\n browseSavedBlocks: \"Explorar bloques guardados\",\n palette: \"Paleta de bloques\",\n insertBlock: \"Insertar bloque {block}\",\n },\n\n // Landmark region labels for assistive technology\n landmarks: {\n canvas: \"Lienzo del correo electrónico\",\n blockToolbar: \"Propiedades del bloque\",\n rightSidebar: \"Propiedades del bloque y configuración de la plantilla\",\n reorderAnnouncements: \"Anuncios de reordenación de bloques\",\n },\n\n // Design Reference (cloud)\n errors: {\n editorLoading: \"Cargando el editor...\",\n editorLoadFailed: \"Error al cargar el editor.\",\n retry: \"Reintentar\",\n },\n\n issues: {\n panelTitle: \"Problemes\",\n panelTabLabel: \"Problemes\",\n groupErrors: \"Errores\",\n groupWarnings: \"Advertencias\",\n groupInfo: \"Información\",\n jump: \"Saltar al bloque\",\n fix: \"Corregir\",\n emptyState: \"Sin problemas, todo se ve bien.\",\n badgeError: \"Tiene errores\",\n badgeWarning: \"Tiene advertencias\",\n issueCountTooltip: \"{count} problema(s)\",\n },\n\n smallScreen: {\n title: \"Se requiere una pantalla más grande\",\n message:\n \"El editor necesita más espacio del que ofrece esta pantalla. Ábrelo en una tableta o computadora de escritorio para comenzar a editar.\",\n },\n};\n\nexport default es;\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import { H as e, N as t, Q as n, S as r, U as i, at as a, c as o, ct as s, f as c, g as l, h as u, k as d, l as f, lt as p, m, o as h, p as g, ut as _ } from "./draggable-D2vo-aQI.js";
2
- import { a as v, d as y, o as b, r as x } from "./src-BD60gqPW.js";
3
- import { t as S } from "./useI18n-DIhawILp.js";
4
- import { t as C } from "./useMergeTag-lWo7So18.js";
5
- import { _ as w, g as T, h as E, n as D, t as O, v as k, y as A } from "./tiptap-Ey0FpaX7.js";
6
- import { i as j, r as M, t as N } from "./MergeTagSuggestion-B9vL0VaG.js";
1
+ import { H as e, N as t, Q as n, S as r, U as i, at as a, c as o, ct as s, f as c, g as l, h as u, k as d, l as f, lt as p, m, o as h, p as g, ut as _ } from "./draggable-kbOhCgnk.js";
2
+ import { a as v, d as y, o as b, r as x } from "./src-CLoCCDfs.js";
3
+ import { t as S } from "./useI18n-DCbvHv6W.js";
4
+ import { t as C } from "./useMergeTag-CbuagYNK.js";
5
+ import { _ as w, g as T, h as E, n as D, t as O, v as k, y as A } from "./tiptap-Epe8m3Vo.js";
6
+ import { i as j, r as M, t as N } from "./MergeTagSuggestion-t8Uj00Er.js";
7
7
  //#region src/extensions/FontSize.ts
8
8
  var P = E.create({
9
9
  name: "fontSize",
@@ -442,4 +442,4 @@ var W = w.create({
442
442
  //#endregion
443
443
  export { P as FontSize, F as LetterSpacing, I as LineBoundaryKeys, L as LineHeight, W as LogicMergeTagNode, J as MergeTagNode, N as MergeTagSuggestion, M as filterMergeTags, j as handleSuggestionKeyDown };
444
444
 
445
- //# sourceMappingURL=extensions-C87Z6_23.js.map
445
+ //# sourceMappingURL=extensions-CeP0iOPC.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensions-C87Z6_23.js","names":[],"sources":["../../../src/extensions/FontSize.ts","../../../src/extensions/LetterSpacing.ts","../../../src/extensions/LineBoundaryKeys.ts","../../../src/extensions/LineHeight.ts","../../../src/extensions/LogicMergeTagNodeView.vue","../../../src/extensions/LogicMergeTagNodeView.vue","../../../src/extensions/isNodeSelected.ts","../../../src/extensions/renderVueNodeView.ts","../../../src/extensions/LogicMergeTagNode.ts","../../../src/extensions/MergeTagNodeView.vue","../../../src/extensions/MergeTagNodeView.vue","../../../src/extensions/MergeTagNode.ts"],"sourcesContent":["import { Extension } from \"@tiptap/core\";\n\nexport interface FontSizeOptions {\n types: string[];\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n fontSize: {\n setFontSize: (size: string) => ReturnType;\n unsetFontSize: () => ReturnType;\n };\n }\n}\n\nexport const FontSize = Extension.create<FontSizeOptions>({\n name: \"fontSize\",\n\n addOptions() {\n return {\n types: [\"textStyle\"],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n fontSize: {\n default: null,\n parseHTML: (element) =>\n element.style.fontSize?.replace(/['\"]+/g, \"\") || null,\n renderHTML: (attributes) => {\n if (!attributes.fontSize) {\n return {};\n }\n return {\n style: `font-size: ${attributes.fontSize}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setFontSize:\n (size: string) =>\n ({ chain }) => {\n return chain().setMark(\"textStyle\", { fontSize: size }).run();\n },\n unsetFontSize:\n () =>\n ({ chain }) => {\n return chain()\n .setMark(\"textStyle\", { fontSize: null })\n .removeEmptyTextStyle()\n .run();\n },\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\nexport interface LetterSpacingOptions {\n types: string[];\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n letterSpacing: {\n setLetterSpacing: (spacing: string) => ReturnType;\n unsetLetterSpacing: () => ReturnType;\n };\n }\n}\n\nexport const LetterSpacing = Extension.create<LetterSpacingOptions>({\n name: \"letterSpacing\",\n\n addOptions() {\n return {\n types: [\"textStyle\"],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n letterSpacing: {\n default: null,\n parseHTML: (element) =>\n element.style.letterSpacing?.replace(/['\"]+/g, \"\") || null,\n renderHTML: (attributes) => {\n if (!attributes.letterSpacing) {\n return {};\n }\n return {\n style: `letter-spacing: ${attributes.letterSpacing}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setLetterSpacing:\n (spacing: string) =>\n ({ chain }) => {\n return chain().setMark(\"textStyle\", { letterSpacing: spacing }).run();\n },\n unsetLetterSpacing:\n () =>\n ({ chain }) => {\n return chain()\n .setMark(\"textStyle\", { letterSpacing: null })\n .removeEmptyTextStyle()\n .run();\n },\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\n/**\n * Routes plain End/Home through `Selection.modify` instead of the browser's\n * native caret movement.\n *\n * Chromium (verified 140–151, including stable Chrome) has a bug where a\n * native End or Home pressed while a triple-click selection is active puts\n * Blink's selection state into a mode where the next typed character\n * natively smooth-scrolls the nearest scrollable ancestor (the editor's\n * canvas, `.tpl-body`) to its very bottom (End) or top (Home), dragging the\n * caret out of view. The state cannot be repaired after the fact — clearing\n * or re-setting the DOM selection, blur/refocus, and preventDefault on the\n * clicks all fail — but a programmatic caret move never arms it.\n *\n * `Selection.modify(\"move\", direction, \"lineboundary\")` is the exact\n * equivalent of the native key (visual line boundary, bidi-aware via the\n * logical forward/backward directions), so behavior is unchanged for users.\n * Shift+End / Shift+Home extend selections natively and do not trigger the\n * bug, so only the plain keys are bound — a keymap entry without modifiers\n * never matches the shifted keys.\n */\nexport const LineBoundaryKeys = Extension.create({\n name: \"lineBoundaryKeys\",\n\n addKeyboardShortcuts() {\n const moveToLineBoundary =\n (direction: \"forward\" | \"backward\") =>\n ({ editor }: { editor: { view: unknown } }): boolean => {\n const view = editor.view as {\n composing: boolean;\n root: DocumentOrShadowRoot & {\n getSelection?: () => Selection | null;\n };\n dom: HTMLElement;\n };\n // During IME composition End/Home commit the composition; leave\n // that to the browser.\n if (!view || view.composing) return false;\n // `view.root` is the editable's Document or ShadowRoot, so the\n // selection resolves correctly in both mount modes. ShadowRoot's\n // getSelection is Chromium-only; elsewhere fall back to the owner\n // document (Chromium is also the only engine with the bug).\n const selection =\n typeof view.root?.getSelection === \"function\"\n ? view.root.getSelection()\n : (view.dom?.ownerDocument?.getSelection?.() ?? null);\n // `modify` is non-standard; without it, or with a selection that\n // is not ours, native handling is the safer default.\n if (!selection || typeof selection.modify !== \"function\") return false;\n if (!selection.anchorNode || !view.dom.contains(selection.anchorNode)) {\n return false;\n }\n selection.modify(\"move\", direction, \"lineboundary\");\n return true;\n };\n\n return {\n End: moveToLineBoundary(\"forward\"),\n Home: moveToLineBoundary(\"backward\"),\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\nexport interface LineHeightOptions {\n types: string[];\n defaultLineHeight: string;\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n lineHeight: {\n setLineHeight: (lineHeight: string) => ReturnType;\n unsetLineHeight: () => ReturnType;\n };\n }\n}\n\nexport const LineHeight = Extension.create<LineHeightOptions>({\n name: \"lineHeight\",\n\n addOptions() {\n return {\n types: [\"paragraph\"],\n defaultLineHeight: \"1.5\",\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n lineHeight: {\n default: null,\n parseHTML: (element) => element.style.lineHeight || null,\n renderHTML: (attributes) => {\n if (!attributes.lineHeight) {\n return {};\n }\n return {\n style: `line-height: ${attributes.lineHeight}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setLineHeight:\n (lineHeight: string) =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.updateAttributes(type, { lineHeight }),\n );\n },\n unsetLineHeight:\n () =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.resetAttributes(type, \"lineHeight\"),\n );\n },\n };\n },\n});\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n} from \"@templatical/types\";\nimport type { Editor } from \"@tiptap/core\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n value: string;\n keyword: string;\n };\n };\n editor: Editor;\n getPos: () => number;\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { syntax } = useMergeTag();\nconst { t } = useI18n();\n\nconst isValid = computed(() =>\n isLogicMergeTagValue(props.node.attrs.value, syntax),\n);\nconst displayKeyword = computed(() =>\n getLogicMergeTagKeyword(props.node.attrs.value, syntax),\n);\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\nlet handled = false;\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n handled = false;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n if (handled) {\n return;\n }\n handled = true;\n\n const newValue = editValue.value.trim();\n if (!newValue) {\n isEditing.value = false;\n return;\n }\n\n if (newValue !== props.node.attrs.value) {\n props.updateAttributes({\n value: newValue,\n keyword: isLogicMergeTagValue(newValue, syntax)\n ? getLogicMergeTagKeyword(newValue, syntax)\n : \"\",\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n :class=\"\n isValid\n ? 'tpl-logic-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase tpl:select-none'\n : ''\n \"\n :style=\"\n isValid\n ? 'background-color: transparent; border: 1.5px solid color-mix(in srgb, var(--tpl-primary) 50%, transparent); color: var(--tpl-primary);'\n : ''\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-40 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:normal-case tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode: valid merge tag -->\n <span\n v-else-if=\"isValid\"\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayKeyword }}\n </span>\n <!-- Display mode: invalid (plain text) -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ node.attrs.value }}\n </span>\n <button\n v-if=\"isValid\"\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all tpl:hover:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n} from \"@templatical/types\";\nimport type { Editor } from \"@tiptap/core\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n value: string;\n keyword: string;\n };\n };\n editor: Editor;\n getPos: () => number;\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { syntax } = useMergeTag();\nconst { t } = useI18n();\n\nconst isValid = computed(() =>\n isLogicMergeTagValue(props.node.attrs.value, syntax),\n);\nconst displayKeyword = computed(() =>\n getLogicMergeTagKeyword(props.node.attrs.value, syntax),\n);\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\nlet handled = false;\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n handled = false;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n if (handled) {\n return;\n }\n handled = true;\n\n const newValue = editValue.value.trim();\n if (!newValue) {\n isEditing.value = false;\n return;\n }\n\n if (newValue !== props.node.attrs.value) {\n props.updateAttributes({\n value: newValue,\n keyword: isLogicMergeTagValue(newValue, syntax)\n ? getLogicMergeTagKeyword(newValue, syntax)\n : \"\",\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n :class=\"\n isValid\n ? 'tpl-logic-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase tpl:select-none'\n : ''\n \"\n :style=\"\n isValid\n ? 'background-color: transparent; border: 1.5px solid color-mix(in srgb, var(--tpl-primary) 50%, transparent); color: var(--tpl-primary);'\n : ''\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-40 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:normal-case tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode: valid merge tag -->\n <span\n v-else-if=\"isValid\"\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayKeyword }}\n </span>\n <!-- Display mode: invalid (plain text) -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ node.attrs.value }}\n </span>\n <button\n v-if=\"isValid\"\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all tpl:hover:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","import type { Editor } from \"@tiptap/core\";\n\n/**\n * Decides whether MergeTagNode / LogicMergeTagNode should swallow a\n * Backspace/Delete keystroke (returning `true` from a TipTap keymap\n * suppresses the default behavior).\n *\n * Only suppresses in the cursor-adjacent case so the \"first press\n * selects the atom, second press deletes it\" UX works. Range selections\n * (Cmd+A, drag-select, double-click-word) explicitly fall through —\n * default `replaceSelection` then deletes the entire range including\n * any merge-tag atoms inside it.\n *\n * Earlier revisions also returned `true` whenever `nodesBetween($from,\n * $to)` found a merge tag anywhere in the selection range — which\n * silently broke Cmd+A + Backspace for any paragraph containing a\n * merge tag (entire deletion was cancelled, nothing happened). The\n * cursor-adjacent protection is the only piece that should survive.\n */\nexport function isNodeSelected(editor: Editor, nodeTypeName: string): boolean {\n const { $from, $to } = editor.state.selection;\n\n // Range selection: let TipTap's default range-delete run. Even when\n // the range contains atom nodes, ProseMirror's replaceSelection\n // handles atomic deletion correctly.\n if ($from.pos !== $to.pos) return false;\n\n // Cursor-adjacent atom: protect from single-keystroke deletion.\n // (`$from.pos > 0` guards against reading `nodeBefore` at doc start\n // where ProseMirror's index would be undefined for nodeBefore.)\n if ($from.pos > 0 && $from.nodeBefore?.type.name === nodeTypeName) {\n return true;\n }\n if ($from.nodeAfter?.type.name === nodeTypeName) {\n return true;\n }\n\n return false;\n}\n","import type { Component } from \"vue\";\nimport { VueNodeViewRenderer } from \"@tiptap/vue-3\";\n\n/**\n * Typed wrapper for VueNodeViewRenderer that handles the known type mismatch\n * between Vue SFC default exports and TipTap's expected component type.\n */\nexport function renderVueNodeView(component: Component) {\n return VueNodeViewRenderer(\n component as Parameters<typeof VueNodeViewRenderer>[0],\n );\n}\n","import LogicMergeTagNodeView from \"./LogicMergeTagNodeView.vue\";\nimport type { SyntaxPreset } from \"@templatical/types\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n SYNTAX_PRESETS,\n} from \"@templatical/types\";\nimport { InputRule, mergeAttributes, Node, PasteRule } from \"@tiptap/core\";\nimport { isNodeSelected } from \"./isNodeSelected\";\nimport { renderVueNodeView } from \"./renderVueNodeView\";\n\nexport interface LogicMergeTagNodeOptions {\n syntax: SyntaxPreset;\n}\n\nexport const LogicMergeTagNode = Node.create<LogicMergeTagNodeOptions>({\n name: \"logicMergeTagNode\",\n\n group: \"inline\",\n\n inline: true,\n\n atom: true,\n\n addOptions() {\n return {\n syntax: SYNTAX_PRESETS.liquid,\n };\n },\n\n addAttributes() {\n return {\n // Both attributes are state, not markup, same as `MergeTagNode`:\n // `renderHTML()` emits the canonical `data-logic-merge-tag` /\n // `data-keyword` pair and `parseHTML` reads only those. `rendered: false`\n // keeps TipTap from also serializing each attribute under its own name,\n // which would put a write-only duplicate of the same data on every tag.\n value: {\n default: \"\",\n rendered: false,\n parseHTML: (element) =>\n element.getAttribute(\"data-logic-merge-tag\") || \"\",\n },\n keyword: {\n default: \"\",\n rendered: false,\n parseHTML: (element) =>\n element.getAttribute(\"data-keyword\") || element.textContent || \"\",\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span[data-logic-merge-tag]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n if (!isLogicMergeTagValue(node.attrs.value, this.options.syntax)) {\n return [\"span\", {}, node.attrs.value];\n }\n\n const keyword = getLogicMergeTagKeyword(\n node.attrs.value,\n this.options.syntax,\n );\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-logic-merge-tag\": node.attrs.value,\n \"data-keyword\": keyword,\n }),\n keyword,\n ];\n },\n\n addNodeView() {\n return renderVueNodeView(LogicMergeTagNodeView);\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () => isNodeSelected(this.editor, this.name),\n Delete: () => isNodeSelected(this.editor, this.name),\n };\n },\n\n addInputRules() {\n const inputRegex = new RegExp(this.options.syntax.logic.source + \"$\", \"\");\n\n return [\n new InputRule({\n find: inputRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n if (!isLogicMergeTagValue(fullValue, this.options.syntax)) {\n return;\n }\n\n const keyword = getLogicMergeTagKeyword(\n fullValue,\n this.options.syntax,\n );\n\n const node = this.type.create({\n value: fullValue,\n keyword,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n\n addPasteRules() {\n const pasteRegex = new RegExp(this.options.syntax.logic.source, \"g\");\n\n return [\n new PasteRule({\n find: pasteRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n if (!isLogicMergeTagValue(fullValue, this.options.syntax)) {\n return;\n }\n\n const keyword = getLogicMergeTagKeyword(\n fullValue,\n this.options.syntax,\n );\n\n const node = this.type.create({\n value: fullValue,\n keyword,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n});\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n label: string;\n value: string;\n };\n };\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { getMergeTagLabel } = useMergeTag();\nconst { t } = useI18n();\n\nconst displayLabel = computed(() => getMergeTagLabel(props.node.attrs.value));\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n const newValue = editValue.value.trim();\n if (newValue && newValue !== props.node.attrs.value) {\n // Update with new value and derive label from it\n props.updateAttributes({\n value: newValue,\n label: getMergeTagLabel(newValue),\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n class=\"tpl-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium tpl:select-none tpl:text-[var(--tpl-primary)]\"\n style=\"\n background-color: color-mix(in srgb, var(--tpl-primary) 20%, transparent);\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-32 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayLabel }}\n </span>\n <button\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all tpl:hover:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n label: string;\n value: string;\n };\n };\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { getMergeTagLabel } = useMergeTag();\nconst { t } = useI18n();\n\nconst displayLabel = computed(() => getMergeTagLabel(props.node.attrs.value));\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n const newValue = editValue.value.trim();\n if (newValue && newValue !== props.node.attrs.value) {\n // Update with new value and derive label from it\n props.updateAttributes({\n value: newValue,\n label: getMergeTagLabel(newValue),\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n class=\"tpl-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium tpl:select-none tpl:text-[var(--tpl-primary)]\"\n style=\"\n background-color: color-mix(in srgb, var(--tpl-primary) 20%, transparent);\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-32 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayLabel }}\n </span>\n <button\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all tpl:hover:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","import MergeTagNodeView from \"./MergeTagNodeView.vue\";\nimport type { MergeTag, SyntaxPreset } from \"@templatical/types\";\nimport { getMergeTagLabel, SYNTAX_PRESETS } from \"@templatical/types\";\nimport { InputRule, mergeAttributes, Node, PasteRule } from \"@tiptap/core\";\nimport { isNodeSelected } from \"./isNodeSelected\";\nimport { renderVueNodeView } from \"./renderVueNodeView\";\n\nexport interface MergeTagNodeOptions {\n mergeTags: MergeTag[];\n syntax: SyntaxPreset;\n}\n\n/**\n * Inserted-node attrs are intentionally limited to `label` + `value`. The\n * `MergeTag` interface also carries optional `group` / `description` for\n * the built-in picker, but those are display-only and must NOT leak into\n * the document JSON — they would bloat templates and pollute serialized\n * state. `Pick<>` makes the constraint explicit at the type level.\n */\nexport type InsertMergeTagAttrs = Pick<MergeTag, \"label\" | \"value\">;\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n mergeTagNode: {\n insertMergeTag: (attrs: InsertMergeTagAttrs) => ReturnType;\n };\n }\n}\n\nexport const MergeTagNode = Node.create<MergeTagNodeOptions>({\n name: \"mergeTagNode\",\n\n group: \"inline\",\n\n inline: true,\n\n atom: true,\n\n addOptions() {\n return {\n mergeTags: [],\n syntax: SYNTAX_PRESETS.liquid,\n };\n },\n\n addAttributes() {\n return {\n // Both attributes are state, not markup: `renderHTML()` below emits the\n // canonical `data-merge-tag` / `data-label` pair and `parseHTML` reads\n // only those. `rendered: false` keeps TipTap from also serializing each\n // attribute under its own name, which would put a write-only duplicate\n // of the same data on every tag — invalid on a `<span>`, and paid again\n // through storage, autosave, snapshots and version history.\n label: {\n default: \"\",\n rendered: false,\n parseHTML: (element) =>\n element.getAttribute(\"data-label\") || element.textContent || \"\",\n },\n value: {\n default: \"\",\n rendered: false,\n parseHTML: (element) => element.getAttribute(\"data-merge-tag\") || \"\",\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span[data-merge-tag]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const label = getMergeTagLabel(node.attrs.value, this.options.mergeTags);\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-merge-tag\": node.attrs.value,\n \"data-label\": label,\n }),\n label,\n ];\n },\n\n addNodeView() {\n return renderVueNodeView(MergeTagNodeView);\n },\n\n addCommands() {\n return {\n insertMergeTag:\n (attrs: InsertMergeTagAttrs) =>\n ({ commands }) => {\n // Whitelist explicitly — even if a caller smuggles extra keys via\n // a wider type assertion, only label/value reach the node attrs.\n return commands.insertContent({\n type: this.name,\n attrs: { label: attrs.label, value: attrs.value },\n });\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () => isNodeSelected(this.editor, this.name),\n Delete: () => isNodeSelected(this.editor, this.name),\n };\n },\n\n addInputRules() {\n const inputRegex = new RegExp(this.options.syntax.value.source + \"$\", \"\");\n\n return [\n new InputRule({\n find: inputRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n const label = getMergeTagLabel(fullValue, this.options.mergeTags);\n\n const node = this.type.create({\n label,\n value: fullValue,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n\n addPasteRules() {\n const pasteRegex = new RegExp(this.options.syntax.value.source, \"g\");\n\n return [\n new PasteRule({\n find: pasteRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n const label = getMergeTagLabel(fullValue, this.options.mergeTags);\n\n const node = this.type.create({\n label,\n value: fullValue,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"extensions-CeP0iOPC.js","names":[],"sources":["../../../src/extensions/FontSize.ts","../../../src/extensions/LetterSpacing.ts","../../../src/extensions/LineBoundaryKeys.ts","../../../src/extensions/LineHeight.ts","../../../src/extensions/LogicMergeTagNodeView.vue","../../../src/extensions/LogicMergeTagNodeView.vue","../../../src/extensions/isNodeSelected.ts","../../../src/extensions/renderVueNodeView.ts","../../../src/extensions/LogicMergeTagNode.ts","../../../src/extensions/MergeTagNodeView.vue","../../../src/extensions/MergeTagNodeView.vue","../../../src/extensions/MergeTagNode.ts"],"sourcesContent":["import { Extension } from \"@tiptap/core\";\n\nexport interface FontSizeOptions {\n types: string[];\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n fontSize: {\n setFontSize: (size: string) => ReturnType;\n unsetFontSize: () => ReturnType;\n };\n }\n}\n\nexport const FontSize = Extension.create<FontSizeOptions>({\n name: \"fontSize\",\n\n addOptions() {\n return {\n types: [\"textStyle\"],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n fontSize: {\n default: null,\n parseHTML: (element) =>\n element.style.fontSize?.replace(/['\"]+/g, \"\") || null,\n renderHTML: (attributes) => {\n if (!attributes.fontSize) {\n return {};\n }\n return {\n style: `font-size: ${attributes.fontSize}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setFontSize:\n (size: string) =>\n ({ chain }) => {\n return chain().setMark(\"textStyle\", { fontSize: size }).run();\n },\n unsetFontSize:\n () =>\n ({ chain }) => {\n return chain()\n .setMark(\"textStyle\", { fontSize: null })\n .removeEmptyTextStyle()\n .run();\n },\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\nexport interface LetterSpacingOptions {\n types: string[];\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n letterSpacing: {\n setLetterSpacing: (spacing: string) => ReturnType;\n unsetLetterSpacing: () => ReturnType;\n };\n }\n}\n\nexport const LetterSpacing = Extension.create<LetterSpacingOptions>({\n name: \"letterSpacing\",\n\n addOptions() {\n return {\n types: [\"textStyle\"],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n letterSpacing: {\n default: null,\n parseHTML: (element) =>\n element.style.letterSpacing?.replace(/['\"]+/g, \"\") || null,\n renderHTML: (attributes) => {\n if (!attributes.letterSpacing) {\n return {};\n }\n return {\n style: `letter-spacing: ${attributes.letterSpacing}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setLetterSpacing:\n (spacing: string) =>\n ({ chain }) => {\n return chain().setMark(\"textStyle\", { letterSpacing: spacing }).run();\n },\n unsetLetterSpacing:\n () =>\n ({ chain }) => {\n return chain()\n .setMark(\"textStyle\", { letterSpacing: null })\n .removeEmptyTextStyle()\n .run();\n },\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\n/**\n * Routes plain End/Home through `Selection.modify` instead of the browser's\n * native caret movement.\n *\n * Chromium (verified 140–151, including stable Chrome) has a bug where a\n * native End or Home pressed while a triple-click selection is active puts\n * Blink's selection state into a mode where the next typed character\n * natively smooth-scrolls the nearest scrollable ancestor (the editor's\n * canvas, `.tpl-body`) to its very bottom (End) or top (Home), dragging the\n * caret out of view. The state cannot be repaired after the fact — clearing\n * or re-setting the DOM selection, blur/refocus, and preventDefault on the\n * clicks all fail — but a programmatic caret move never arms it.\n *\n * `Selection.modify(\"move\", direction, \"lineboundary\")` is the exact\n * equivalent of the native key (visual line boundary, bidi-aware via the\n * logical forward/backward directions), so behavior is unchanged for users.\n * Shift+End / Shift+Home extend selections natively and do not trigger the\n * bug, so only the plain keys are bound — a keymap entry without modifiers\n * never matches the shifted keys.\n */\nexport const LineBoundaryKeys = Extension.create({\n name: \"lineBoundaryKeys\",\n\n addKeyboardShortcuts() {\n const moveToLineBoundary =\n (direction: \"forward\" | \"backward\") =>\n ({ editor }: { editor: { view: unknown } }): boolean => {\n const view = editor.view as {\n composing: boolean;\n root: DocumentOrShadowRoot & {\n getSelection?: () => Selection | null;\n };\n dom: HTMLElement;\n };\n // During IME composition End/Home commit the composition; leave\n // that to the browser.\n if (!view || view.composing) return false;\n // `view.root` is the editable's Document or ShadowRoot, so the\n // selection resolves correctly in both mount modes. ShadowRoot's\n // getSelection is Chromium-only; elsewhere fall back to the owner\n // document (Chromium is also the only engine with the bug).\n const selection =\n typeof view.root?.getSelection === \"function\"\n ? view.root.getSelection()\n : (view.dom?.ownerDocument?.getSelection?.() ?? null);\n // `modify` is non-standard; without it, or with a selection that\n // is not ours, native handling is the safer default.\n if (!selection || typeof selection.modify !== \"function\") return false;\n if (!selection.anchorNode || !view.dom.contains(selection.anchorNode)) {\n return false;\n }\n selection.modify(\"move\", direction, \"lineboundary\");\n return true;\n };\n\n return {\n End: moveToLineBoundary(\"forward\"),\n Home: moveToLineBoundary(\"backward\"),\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\nexport interface LineHeightOptions {\n types: string[];\n defaultLineHeight: string;\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n lineHeight: {\n setLineHeight: (lineHeight: string) => ReturnType;\n unsetLineHeight: () => ReturnType;\n };\n }\n}\n\nexport const LineHeight = Extension.create<LineHeightOptions>({\n name: \"lineHeight\",\n\n addOptions() {\n return {\n types: [\"paragraph\"],\n defaultLineHeight: \"1.5\",\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n lineHeight: {\n default: null,\n parseHTML: (element) => element.style.lineHeight || null,\n renderHTML: (attributes) => {\n if (!attributes.lineHeight) {\n return {};\n }\n return {\n style: `line-height: ${attributes.lineHeight}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setLineHeight:\n (lineHeight: string) =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.updateAttributes(type, { lineHeight }),\n );\n },\n unsetLineHeight:\n () =>\n ({ commands }) => {\n return this.options.types.every((type) =>\n commands.resetAttributes(type, \"lineHeight\"),\n );\n },\n };\n },\n});\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n} from \"@templatical/types\";\nimport type { Editor } from \"@tiptap/core\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n value: string;\n keyword: string;\n };\n };\n editor: Editor;\n getPos: () => number;\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { syntax } = useMergeTag();\nconst { t } = useI18n();\n\nconst isValid = computed(() =>\n isLogicMergeTagValue(props.node.attrs.value, syntax),\n);\nconst displayKeyword = computed(() =>\n getLogicMergeTagKeyword(props.node.attrs.value, syntax),\n);\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\nlet handled = false;\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n handled = false;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n if (handled) {\n return;\n }\n handled = true;\n\n const newValue = editValue.value.trim();\n if (!newValue) {\n isEditing.value = false;\n return;\n }\n\n if (newValue !== props.node.attrs.value) {\n props.updateAttributes({\n value: newValue,\n keyword: isLogicMergeTagValue(newValue, syntax)\n ? getLogicMergeTagKeyword(newValue, syntax)\n : \"\",\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n :class=\"\n isValid\n ? 'tpl-logic-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase tpl:select-none'\n : ''\n \"\n :style=\"\n isValid\n ? 'background-color: transparent; border: 1.5px solid color-mix(in srgb, var(--tpl-primary) 50%, transparent); color: var(--tpl-primary);'\n : ''\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-40 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:normal-case tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode: valid merge tag -->\n <span\n v-else-if=\"isValid\"\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayKeyword }}\n </span>\n <!-- Display mode: invalid (plain text) -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ node.attrs.value }}\n </span>\n <button\n v-if=\"isValid\"\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all tpl:hover:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n} from \"@templatical/types\";\nimport type { Editor } from \"@tiptap/core\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n value: string;\n keyword: string;\n };\n };\n editor: Editor;\n getPos: () => number;\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { syntax } = useMergeTag();\nconst { t } = useI18n();\n\nconst isValid = computed(() =>\n isLogicMergeTagValue(props.node.attrs.value, syntax),\n);\nconst displayKeyword = computed(() =>\n getLogicMergeTagKeyword(props.node.attrs.value, syntax),\n);\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\nlet handled = false;\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n handled = false;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n if (handled) {\n return;\n }\n handled = true;\n\n const newValue = editValue.value.trim();\n if (!newValue) {\n isEditing.value = false;\n return;\n }\n\n if (newValue !== props.node.attrs.value) {\n props.updateAttributes({\n value: newValue,\n keyword: isLogicMergeTagValue(newValue, syntax)\n ? getLogicMergeTagKeyword(newValue, syntax)\n : \"\",\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n :class=\"\n isValid\n ? 'tpl-logic-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase tpl:select-none'\n : ''\n \"\n :style=\"\n isValid\n ? 'background-color: transparent; border: 1.5px solid color-mix(in srgb, var(--tpl-primary) 50%, transparent); color: var(--tpl-primary);'\n : ''\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-40 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:normal-case tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode: valid merge tag -->\n <span\n v-else-if=\"isValid\"\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayKeyword }}\n </span>\n <!-- Display mode: invalid (plain text) -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ node.attrs.value }}\n </span>\n <button\n v-if=\"isValid\"\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all tpl:hover:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","import type { Editor } from \"@tiptap/core\";\n\n/**\n * Decides whether MergeTagNode / LogicMergeTagNode should swallow a\n * Backspace/Delete keystroke (returning `true` from a TipTap keymap\n * suppresses the default behavior).\n *\n * Only suppresses in the cursor-adjacent case so the \"first press\n * selects the atom, second press deletes it\" UX works. Range selections\n * (Cmd+A, drag-select, double-click-word) explicitly fall through —\n * default `replaceSelection` then deletes the entire range including\n * any merge-tag atoms inside it.\n *\n * Earlier revisions also returned `true` whenever `nodesBetween($from,\n * $to)` found a merge tag anywhere in the selection range — which\n * silently broke Cmd+A + Backspace for any paragraph containing a\n * merge tag (entire deletion was cancelled, nothing happened). The\n * cursor-adjacent protection is the only piece that should survive.\n */\nexport function isNodeSelected(editor: Editor, nodeTypeName: string): boolean {\n const { $from, $to } = editor.state.selection;\n\n // Range selection: let TipTap's default range-delete run. Even when\n // the range contains atom nodes, ProseMirror's replaceSelection\n // handles atomic deletion correctly.\n if ($from.pos !== $to.pos) return false;\n\n // Cursor-adjacent atom: protect from single-keystroke deletion.\n // (`$from.pos > 0` guards against reading `nodeBefore` at doc start\n // where ProseMirror's index would be undefined for nodeBefore.)\n if ($from.pos > 0 && $from.nodeBefore?.type.name === nodeTypeName) {\n return true;\n }\n if ($from.nodeAfter?.type.name === nodeTypeName) {\n return true;\n }\n\n return false;\n}\n","import type { Component } from \"vue\";\nimport { VueNodeViewRenderer } from \"@tiptap/vue-3\";\n\n/**\n * Typed wrapper for VueNodeViewRenderer that handles the known type mismatch\n * between Vue SFC default exports and TipTap's expected component type.\n */\nexport function renderVueNodeView(component: Component) {\n return VueNodeViewRenderer(\n component as Parameters<typeof VueNodeViewRenderer>[0],\n );\n}\n","import LogicMergeTagNodeView from \"./LogicMergeTagNodeView.vue\";\nimport type { SyntaxPreset } from \"@templatical/types\";\nimport {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n SYNTAX_PRESETS,\n} from \"@templatical/types\";\nimport { InputRule, mergeAttributes, Node, PasteRule } from \"@tiptap/core\";\nimport { isNodeSelected } from \"./isNodeSelected\";\nimport { renderVueNodeView } from \"./renderVueNodeView\";\n\nexport interface LogicMergeTagNodeOptions {\n syntax: SyntaxPreset;\n}\n\nexport const LogicMergeTagNode = Node.create<LogicMergeTagNodeOptions>({\n name: \"logicMergeTagNode\",\n\n group: \"inline\",\n\n inline: true,\n\n atom: true,\n\n addOptions() {\n return {\n syntax: SYNTAX_PRESETS.liquid,\n };\n },\n\n addAttributes() {\n return {\n // Both attributes are state, not markup, same as `MergeTagNode`:\n // `renderHTML()` emits the canonical `data-logic-merge-tag` /\n // `data-keyword` pair and `parseHTML` reads only those. `rendered: false`\n // keeps TipTap from also serializing each attribute under its own name,\n // which would put a write-only duplicate of the same data on every tag.\n value: {\n default: \"\",\n rendered: false,\n parseHTML: (element) =>\n element.getAttribute(\"data-logic-merge-tag\") || \"\",\n },\n keyword: {\n default: \"\",\n rendered: false,\n parseHTML: (element) =>\n element.getAttribute(\"data-keyword\") || element.textContent || \"\",\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span[data-logic-merge-tag]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n if (!isLogicMergeTagValue(node.attrs.value, this.options.syntax)) {\n return [\"span\", {}, node.attrs.value];\n }\n\n const keyword = getLogicMergeTagKeyword(\n node.attrs.value,\n this.options.syntax,\n );\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-logic-merge-tag\": node.attrs.value,\n \"data-keyword\": keyword,\n }),\n keyword,\n ];\n },\n\n addNodeView() {\n return renderVueNodeView(LogicMergeTagNodeView);\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () => isNodeSelected(this.editor, this.name),\n Delete: () => isNodeSelected(this.editor, this.name),\n };\n },\n\n addInputRules() {\n const inputRegex = new RegExp(this.options.syntax.logic.source + \"$\", \"\");\n\n return [\n new InputRule({\n find: inputRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n if (!isLogicMergeTagValue(fullValue, this.options.syntax)) {\n return;\n }\n\n const keyword = getLogicMergeTagKeyword(\n fullValue,\n this.options.syntax,\n );\n\n const node = this.type.create({\n value: fullValue,\n keyword,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n\n addPasteRules() {\n const pasteRegex = new RegExp(this.options.syntax.logic.source, \"g\");\n\n return [\n new PasteRule({\n find: pasteRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n if (!isLogicMergeTagValue(fullValue, this.options.syntax)) {\n return;\n }\n\n const keyword = getLogicMergeTagKeyword(\n fullValue,\n this.options.syntax,\n );\n\n const node = this.type.create({\n value: fullValue,\n keyword,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n});\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n label: string;\n value: string;\n };\n };\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { getMergeTagLabel } = useMergeTag();\nconst { t } = useI18n();\n\nconst displayLabel = computed(() => getMergeTagLabel(props.node.attrs.value));\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n const newValue = editValue.value.trim();\n if (newValue && newValue !== props.node.attrs.value) {\n // Update with new value and derive label from it\n props.updateAttributes({\n value: newValue,\n label: getMergeTagLabel(newValue),\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n class=\"tpl-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium tpl:select-none tpl:text-[var(--tpl-primary)]\"\n style=\"\n background-color: color-mix(in srgb, var(--tpl-primary) 20%, transparent);\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-32 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayLabel }}\n </span>\n <button\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all tpl:hover:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport { NodeViewWrapper } from \"@tiptap/vue-3\";\nimport { computed, nextTick, ref } from \"vue\";\n\nconst props = defineProps<{\n node: {\n attrs: {\n label: string;\n value: string;\n };\n };\n deleteNode: () => void;\n updateAttributes: (attrs: Record<string, unknown>) => void;\n}>();\n\nconst { getMergeTagLabel } = useMergeTag();\nconst { t } = useI18n();\n\nconst displayLabel = computed(() => getMergeTagLabel(props.node.attrs.value));\n\nconst isEditing = ref(false);\nconst editValue = ref(\"\");\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nfunction startEditing(): void {\n editValue.value = props.node.attrs.value;\n isEditing.value = true;\n nextTick(() => {\n inputRef.value?.focus();\n inputRef.value?.select();\n });\n}\n\nfunction finishEditing(): void {\n const newValue = editValue.value.trim();\n if (newValue && newValue !== props.node.attrs.value) {\n // Update with new value and derive label from it\n props.updateAttributes({\n value: newValue,\n label: getMergeTagLabel(newValue),\n });\n }\n isEditing.value = false;\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key === \"Enter\") {\n event.preventDefault();\n finishEditing();\n } else if (event.key === \"Escape\") {\n isEditing.value = false;\n }\n}\n</script>\n\n<template>\n <NodeViewWrapper\n as=\"span\"\n class=\"tpl-merge-tag-node tpl:group tpl:mx-0.5 tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium tpl:select-none tpl:text-[var(--tpl-primary)]\"\n style=\"\n background-color: color-mix(in srgb, var(--tpl-primary) 20%, transparent);\n \"\n contenteditable=\"false\"\n >\n <!-- Edit mode -->\n <input\n v-if=\"isEditing\"\n ref=\"inputRef\"\n v-model=\"editValue\"\n type=\"text\"\n class=\"tpl:w-32 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-0.5 tpl:py-0 tpl:text-[1em] tpl:font-medium tpl:outline-none tpl:text-[var(--tpl-primary)]\"\n @blur=\"finishEditing\"\n @keydown=\"handleKeydown\"\n />\n <!-- Display mode -->\n <span\n v-else\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"t.mergeTag.editValue\"\n class=\"tpl-tooltip tpl:cursor-pointer\"\n :data-tooltip=\"node.attrs.value\"\n @click.stop=\"startEditing\"\n @keydown.enter.stop=\"startEditing\"\n @keydown.space.prevent.stop=\"startEditing\"\n >\n {{ displayLabel }}\n </span>\n <button\n type=\"button\"\n :aria-label=\"t.mergeTag.deleteMergeTag\"\n class=\"tpl-merge-tag-delete tpl:flex tpl:size-5 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:opacity-60 tpl:transition-all tpl:hover:opacity-100 tpl:text-[var(--tpl-primary)]\"\n contenteditable=\"false\"\n @click.stop.prevent=\"deleteNode\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </NodeViewWrapper>\n</template>\n","import MergeTagNodeView from \"./MergeTagNodeView.vue\";\nimport type { MergeTag, SyntaxPreset } from \"@templatical/types\";\nimport { getMergeTagLabel, SYNTAX_PRESETS } from \"@templatical/types\";\nimport { InputRule, mergeAttributes, Node, PasteRule } from \"@tiptap/core\";\nimport { isNodeSelected } from \"./isNodeSelected\";\nimport { renderVueNodeView } from \"./renderVueNodeView\";\n\nexport interface MergeTagNodeOptions {\n mergeTags: MergeTag[];\n syntax: SyntaxPreset;\n}\n\n/**\n * Inserted-node attrs are intentionally limited to `label` + `value`. The\n * `MergeTag` interface also carries optional `group` / `description` for\n * the built-in picker, but those are display-only and must NOT leak into\n * the document JSON — they would bloat templates and pollute serialized\n * state. `Pick<>` makes the constraint explicit at the type level.\n */\nexport type InsertMergeTagAttrs = Pick<MergeTag, \"label\" | \"value\">;\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n mergeTagNode: {\n insertMergeTag: (attrs: InsertMergeTagAttrs) => ReturnType;\n };\n }\n}\n\nexport const MergeTagNode = Node.create<MergeTagNodeOptions>({\n name: \"mergeTagNode\",\n\n group: \"inline\",\n\n inline: true,\n\n atom: true,\n\n addOptions() {\n return {\n mergeTags: [],\n syntax: SYNTAX_PRESETS.liquid,\n };\n },\n\n addAttributes() {\n return {\n // Both attributes are state, not markup: `renderHTML()` below emits the\n // canonical `data-merge-tag` / `data-label` pair and `parseHTML` reads\n // only those. `rendered: false` keeps TipTap from also serializing each\n // attribute under its own name, which would put a write-only duplicate\n // of the same data on every tag — invalid on a `<span>`, and paid again\n // through storage, autosave, snapshots and version history.\n label: {\n default: \"\",\n rendered: false,\n parseHTML: (element) =>\n element.getAttribute(\"data-label\") || element.textContent || \"\",\n },\n value: {\n default: \"\",\n rendered: false,\n parseHTML: (element) => element.getAttribute(\"data-merge-tag\") || \"\",\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span[data-merge-tag]\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const label = getMergeTagLabel(node.attrs.value, this.options.mergeTags);\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-merge-tag\": node.attrs.value,\n \"data-label\": label,\n }),\n label,\n ];\n },\n\n addNodeView() {\n return renderVueNodeView(MergeTagNodeView);\n },\n\n addCommands() {\n return {\n insertMergeTag:\n (attrs: InsertMergeTagAttrs) =>\n ({ commands }) => {\n // Whitelist explicitly — even if a caller smuggles extra keys via\n // a wider type assertion, only label/value reach the node attrs.\n return commands.insertContent({\n type: this.name,\n attrs: { label: attrs.label, value: attrs.value },\n });\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () => isNodeSelected(this.editor, this.name),\n Delete: () => isNodeSelected(this.editor, this.name),\n };\n },\n\n addInputRules() {\n const inputRegex = new RegExp(this.options.syntax.value.source + \"$\", \"\");\n\n return [\n new InputRule({\n find: inputRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n const label = getMergeTagLabel(fullValue, this.options.mergeTags);\n\n const node = this.type.create({\n label,\n value: fullValue,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n\n addPasteRules() {\n const pasteRegex = new RegExp(this.options.syntax.value.source, \"g\");\n\n return [\n new PasteRule({\n find: pasteRegex,\n handler: ({ state, range, match }) => {\n const fullValue = match[0];\n const label = getMergeTagLabel(fullValue, this.options.mergeTags);\n\n const node = this.type.create({\n label,\n value: fullValue,\n });\n\n state.tr.replaceWith(range.from, range.to, node);\n },\n }),\n ];\n },\n});\n"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ //#region src/utils/formatAbsoluteDateTime.ts
2
+ function e(e, t, n) {
3
+ let r = new Date(e);
4
+ if (Number.isNaN(r.getTime())) return "";
5
+ let i = t?.trim().replace(/_/g, "-") || void 0;
6
+ try {
7
+ return r.toLocaleString(i, n);
8
+ } catch {
9
+ return r.toLocaleString(void 0, n);
10
+ }
11
+ }
12
+ //#endregion
13
+ export { e as t };
14
+
15
+ //# sourceMappingURL=formatAbsoluteDateTime-DMmop3C-.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatAbsoluteDateTime-DMmop3C-.js","names":[],"sources":["../../../src/utils/formatAbsoluteDateTime.ts"],"sourcesContent":["/**\n * An absolute date/time label in the **editor's** locale.\n *\n * `toLocaleString()` and `toLocaleDateString(undefined, …)` format in the\n * *runtime's* locale, which is the browser's or the OS's — not the one the\n * consumer passed to `init({ locale })`. So a German editor opened in an\n * English browser rendered \"Mar 4, 2026\" beside fully German chrome, and an\n * English editor in a German browser did the mirror image. The editor's own\n * locale is the only one that agrees with the surrounding labels.\n *\n * Two guards, both reachable from consumer input:\n *\n * - **A malformed tag makes `Intl` throw `RangeError`.** `config.locale` is\n * free-text config, so `\"not a locale\"` would take down the whole component\n * render for what is a cosmetic tooltip. Falls back to the runtime locale —\n * the behaviour before this existed — rather than to a hardcoded language.\n * A well-formed but *unregistered* tag (`\"zz\"`) is not caught: `Intl`\n * resolves its own fallback, and second-guessing it would be worse.\n * - **An unparseable date yields `\"\"`.** Every caller renders this into a\n * `title` attribute, where a literal \"Invalid Date\" is worse than no\n * tooltip.\n */\nexport function formatAbsoluteDateTime(\n iso: string,\n locale: string | undefined,\n options?: Intl.DateTimeFormatOptions,\n): string {\n const parsed = new Date(iso);\n if (Number.isNaN(parsed.getTime())) return \"\";\n\n const tag = locale?.trim().replace(/_/g, \"-\") || undefined;\n\n try {\n return parsed.toLocaleString(tag, options);\n } catch {\n // RangeError from a malformed tag — format as we did before a locale was\n // threaded through at all.\n return parsed.toLocaleString(undefined, options);\n }\n}\n"],"mappings":";AAsBA,SAAgB,EACd,GACA,GACA,GACQ;CACR,IAAM,IAAS,IAAI,KAAK,CAAG;CAC3B,IAAI,OAAO,MAAM,EAAO,QAAQ,CAAC,GAAG,OAAO;CAE3C,IAAM,IAAM,GAAQ,KAAK,CAAC,CAAC,QAAQ,MAAM,GAAG,KAAK,KAAA;CAEjD,IAAI;EACF,OAAO,EAAO,eAAe,GAAK,CAAO;CAC3C,QAAQ;EAGN,OAAO,EAAO,eAAe,KAAA,GAAW,CAAO;CACjD;AACF"}
@@ -59,6 +59,11 @@ var e = {
59
59
  table: "Tableau",
60
60
  countdown: "Compte à rebours"
61
61
  },
62
+ blockDefaults: {
63
+ title: "Saisissez votre titre",
64
+ paragraph: "Saisissez votre texte ici",
65
+ button: "Cliquez ici"
66
+ },
62
67
  sidebar: {
63
68
  content: "Contenu",
64
69
  settings: "Paramètres",
@@ -608,3 +613,5 @@ var e = {
608
613
  };
609
614
  //#endregion
610
615
  export { e as default };
616
+
617
+ //# sourceMappingURL=fr-L8DR73mK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fr-L8DR73mK.js","names":[],"sources":["../../../src/i18n/locales/fr.ts"],"sourcesContent":["import type en from \"./en\";\n\nconst fr: typeof en = {\n footer: {\n poweredBy: \"Propulsé par\",\n openSource: \"Open Source\",\n },\n\n header: {\n save: \"Enregistrer\",\n saving: \"Enregistrement...\",\n saved: \"Enregistré\",\n unsaved: \"Non enregistré\",\n saveFailed: \"Échec de l'enregistrement\",\n saveNoTemplate: \"Chargez ou créez d'abord un modèle\",\n templateName: \"Nom du modèle\",\n rename: \"Renommer le modèle\",\n untitled: \"Sans titre\",\n updatedAt: \"Modifié {time}\",\n createdAt: \"Créé {time}\",\n updatedJustNow: \"Modifié à l'instant\",\n createdJustNow: \"Créé à l'instant\",\n },\n\n // Relative timestamps, shared by every surface that shows one: the header's\n // updated line, saved blocks, comments and version history.\n time: {\n justNow: \"À l'instant\",\n minutesAgo: \"il y a {minutes} min\",\n hoursAgo: \"il y a {hours} h\",\n daysAgo: \"il y a {days} j\",\n },\n\n // Toolbar - Paragraph\n paragraph: {\n paragraphSpacing: \"Espacement des paragraphes\",\n },\n\n history: {\n collabWarning:\n \"Annuler peut affecter les modifications récentes de vos collaborateurs\",\n undo: \"Annuler\",\n redo: \"Rétablir\",\n },\n viewport: {\n label: \"Affichage\",\n desktop: \"Ordinateur\",\n mobile: \"Mobile\",\n },\n darkMode: {\n enable: \"Aperçu en mode sombre\",\n disable: \"Aperçu en mode clair\",\n },\n previewMode: {\n enable: \"Mode aperçu\",\n disable: \"Quitter l'aperçu\",\n },\n blocks: {\n section: \"Section\",\n image: \"Image\",\n title: \"Titre\",\n paragraph: \"Paragraphe\",\n button: \"Bouton\",\n divider: \"Séparateur\",\n video: \"Vidéo\",\n social: \"Réseaux sociaux\",\n spacer: \"Espaceur\",\n html: \"HTML\",\n menu: \"Menu\",\n table: \"Tableau\",\n countdown: \"Compte à rebours\",\n },\n\n // Placeholder text a newly inserted block starts with. Author-facing\n // prompts, meant to be overwritten — so they follow the editor UI locale.\n // Recipient-facing defaults live in `i18n/contentDefaults.ts` and follow\n // the template's own `settings.locale` instead.\n blockDefaults: {\n title: \"Saisissez votre titre\",\n paragraph: \"Saisissez votre texte ici\",\n button: \"Cliquez ici\",\n },\n sidebar: {\n content: \"Contenu\",\n settings: \"Paramètres\",\n noSelection: \"Aucun élément sélectionné\",\n noSelectionHint: \"Sélectionnez un bloc sur le canevas pour le modifier\",\n },\n toolbar: {\n duplicate: \"Dupliquer\",\n delete: \"Supprimer\",\n },\n titleEditor: {\n toolbar: \"Mise en forme du titre\",\n bold: \"Gras (Ctrl+B)\",\n italic: \"Italique (Ctrl+I)\",\n addLink: \"Ajouter un lien\",\n },\n paragraphEditor: {\n toolbar: \"Mise en forme du texte\",\n bold: \"Gras (Ctrl+B)\",\n italic: \"Italique (Ctrl+I)\",\n underline: \"Souligné (Ctrl+U)\",\n strikethrough: \"Barré\",\n subscript: \"Indice\",\n superscript: \"Exposant\",\n addLink: \"Ajouter un lien\",\n bulletList: \"Liste à puces\",\n numberedList: \"Liste numérotée\",\n alignLeft: \"Aligner à gauche\",\n alignCenter: \"Centrer\",\n alignRight: \"Aligner à droite\",\n alignJustify: \"Justifier\",\n clearFormatting: \"Effacer la mise en forme\",\n insertEmoji: \"Insérer un émoji\",\n fontFamily: \"Police\",\n defaultFont: \"Par défaut\",\n fontSize: \"Taille de police\",\n defaultSize: \"Par défaut\",\n textColor: \"Couleur du texte\",\n highlightColor: \"Couleur de surlignage\",\n lineHeight: \"Interligne\",\n letterSpacing: \"Espacement des lettres\",\n emojiItemLabel: \"Insérer l'émoji {emoji}\",\n },\n blockActions: {\n drag: \"Faites glisser pour réorganiser, ou appuyez sur Espace pour déplacer au clavier\",\n dragLifted:\n \"Déplacement de {block}. Utilisez les flèches haut et bas pour repositionner, Espace ou Entrée pour déposer, Échap pour annuler.\",\n duplicate: \"Dupliquer le bloc\",\n delete: \"Supprimer le bloc\",\n hiddenOnViewport: \"Masqué sur {viewport}\",\n saveAsBlock: \"Enregistrer comme bloc\",\n conditionToggle: \"Basculer la condition d'affichage\",\n comments: \"Commentaires ({count})\",\n lifted: \"{block} saisi. Position {position} sur {total}.\",\n moved: \"{block} déplacé en position {position} sur {total}.\",\n dropped: \"{block} déposé en position {position} sur {total}.\",\n cancelled: \"Déplacement annulé. {block} est revenu en position {position}.\",\n },\n section: {\n dropHere: \"Déposez des blocs ici\",\n columns: \"Colonnes\",\n column1: \"1 colonne\",\n column2: \"2 colonnes\",\n column3: \"3 colonnes\",\n ratio12: \"Ratio 1:2\",\n ratio21: \"Ratio 2:1\",\n borderRadius: \"Rayon de bordure\",\n wrapperEnable: \"Ajouter un conteneur\",\n stackOnMobile: \"Empiler sur mobile\",\n },\n linkDialog: {\n editLink: \"Modifier le lien\",\n insertLink: \"Insérer un lien\",\n updateLink: \"Mettre à jour le lien\",\n removeLink: \"Supprimer le lien\",\n cancel: \"Annuler\",\n urlPlaceholder: \"https://example.com\",\n urlLabel: \"URL\",\n colorLabel: \"Couleur du lien\",\n },\n title: {\n level: \"Niveau de titre\",\n heading1: \"Titre 1 (36px)\",\n heading2: \"Titre 2 (28px)\",\n heading3: \"Titre 3 (22px)\",\n heading4: \"Titre 4 (18px)\",\n fontFamily: \"Police\",\n inheritFont: \"Utiliser la police du modèle\",\n color: \"Couleur\",\n align: \"Aligner\",\n alignLeft: \"Gauche\",\n alignCenter: \"Centre\",\n alignRight: \"Droite\",\n },\n emoji: {\n smileys: \"Smileys\",\n gestures: \"Gestes\",\n objects: \"Objets\",\n },\n image: {\n imageUrl: \"URL de l'image\",\n imageUrlPlaceholder: \"https://...\",\n altText: \"Texte alternatif\",\n altTextPlaceholder: \"Description de l'image\",\n width: \"Largeur\",\n fullWidth: \"Pleine largeur\",\n widthCustom: \"Personnalisée\",\n height: \"Hauteur\",\n heightAuto: \"Automatique\",\n heightCustom: \"Personnalisée\",\n borderRadius: \"Rayon de bordure\",\n linkUrl: \"URL du lien\",\n openInNewTab: \"Ouvrir dans un nouvel onglet\",\n placeholderUrl: \"Image de substitution\",\n optional: \"(facultatif)\",\n placeholderUrlPlaceholder: \"https://... (conception uniquement)\",\n placeholderUrlTooltip:\n \"L'URL de l'image utilisant une balise de fusion, vous pouvez fournir ici une vraie image pour prévisualiser la mise en page pendant la conception. Elle n'est pas incluse dans le résultat final.\",\n clickToAdd: \"Cliquez pour ajouter l'URL de l'image\",\n browseMedia: \"Parcourir la médiathèque\",\n dropToUpload: \"Déposez une image pour la téléverser\",\n uploading: \"Téléversement…\",\n decorative: \"Image décorative\",\n decorativeHint:\n \"Masquée pour les lecteurs d'écran. À réserver aux espaceurs et ornements visuels.\",\n },\n video: {\n videoUrl: \"URL de la vidéo\",\n videoUrlPlaceholder: \"https://youtube.com/...\",\n openInNewTab: \"Ouvrir dans un nouvel onglet\",\n customThumbnail: \"Miniature personnalisée\",\n optional: \"(facultatif)\",\n thumbnailPlaceholder: \"Générée automatiquement depuis l'URL de la vidéo\",\n altText: \"Texte alternatif\",\n altTextPlaceholder: \"Description de la vidéo\",\n width: \"Largeur\",\n fullWidth: \"Pleine largeur\",\n height: \"Hauteur\",\n heightAuto: \"Automatique\",\n heightCustom: \"Personnalisée\",\n placeholderUrl: \"Miniature de substitution\",\n placeholderUrlPlaceholder: \"https://... (conception uniquement)\",\n placeholderUrlTooltip:\n \"L'URL de la vidéo utilisant une balise de fusion, vous pouvez fournir ici une vraie miniature pour prévisualiser la mise en page pendant la conception. Elle n'est pas incluse dans le résultat final.\",\n addVideo: \"Ajoutez une URL de vidéo\",\n },\n button: {\n fontFamily: \"Police\",\n inheritFont: \"Utiliser la police du modèle\",\n text: \"Texte\",\n url: \"URL\",\n urlPlaceholder: \"https://...\",\n openInNewTab: \"Ouvrir dans un nouvel onglet\",\n background: \"Fond\",\n textColor: \"Couleur du texte\",\n borderRadius: \"Rayon de bordure\",\n fontSize: \"Taille de police\",\n width: \"Largeur\",\n widthAuto: \"Ajuster au contenu\",\n fullWidth: \"Pleine largeur\",\n widthCustom: \"Personnalisée\",\n },\n divider: {\n style: \"Style\",\n solid: \"Continu\",\n dashed: \"Tirets\",\n dotted: \"Pointillés\",\n color: \"Couleur\",\n thickness: \"Épaisseur\",\n },\n social: {\n icons: \"Icônes\",\n addIcon: \"Ajouter une icône\",\n addIcons: \"Ajoutez des icônes de réseaux sociaux\",\n removeIcon: \"Supprimer\",\n urlPlaceholder: \"https://...\",\n style: \"Style\",\n styleSolid: \"Plein\",\n styleOutlined: \"Contour\",\n styleRounded: \"Arrondi\",\n styleSquare: \"Carré\",\n styleCircle: \"Cercle\",\n size: \"Taille\",\n sizeSmall: \"S\",\n sizeMedium: \"M\",\n sizeLarge: \"L\",\n spacing: \"Espacement\",\n align: \"Alignement\",\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: \"Site web\",\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 menu: {\n items: \"Éléments du menu\",\n addItem: \"Ajouter un élément\",\n removeItem: \"Supprimer\",\n text: \"Texte\",\n urlPlaceholder: \"https://example.com\",\n openInNewTab: \"Ouvrir dans un nouvel onglet\",\n bold: \"Gras\",\n underline: \"Souligné\",\n color: \"Couleur\",\n linkColor: \"Couleur des liens\",\n fontSize: \"Taille de police\",\n fontFamily: \"Police\",\n separator: \"Séparateur\",\n separatorColor: \"Couleur du séparateur\",\n spacing: \"Espacement\",\n textAlign: \"Alignement\",\n addLinks: \"Ajoutez des liens de menu\",\n },\n table: {\n dimensions: \"Dimensions\",\n rows: \"Lignes\",\n columns: \"Colonnes\",\n hasHeaderRow: \"Ligne d'en-tête\",\n headerBackgroundColor: \"Fond de l'en-tête\",\n noHeaderBg: \"Sans fond\",\n borderColor: \"Couleur de bordure\",\n borderWidth: \"Épaisseur de bordure\",\n cellPadding: \"Marge intérieure des cellules\",\n fontFamily: \"Police\",\n fontSize: \"Taille de police\",\n color: \"Couleur du texte\",\n textAlign: \"Alignement\",\n cellPlaceholder: \"Saisissez du texte...\",\n empty: \"Ajoutez un tableau\",\n },\n spacer: {\n height: \"Hauteur\",\n },\n countdown: {\n targetDate: \"Date cible\",\n timezone: \"Fuseau horaire\",\n display: \"Affichage\",\n days: \"Jours\",\n hours: \"Heures\",\n minutes: \"Minutes\",\n seconds: \"Secondes\",\n separator: \"Séparateur\",\n fontFamily: \"Police\",\n inheritFont: \"Par défaut\",\n digitFontSize: \"Taille des chiffres\",\n digitColor: \"Couleur des chiffres\",\n labelColor: \"Couleur des libellés\",\n labelFontSize: \"Taille des libellés\",\n background: \"Fond\",\n labels: \"Libellés\",\n expiry: \"Message d'expiration\",\n expiredMessagePlaceholder: \"Cette offre a expiré\",\n expiredImageUrl: \"URL de l'image d'expiration\",\n hideOnExpiry: \"Masquer à l'expiration\",\n setDate: \"Définissez une date cible dans le panneau des paramètres\",\n hidden: \"Masqué (expiré)\",\n },\n customBlocks: {\n definitionNotFound: \"Type de bloc inconnu — ce bloc n'est pas enregistré\",\n renderError:\n \"Ce bloc n'a pas pu être rendu. Vérifiez les erreurs dans le modèle du bloc.\",\n fields: {\n required: \"Obligatoire\",\n addItem: \"Ajouter un élément\",\n removeItem: \"Supprimer\",\n maxItemsReached: \"Nombre maximal d'éléments atteint\",\n minItemsRequired: \"Minimum {count} éléments requis\",\n },\n toolbar: {\n noDefinition:\n \"Enregistrez ce type de bloc dans la configuration du SDK pour modifier ses propriétés\",\n },\n dataSource: {\n fetchButton: \"Charger le contenu\",\n changeButton: \"Changer\",\n fetching: \"Chargement...\",\n readOnlyTooltip: \"Cette valeur provient de votre source de données\",\n fetchError: \"Échec du chargement du contenu\",\n },\n },\n html: {\n content: \"Contenu HTML\",\n preview: \"Bloc HTML personnalisé\",\n empty: \"Ajoutez du contenu HTML dans le panneau\",\n sanitizationHint:\n \"Le HTML est exporté tel quel, sans assainissement — assurez-vous que le contenu est sûr.\",\n },\n blockSettings: {\n spacing: \"Espacement\",\n padding: \"Marge intérieure\",\n background: \"Fond\",\n color: \"Couleur\",\n display: \"Affichage\",\n showOnDesktop: \"Afficher sur ordinateur\",\n showOnMobile: \"Afficher sur mobile\",\n hiddenOnDevice: \"Masqué sur {device}\",\n displayCondition: \"Condition d'affichage\",\n selectCondition: \"Sélectionner une condition\",\n removeCondition: \"Supprimer la condition\",\n noCondition: \"Toujours visible\",\n conditionApplied: \"Condition appliquée\",\n customCondition: \"Condition personnalisée\",\n customConditionLabel: \"Nom de la condition\",\n customConditionBefore: \"Avant (logique d'ouverture)\",\n customConditionAfter: \"Après (logique de fermeture)\",\n applyCondition: \"Appliquer\",\n cancelCondition: \"Annuler\",\n customBadge: \"Personnalisée\",\n restoreHiddenBlocks: \"Afficher tous les blocs masqués\",\n },\n templateSettings: {\n layout: \"Mise en page\",\n widthPreset: \"Largeur prédéfinie\",\n customWidth: \"Largeur personnalisée\",\n appearance: \"Apparence\",\n backgroundColor: \"Couleur de fond\",\n textColor: \"Couleur du texte\",\n linkColor: \"Couleur des liens\",\n linkUnderline: \"Souligner les liens\",\n fontFamily: \"Police\",\n preheaderText: \"Texte d'aperçu (preheader)\",\n preheaderTextPlaceholder:\n \"Texte d'aperçu affiché après l'objet dans la boîte de réception...\",\n preheaderTextHint:\n \"Ce texte apparaît après l'objet dans les aperçus des clients de messagerie. Les balises de fusion sont prises en charge.\",\n language: \"Langue\",\n contentLocale: \"Langue du contenu\",\n contentLocaleHint:\n \"Code BCP 47 (ex. fr, de, pt-BR). Définit l'attribut lang de l'e-mail rendu pour que les lecteurs d'écran prononcent correctement le contenu.\",\n tips: \"Conseils\",\n tip1: \"600px est la largeur standard des modèles d'e-mail\",\n tip2: \"Utilisez des polices web sûres pour une compatibilité maximale\",\n tip3: \"Les fonds clairs offrent la meilleure lisibilité\",\n },\n spacingControl: {\n lockAll: \"Verrouiller tous les côtés\",\n unlock: \"Déverrouiller les côtés\",\n top: \"Haut\",\n right: \"Droite\",\n bottom: \"Bas\",\n left: \"Gauche\",\n decreaseTop: \"Réduire en haut\",\n increaseTop: \"Augmenter en haut\",\n decreaseLeft: \"Réduire à gauche\",\n increaseLeft: \"Augmenter à gauche\",\n decreaseRight: \"Réduire à droite\",\n increaseRight: \"Augmenter à droite\",\n decreaseBottom: \"Réduire en bas\",\n increaseBottom: \"Augmenter en bas\",\n },\n colorPicker: {\n pickColor: \"Choisir une couleur\",\n hexValue: \"Valeur hexadécimale de la couleur\",\n notSet: \"Non définie\",\n clear: \"Effacer la couleur\",\n presetColors: \"Couleurs prédéfinies\",\n },\n mergeTag: {\n clickToEdit: \"Cliquez pour modifier\",\n remove: \"Supprimer la balise de fusion\",\n insert: \"Insérer une balise de fusion\",\n insertShort: \"Balise de fusion\",\n editValue: \"Modifier la valeur de la balise de fusion\",\n deleteMergeTag: \"Supprimer la balise de fusion\",\n suggestionEmpty: \"Aucune balise de fusion correspondante\",\n picker: {\n title: \"Insérer une balise de fusion\",\n searchPlaceholder: \"Rechercher des balises de fusion\",\n searchAriaLabel: \"Rechercher des balises de fusion\",\n noResults: \"Aucune balise de fusion correspondante\",\n empty: \"Aucune balise de fusion configurée\",\n otherGroup: \"Autres\",\n close: \"Fermer\",\n groupCount: \"{count}\",\n sample: \"Aperçu : {sample}\",\n },\n },\n logicTag: {\n insert: \"Insérer une logique\",\n insertShort: \"Logique\",\n picker: {\n title: \"Insérer une logique\",\n searchPlaceholder: \"Rechercher des balises logiques\",\n searchAriaLabel: \"Rechercher des balises logiques\",\n noResults: \"Aucune balise logique correspondante\",\n empty: \"Aucune balise logique configurée\",\n otherGroup: \"Autres\",\n close: \"Fermer\",\n },\n },\n canvas: {\n noBlocks: \"Aucun bloc pour l'instant\",\n dragHint:\n \"Partez de zéro en faisant glisser des blocs depuis la barre latérale\",\n dropHere: \"Déposez ici\",\n aiHintChat: \"ou laissez\",\n aiHintChatSuffix:\n \"générer un modèle complet pour vous en quelques secondes\",\n aiHintDesign:\n \"Vous avez déjà un design ? Téléversez une capture d'écran, une image ou un PDF et\",\n aiHintDesignSuffix: \"le recréera instantanément\",\n },\n savedBlocks: {\n title: \"Blocs enregistrés\",\n saveAsBlock: \"Enregistrer comme bloc\",\n name: \"Nom\",\n namePlaceholder: \"p. ex. En-tête, Pied de page, CTA...\",\n save: \"Enregistrer le bloc\",\n saving: \"Enregistrement...\",\n cancel: \"Annuler\",\n empty: \"Aucun bloc enregistré pour l'instant\",\n emptyHint:\n \"Enregistrez des blocs depuis vos modèles pour les réutiliser plus tard.\",\n noResults: \"Aucun bloc enregistré ne correspond à votre recherche\",\n search: \"Rechercher des blocs enregistrés...\",\n loading: \"Chargement des blocs enregistrés…\",\n category: \"Catégorie\",\n categoryPlaceholder: \"p. ex. En-têtes, Promos... (facultatif)\",\n allCategories: \"Toutes les catégories\",\n filterByCategory: \"Filtrer par catégorie\",\n insert: \"Insérer\",\n rename: \"Renommer\",\n delete: \"Supprimer\",\n deleteConfirm: \"Supprimer ce bloc enregistré ?\",\n blockCount: \"{count} bloc(s)\",\n browse: \"Parcourir les blocs enregistrés\",\n selectToPreview: \"Sélectionnez un bloc enregistré pour l'afficher\",\n insertAtBeginning: \"Au début\",\n insertAfterBlock: \"Après {block}\",\n insertAtEnd: \"À la fin\",\n insertPosition: \"Position d'insertion\",\n close: \"Fermer\",\n pickToolbar: \"Sélection de blocs à enregistrer\",\n pickCount: \"{count} bloc(s) sélectionné(s)\",\n pickHint: \"Cliquez sur les blocs pour les ajouter ou les retirer\",\n savingCount: \"Enregistrement de {count} bloc(s) :\",\n reorderHint:\n \"Glissez pour réordonner — les blocs sont enregistrés dans cet ordre\",\n reorderHandle: \"Réordonner {block}, position {position} sur {total}\",\n reorderAnnouncement: \"{block} déplacé en position {position} sur {total}\",\n expand: \"Développer\",\n collapse: \"Réduire\",\n expandPreview: \"Développer l'aperçu de {block}\",\n collapsePreview: \"Réduire l'aperçu de {block}\",\n },\n comments: {\n button: \"Commentaires\",\n title: \"Commentaires\",\n placeholder: \"Écrire un commentaire...\",\n replyPlaceholder: \"Écrire une réponse...\",\n reply: \"Répondre\",\n resolve: \"Résoudre\",\n unresolve: \"Réouvrir\",\n delete: \"Supprimer\",\n edit: \"Modifier\",\n cancel: \"Annuler\",\n save: \"Enregistrer\",\n noComments: \"Aucun commentaire\",\n noCommentsHint:\n \"Démarrez une conversation en ajoutant un commentaire au modèle ou à un bloc précis.\",\n deleteConfirm: \"Supprimer ce commentaire ?\",\n filterAll: \"Tous\",\n filterUnresolved: \"Non résolus\",\n filterBlock: \"Ce bloc\",\n jumpToBlock: \"Bloc\",\n ownedByYou: \"Vous\",\n edited: \"modifié\",\n resolvedBy: \"Résolu par {name}\",\n replyOne: \"{count} réponse\",\n replyMany: \"{count} réponses\",\n missingBlock: \"Bloc introuvable\",\n saveTemplateFirst: \"Enregistrez le modèle avant de commenter ce bloc.\",\n },\n versionHistory: {\n tooltip: \"Historique des versions\",\n dropdownTitle: \"Historique des versions\",\n empty: \"Aucune version pour l’instant\",\n auto: \"auto\",\n olderVersion: \"Version précédente\",\n newerVersion: \"Version plus récente\",\n },\n versionPreview: {\n message: \"Vous consultez une version antérieure de ce modèle.\",\n cancel: \"Annuler\",\n restore: \"Restaurer cette version\",\n restoreConfirm: {\n title: \"Restaurer cette version ?\",\n unsavedWithSave:\n \"Vous avez des modifications non enregistrées. Enregistrez-les d’abord et elles resteront dans l’historique ; restaurez sans enregistrer et elles seront perdues.\",\n unsavedNoSave:\n \"Vous avez des modifications non enregistrées et aucun endroit où les enregistrer. Restaurer cette version les fera disparaître.\",\n saveAndRestore: \"Enregistrer, puis restaurer\",\n restoreAnyway: \"Restaurer quand même\",\n cancel: \"Annuler\",\n },\n },\n previewResolution: {\n resolving: \"Résolution de l’aperçu…\",\n failed:\n \"L’aperçu n’a pas pu être résolu — le modèle non résolu est affiché.\",\n hint: \"L’aperçu utilise des données résolues par votre backend.\",\n },\n mergeTagPreview: {\n label: \"Affichage des balises de fusion\",\n sample: \"Exemple\",\n labelView: \"Libellé\",\n },\n testEmail: {\n title: \"Envoyer un e-mail de test\",\n recipientLabel: \"Destinataire\",\n recipientPlaceholder: \"vous@exemple.fr\",\n invalidAddress: \"Saisissez une adresse e-mail valide.\",\n preview: \"Aperçu\",\n previewHint:\n \"Les balises de fusion sont affichées non résolues — votre backend les remplace.\",\n previewHintSample:\n \"Les balises de fusion affichent des valeurs d’exemple — votre backend insère les données réelles.\",\n recipientNotAllowed:\n \"Cette adresse ne figure pas dans la liste des destinataires autorisés.\",\n send: \"Envoyer\",\n sending: \"Envoi en cours...\",\n cancel: \"Annuler\",\n success: \"E-mail de test envoyé avec succès\",\n button: \"Test\",\n },\n sidebarNav: {\n browseSavedBlocks: \"Parcourir les blocs enregistrés\",\n palette: \"Palette de blocs\",\n insertBlock: \"Insérer un bloc {block}\",\n },\n landmarks: {\n canvas: \"Canevas de l'e-mail\",\n blockToolbar: \"Propriétés du bloc\",\n rightSidebar: \"Propriétés du bloc et paramètres du modèle\",\n reorderAnnouncements: \"Annonces de réorganisation des blocs\",\n },\n errors: {\n editorLoading: \"Chargement de l'éditeur...\",\n editorLoadFailed: \"Échec du chargement de l'éditeur.\",\n retry: \"Réessayer\",\n },\n issues: {\n panelTitle: \"Problèmes\",\n panelTabLabel: \"Problèmes\",\n groupErrors: \"Erreurs\",\n groupWarnings: \"Avertissements\",\n groupInfo: \"Infos\",\n jump: \"Aller au bloc\",\n fix: \"Corriger\",\n emptyState: \"Aucun problème — tout va bien.\",\n badgeError: \"Contient des erreurs\",\n badgeWarning: \"Contient des avertissements\",\n issueCountTooltip: \"{count} problème(s)\",\n },\n smallScreen: {\n title: \"Écran plus grand requis\",\n message:\n \"L'éditeur a besoin de plus d'espace que cet écran n'en offre. Ouvrez-le sur une tablette ou un ordinateur pour commencer à modifier.\",\n },\n};\n\nexport default fr;\n"],"mappings":"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"}