@templatical/editor 0.24.0 → 0.25.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 (231) hide show
  1. package/dist/{AiChatSidebar-Nq-jrGaf.js → AiChatSidebar-CIkS8DsO.js} +15 -15
  2. package/dist/{AiFeatureMenu-tg_zMKMK.js → AiFeatureMenu-Cji1LBJJ.js} +7 -7
  3. package/dist/{BlockIssueBadge-Bd94kIiw.js → BlockIssueBadge-BQiT0FML.js} +5 -5
  4. package/dist/{BlockPreviewCanvas-B34aMhHe.js → BlockPreviewCanvas-DAnwZofk.js} +11 -7
  5. package/dist/{CloudEditor-DjN_9Yso.js → CloudEditor-CXaft6Ej.js} +73 -71
  6. package/dist/{CollaboratorBar-Bhazzcg-.js → CollaboratorBar-BR-rL2wG.js} +4 -4
  7. package/dist/{ColorPicker-DXGrcJxJ.js → ColorPicker-B4ArSUhy.js} +7 -9
  8. package/dist/{CommentsSidebar-ku1kt10u.js → CommentsSidebar-Bm5GLDts.js} +16 -16
  9. package/dist/{CountdownBlock-CN9Lc23W.js → CountdownBlock-CIVAQDVu.js} +3 -3
  10. package/dist/{CountdownToolbar-VEsIyKV6.js → CountdownToolbar-DBmb3tlb.js} +4 -4
  11. package/dist/DesignReferenceSidebar-CnyJ8L-j.js +264 -0
  12. package/dist/{IssuesPanel-CEfzOpS_.js → IssuesPanel-D3XgmYCt.js} +8 -8
  13. package/dist/{LoadingTrack-KIcREPlS.js → LoadingTrack-XK_eeUdq.js} +1 -1
  14. package/dist/{MergeTagModeToggle-C3V2xGAg.js → MergeTagModeToggle-BK0fI3P2.js} +6 -6
  15. package/dist/{MergeTagSuggestion-Dn8ww9nV.js → MergeTagSuggestion-D0OHRv7L.js} +8 -12
  16. package/dist/{NumberWithSuffix-BGocZkj9.js → NumberWithSuffix-Cjj9UNIp.js} +2 -2
  17. package/dist/{ParagraphEditor-D-fz0kUb.js → ParagraphEditor-jGnbJEA2.js} +45 -45
  18. package/dist/{RichTextEditorContent-DydrqFts.js → RichTextEditorContent-DaaKdzjb.js} +8 -8
  19. package/dist/{SaveBlockDialog-BDDFbAWF.js → SaveBlockDialog-B3ngEldp.js} +12 -12
  20. package/dist/{SavedBlocksBrowserModal-Djik_fJh.js → SavedBlocksBrowserModal-DawN3XaB.js} +11 -11
  21. package/dist/{SavedBlocksPanels-CxemyPxL.js → SavedBlocksPanels-eDC9Y46N.js} +2 -2
  22. package/dist/{SavedBlocksPickBar-Dlhipmob.js → SavedBlocksPickBar-CQbbXmzj.js} +4 -4
  23. package/dist/{SnapshotHistory-DPbM4ons.js → SnapshotHistory-COxKtHM-.js} +10 -10
  24. package/dist/{TemplateScoringPanel-BFYgweDX.js → TemplateScoringPanel-bUuqOO1z.js} +16 -16
  25. package/dist/{TestEmailModal-IZfwgya-.js → TestEmailModal-CytkbZVQ.js} +89 -58
  26. package/dist/{TestEmailPanel-QEEx_PkN.js → TestEmailPanel-CHUY7VZn.js} +2 -2
  27. package/dist/{TitleEditor-BB4YlIBF.js → TitleEditor-aMR1bOyY.js} +13 -13
  28. package/dist/TplModal-fmYNYdyp.js +49 -0
  29. package/dist/{blockTypeIcons-Wzd7W_2x.js → blockTypeIcons-C6b9rg88.js} +26 -26
  30. package/dist/bundle-stats.json +6 -6
  31. package/dist/{ca-CO4nq6TX.js → ca-8Dvbwo50.js} +5 -0
  32. package/dist/cdn/chunks/{AiChatSidebar-CN-0DIuA.js → AiChatSidebar-bkBKpNgE.js} +9 -9
  33. package/dist/cdn/chunks/{AiChatSidebar-CN-0DIuA.js.map → AiChatSidebar-bkBKpNgE.js.map} +1 -1
  34. package/dist/cdn/chunks/{AiFeatureMenu-B5pV6Iux.js → AiFeatureMenu-CI4SYTq2.js} +6 -6
  35. package/dist/cdn/chunks/{AiFeatureMenu-B5pV6Iux.js.map → AiFeatureMenu-CI4SYTq2.js.map} +1 -1
  36. package/dist/cdn/chunks/{BlockIssueBadge-aanOjeyi.js → BlockIssueBadge-CRnx8Dv9.js} +5 -5
  37. package/dist/cdn/chunks/{BlockIssueBadge-aanOjeyi.js.map → BlockIssueBadge-CRnx8Dv9.js.map} +1 -1
  38. package/dist/cdn/chunks/{BlockPreviewCanvas-Dc4F4HzY.js → BlockPreviewCanvas-CXCWhqbp.js} +13 -9
  39. package/dist/cdn/chunks/BlockPreviewCanvas-CXCWhqbp.js.map +1 -0
  40. package/dist/cdn/chunks/{CloudEditor-CeKaWWO5.js → CloudEditor-D-t7RyDh.js} +67 -65
  41. package/dist/cdn/chunks/CloudEditor-D-t7RyDh.js.map +1 -0
  42. package/dist/cdn/chunks/{CollaboratorBar-CEdKr0A2.js → CollaboratorBar-DcXYo47v.js} +5 -5
  43. package/dist/cdn/chunks/{CollaboratorBar-CEdKr0A2.js.map → CollaboratorBar-DcXYo47v.js.map} +1 -1
  44. package/dist/cdn/chunks/{ColorPicker-BckwEfcN.js → ColorPicker-_1O7YU2z.js} +8 -10
  45. package/dist/cdn/chunks/{ColorPicker-BckwEfcN.js.map → ColorPicker-_1O7YU2z.js.map} +1 -1
  46. package/dist/cdn/chunks/{CommentsSidebar-6PfpJKh-.js → CommentsSidebar-BEgLBYX-.js} +7 -7
  47. package/dist/cdn/chunks/{CommentsSidebar-6PfpJKh-.js.map → CommentsSidebar-BEgLBYX-.js.map} +1 -1
  48. package/dist/cdn/chunks/{CountdownBlock-CoBmvQKv.js → CountdownBlock-CPnQA44g.js} +4 -4
  49. package/dist/cdn/chunks/{CountdownBlock-CoBmvQKv.js.map → CountdownBlock-CPnQA44g.js.map} +1 -1
  50. package/dist/cdn/chunks/{CountdownToolbar-CdV8RTQu.js → CountdownToolbar-Cdo-30U4.js} +5 -5
  51. package/dist/cdn/chunks/{CountdownToolbar-CdV8RTQu.js.map → CountdownToolbar-Cdo-30U4.js.map} +1 -1
  52. package/dist/cdn/chunks/DesignReferenceSidebar-DPqBr-ut.js +223 -0
  53. package/dist/cdn/chunks/{DesignReferenceSidebar-BjlaP69l.js.map → DesignReferenceSidebar-DPqBr-ut.js.map} +1 -1
  54. package/dist/cdn/chunks/{IssuesPanel-CkkEnhxZ.js → IssuesPanel-DoQWb23r.js} +5 -5
  55. package/dist/cdn/chunks/{IssuesPanel-CkkEnhxZ.js.map → IssuesPanel-DoQWb23r.js.map} +1 -1
  56. package/dist/cdn/chunks/{LoadingTrack-D-CW2tUa.js → LoadingTrack-G2tuXqCJ.js} +2 -2
  57. package/dist/cdn/chunks/{LoadingTrack-D-CW2tUa.js.map → LoadingTrack-G2tuXqCJ.js.map} +1 -1
  58. package/dist/cdn/chunks/{MergeTagModeToggle-DmtR300G.js → MergeTagModeToggle-CWuVC3MU.js} +6 -6
  59. package/dist/cdn/chunks/{MergeTagModeToggle-DmtR300G.js.map → MergeTagModeToggle-CWuVC3MU.js.map} +1 -1
  60. package/dist/cdn/chunks/{MergeTagSuggestion-Cvlkw_PM.js → MergeTagSuggestion-Ces5Ua78.js} +3 -3
  61. package/dist/cdn/chunks/{MergeTagSuggestion-Cvlkw_PM.js.map → MergeTagSuggestion-Ces5Ua78.js.map} +1 -1
  62. package/dist/cdn/chunks/{NumberWithSuffix-BOcMN26z.js → NumberWithSuffix-DQ4sgvt5.js} +3 -3
  63. package/dist/cdn/chunks/{NumberWithSuffix-BOcMN26z.js.map → NumberWithSuffix-DQ4sgvt5.js.map} +1 -1
  64. package/dist/cdn/chunks/{ParagraphEditor-CX1yks4N.js → ParagraphEditor-Uv5LPF3W.js} +131 -131
  65. package/dist/cdn/chunks/{ParagraphEditor-CX1yks4N.js.map → ParagraphEditor-Uv5LPF3W.js.map} +1 -1
  66. package/dist/cdn/chunks/{RichTextEditorContent-z9s7qxs3.js → RichTextEditorContent-Bt3s09qY.js} +7 -7
  67. package/dist/cdn/chunks/{RichTextEditorContent-z9s7qxs3.js.map → RichTextEditorContent-Bt3s09qY.js.map} +1 -1
  68. package/dist/cdn/chunks/{SaveBlockDialog-D2CtW4lC.js → SaveBlockDialog-BAew6EFd.js} +10 -10
  69. package/dist/cdn/chunks/{SaveBlockDialog-D2CtW4lC.js.map → SaveBlockDialog-BAew6EFd.js.map} +1 -1
  70. package/dist/cdn/chunks/{SavedBlocksBrowserModal-DdUKJzzF.js → SavedBlocksBrowserModal-Dn4IJDJW.js} +9 -9
  71. package/dist/cdn/chunks/{SavedBlocksBrowserModal-DdUKJzzF.js.map → SavedBlocksBrowserModal-Dn4IJDJW.js.map} +1 -1
  72. package/dist/cdn/chunks/{SavedBlocksPanels-1kVbqdpc.js → SavedBlocksPanels-B62U5DYW.js} +3 -3
  73. package/dist/cdn/chunks/{SavedBlocksPanels-1kVbqdpc.js.map → SavedBlocksPanels-B62U5DYW.js.map} +1 -1
  74. package/dist/cdn/chunks/{SavedBlocksPickBar--noDJIyN.js → SavedBlocksPickBar-CyRKZg2T.js} +5 -5
  75. package/dist/cdn/chunks/{SavedBlocksPickBar--noDJIyN.js.map → SavedBlocksPickBar-CyRKZg2T.js.map} +1 -1
  76. package/dist/cdn/chunks/{SnapshotHistory-DFuNJRc9.js → SnapshotHistory-QQt0DKey.js} +7 -7
  77. package/dist/cdn/chunks/{SnapshotHistory-DFuNJRc9.js.map → SnapshotHistory-QQt0DKey.js.map} +1 -1
  78. package/dist/cdn/chunks/{TemplateScoringPanel-DG1dAjQk.js → TemplateScoringPanel-BwyCMcit.js} +67 -67
  79. package/dist/cdn/chunks/{TemplateScoringPanel-DG1dAjQk.js.map → TemplateScoringPanel-BwyCMcit.js.map} +1 -1
  80. package/dist/cdn/chunks/{TestEmailModal-CiPfOn2v.js → TestEmailModal-B5UQkDJp.js} +89 -58
  81. package/dist/cdn/chunks/TestEmailModal-B5UQkDJp.js.map +1 -0
  82. package/dist/cdn/chunks/{TestEmailPanel-saOfnpjz.js → TestEmailPanel-CvuBq4RA.js} +3 -3
  83. package/dist/cdn/chunks/{TestEmailPanel-saOfnpjz.js.map → TestEmailPanel-CvuBq4RA.js.map} +1 -1
  84. package/dist/cdn/chunks/{TitleEditor-08KM_VzZ.js → TitleEditor-B9W954u9.js} +13 -13
  85. package/dist/cdn/chunks/{TitleEditor-08KM_VzZ.js.map → TitleEditor-B9W954u9.js.map} +1 -1
  86. package/dist/cdn/chunks/TplModal-B8UsvWc8.js +50 -0
  87. package/dist/cdn/chunks/TplModal-B8UsvWc8.js.map +1 -0
  88. package/dist/cdn/chunks/{blockTypeIcons-DvohkXqi.js → blockTypeIcons-B8s3_ahs.js} +2 -2
  89. package/dist/cdn/chunks/{blockTypeIcons-DvohkXqi.js.map → blockTypeIcons-B8s3_ahs.js.map} +1 -1
  90. package/dist/cdn/chunks/{ca-CO4nq6TX.js → ca-8Dvbwo50.js} +6 -1
  91. package/dist/cdn/chunks/{ca-CO4nq6TX.js.map → ca-8Dvbwo50.js.map} +1 -1
  92. package/dist/cdn/chunks/{cloud-C2I0P9qj.js → cloud-DOaGUdR0.js} +13 -17
  93. package/dist/cdn/chunks/{cloud-C2I0P9qj.js.map → cloud-DOaGUdR0.js.map} +1 -1
  94. package/dist/{de-CUeaFJph.js → cdn/chunks/de-CieSMCUp.js} +7 -0
  95. package/dist/cdn/chunks/{de-CUeaFJph.js.map → de-CieSMCUp.js.map} +1 -1
  96. package/dist/cdn/chunks/{dist-CxTt8FRE.js → dist-B8AX9np4.js} +16 -12
  97. package/dist/cdn/chunks/dist-B8AX9np4.js.map +1 -0
  98. package/dist/cdn/chunks/{dist-CiBEt0VR.js → dist-lZgXNk4G.js} +36 -20
  99. package/dist/cdn/chunks/dist-lZgXNk4G.js.map +1 -0
  100. package/dist/cdn/chunks/{draggable-D840DIZB.js → draggable-JcMTNF3U.js} +14 -15
  101. package/dist/cdn/chunks/{draggable-D840DIZB.js.map → draggable-JcMTNF3U.js.map} +1 -1
  102. package/dist/{en-zCYIPAL5.js → cdn/chunks/en-D0t_2Fq_.js} +7 -0
  103. package/dist/cdn/chunks/{en-zCYIPAL5.js.map → en-D0t_2Fq_.js.map} +1 -1
  104. package/dist/cdn/chunks/{es-BSiH7YkP.js → es-DwDoNuLM.js} +6 -1
  105. package/dist/cdn/chunks/{es-BSiH7YkP.js.map → es-DwDoNuLM.js.map} +1 -1
  106. package/dist/cdn/chunks/{extensions-DBWF_lxx.js → extensions-5jgtarD-.js} +30 -26
  107. package/dist/cdn/chunks/{extensions-DBWF_lxx.js.map → extensions-5jgtarD-.js.map} +1 -1
  108. package/dist/{fr-DTVJ3det.js → cdn/chunks/fr-CSEEzv1_.js} +7 -0
  109. package/dist/cdn/chunks/{fr-DTVJ3det.js.map → fr-CSEEzv1_.js.map} +1 -1
  110. package/dist/cdn/chunks/{htmlparser-CZa2V5cF.js → htmlparser-CPhs2cYE.js} +3 -5
  111. package/dist/cdn/chunks/{htmlparser-CZa2V5cF.js.map → htmlparser-CPhs2cYE.js.map} +1 -1
  112. package/dist/cdn/chunks/{icons-Cqxvwgz7.js → icons-Cp4ZIJw-.js} +31 -31
  113. package/dist/cdn/chunks/{icons-Cqxvwgz7.js.map → icons-Cp4ZIJw-.js.map} +1 -1
  114. package/dist/cdn/chunks/keys-BxPCfHBH.js +12 -0
  115. package/dist/cdn/chunks/keys-BxPCfHBH.js.map +1 -0
  116. package/dist/cdn/chunks/{liquid.browser-BJOEu6Cg.js → liquid.browser-CZaQe87t.js} +756 -718
  117. package/dist/cdn/chunks/liquid.browser-CZaQe87t.js.map +1 -0
  118. package/dist/cdn/chunks/{nl-BqSquFS3.js → nl-xyk1T2mA.js} +6 -1
  119. package/dist/cdn/chunks/{nl-BqSquFS3.js.map → nl-xyk1T2mA.js.map} +1 -1
  120. package/dist/{pt-BR-CMljK37h.js → cdn/chunks/pt-BR-yr6uOJgn.js} +7 -0
  121. package/dist/cdn/chunks/{pt-BR-CMljK37h.js.map → pt-BR-yr6uOJgn.js.map} +1 -1
  122. package/dist/cdn/chunks/{pusher-R0v5p99W.js → pusher-kUlkqMvR.js} +21 -28
  123. package/dist/cdn/chunks/{pusher-R0v5p99W.js.map → pusher-kUlkqMvR.js.map} +1 -1
  124. package/dist/cdn/chunks/{rolldown-runtime-Dqa2HsxW.js → rolldown-runtime-B0aSnxlc.js} +2 -2
  125. package/dist/cdn/chunks/{src-YVsPFLNJ.js → src-B8W42vT-.js} +153 -153
  126. package/dist/cdn/chunks/{src-YVsPFLNJ.js.map → src-B8W42vT-.js.map} +1 -1
  127. package/dist/cdn/chunks/{src-C45kfA2t.js → src-C417zeUg.js} +22 -26
  128. package/dist/cdn/chunks/{src-C45kfA2t.js.map → src-C417zeUg.js.map} +1 -1
  129. package/dist/cdn/chunks/{src-BCJna-6p.js → src-CZjSXPYq.js} +9 -4
  130. package/dist/cdn/chunks/src-CZjSXPYq.js.map +1 -0
  131. package/dist/cdn/chunks/{src-XQmI_Xs1.js → src-Dpj0x27M.js} +523 -787
  132. package/dist/cdn/chunks/{src-XQmI_Xs1.js.map → src-Dpj0x27M.js.map} +1 -1
  133. package/dist/cdn/chunks/{styles-BohMfIBd.js → styles-DANwMzW2.js} +770 -751
  134. package/dist/cdn/chunks/styles-DANwMzW2.js.map +1 -0
  135. package/dist/cdn/chunks/timeouts-SsLMC4a3.js +6 -0
  136. package/dist/cdn/chunks/{timeouts-Bmi_yePw.js.map → timeouts-SsLMC4a3.js.map} +1 -1
  137. package/dist/cdn/chunks/{tiptap-DRKu__AX.js → tiptap-rsib432n.js} +132 -119
  138. package/dist/cdn/chunks/tiptap-rsib432n.js.map +1 -0
  139. package/dist/cdn/chunks/{useAliveFlag-aanU8uqB.js → useAliveFlag-CseYNikC.js} +2 -2
  140. package/dist/cdn/chunks/{useAliveFlag-aanU8uqB.js.map → useAliveFlag-CseYNikC.js.map} +1 -1
  141. package/dist/cdn/chunks/{useCloudI18n-Bem8DUjH.js → useCloudI18n-CjVzv11v.js} +3 -3
  142. package/dist/cdn/chunks/{useCloudI18n-Bem8DUjH.js.map → useCloudI18n-CjVzv11v.js.map} +1 -1
  143. package/dist/cdn/chunks/{useEditorCore-B_vwuKdI.js → useEditorCore-DfW-thCr.js} +484 -411
  144. package/dist/cdn/chunks/useEditorCore-DfW-thCr.js.map +1 -0
  145. package/dist/cdn/chunks/{useI18n-graz19nI.js → useI18n-DniEFeIl.js} +3 -3
  146. package/dist/cdn/chunks/{useI18n-graz19nI.js.map → useI18n-DniEFeIl.js.map} +1 -1
  147. package/dist/cdn/chunks/{useMergeTag-rTzAFMlr.js → useMergeTag-Bk9_f5cc.js} +7 -7
  148. package/dist/cdn/chunks/{useMergeTag-rTzAFMlr.js.map → useMergeTag-Bk9_f5cc.js.map} +1 -1
  149. package/dist/cdn/chunks/{usePopoverPosition-BaFxLP3w.js → usePopoverPosition-C4xFJCJ2.js} +3 -3
  150. package/dist/cdn/chunks/{usePopoverPosition-BaFxLP3w.js.map → usePopoverPosition-C4xFJCJ2.js.map} +1 -1
  151. package/dist/cdn/editor.css +1 -1
  152. package/dist/cdn/editor.js +24 -22
  153. package/dist/cdn/editor.js.map +1 -1
  154. package/dist/{check-BpQDKiPz.js → check-CIhIDh4h.js} +1 -1
  155. package/dist/{chevron-down-j8GrdTyz.js → chevron-down-CZ0m6G3s.js} +1 -1
  156. package/dist/{chevron-up-BACyVhyC.js → chevron-up-BH_tJLeb.js} +1 -1
  157. package/dist/{circle-alert-CgtE46ND.js → circle-alert-DkEXnGPV.js} +1 -1
  158. package/dist/{clock-BzKLLW5L.js → clock-BDIJZUET.js} +1 -1
  159. package/dist/{cloud-DsUct4Zq.js → cloud-BZn3jqoL.js} +10 -14
  160. package/dist/{createLucideIcon-JWHwTI6N.js → createLucideIcon-AEltGIse.js} +3 -3
  161. package/dist/{cdn/chunks/de-CUeaFJph.js → de-CieSMCUp.js} +5 -2
  162. package/dist/{dist-BAkGuPYm.js → dist-B6Px6GPj.js} +1 -1
  163. package/dist/{dist-9uhI32Q4.js → dist-BxbTVeY0.js} +1 -1
  164. package/dist/{dist-DWu9QWFl.js → dist-CIqhVQ1O.js} +5 -5
  165. package/dist/{dist-DPHqs0Yh.js → dist-CQ0fVBQ3.js} +8 -3
  166. package/dist/{dist-CkCVlKj_.js → dist-CRH880TV.js} +1 -1
  167. package/dist/{dist-ByJVlKWy.js → dist-CcQFPJMF.js} +116 -100
  168. package/dist/{dist-JXOq1hib.js → dist-CkPvZCld.js} +1 -1
  169. package/dist/{dist-IGetXrbO.js → dist-DSIgxp0v.js} +1 -1
  170. package/dist/{dist-DYv_Pttj.js → dist-DT1XnEnj.js} +33 -17
  171. package/dist/{dist-C_kAE1sC.js → dist-DX4x6mQ1.js} +3 -3
  172. package/dist/{dist-DFO896yT.js → dist-Dx71pluS.js} +16 -11
  173. package/dist/{dist-CQiAZlTt.js → dist-DyCHUyRR.js} +1 -1
  174. package/dist/{dist-BIYm-U9x.js → dist-iCEDH3cC.js} +1 -1
  175. package/dist/{dist-C5tigvDF.js → dist-nR6mxyqI.js} +1 -1
  176. package/dist/{cdn/chunks/en-zCYIPAL5.js → en-D0t_2Fq_.js} +5 -2
  177. package/dist/{es-BSiH7YkP.js → es-DwDoNuLM.js} +5 -0
  178. package/dist/{extensions-C0DXnYdA.js → extensions-BjvyU9Ea.js} +16 -12
  179. package/dist/{cdn/chunks/fr-DTVJ3det.js → fr-CSEEzv1_.js} +5 -2
  180. package/dist/{image-up-CQdtq8ge.js → image-up-8ktdYdaZ.js} +1 -1
  181. package/dist/index.d.ts +26 -0
  182. package/dist/{info-BUJBXoE6.js → info-CvrCgTLH.js} +1 -1
  183. package/dist/keys-BFPiNAIn.js +10 -0
  184. package/dist/{liquid.browser-DZLtv26k.js → liquid.browser-BECWFL5Z.js} +755 -717
  185. package/dist/{list-checks-BGHaCSD5.js → list-checks-yzGT93ZL.js} +1 -1
  186. package/dist/{loader-circle-C-Z6kgI6.js → loader-circle-B6euendB.js} +1 -1
  187. package/dist/{message-circle-CEm5qckV.js → message-circle-BMldLVcA.js} +1 -1
  188. package/dist/{nl-BqSquFS3.js → nl-xyk1T2mA.js} +5 -0
  189. package/dist/{pencil-DdwmkKLb.js → pencil-CkKkSd6N.js} +1 -1
  190. package/dist/{cdn/chunks/pt-BR-CMljK37h.js → pt-BR-yr6uOJgn.js} +5 -2
  191. package/dist/{refresh-cw-maKlg0dl.js → refresh-cw-fBPgB97G.js} +1 -1
  192. package/dist/{runtime-dom.esm-bundler-GdMI8WqG.js → runtime-dom.esm-bundler-CBbDt7sw.js} +2 -2
  193. package/dist/{scan-line-BFgesTOY.js → scan-line-CRoEOUiK.js} +1 -1
  194. package/dist/{send-B70aQDrA.js → send-B9Tt2qBi.js} +1 -1
  195. package/dist/{shield-check-B7x5OKt5.js → shield-check-QfZkYeIo.js} +1 -1
  196. package/dist/{sparkles-DVlm1Ipp.js → sparkles-8UeMmZb8.js} +1 -1
  197. package/dist/style.css +1 -1
  198. package/dist/{styles-BTTD0Je4.js → styles-C9GM-bBC.js} +913 -894
  199. package/dist/templatical-editor.js +96 -94
  200. package/dist/{text-align-start-Vay3Kvo2.js → text-align-start-Dn8uIheW.js} +1 -1
  201. package/dist/{trash-2-DE8CmxAG.js → trash-2-DDyvqj0E.js} +1 -1
  202. package/dist/{triangle-alert-Djg6IG8N.js → triangle-alert-B3PydLzl.js} +1 -1
  203. package/dist/{upload-BwwE0U6G.js → upload-hE8ItfyG.js} +2 -2
  204. package/dist/{useAliveFlag-C43EhZFY.js → useAliveFlag-AfoTE_AY.js} +1 -1
  205. package/dist/{useCloudI18n-DGr3b2SX.js → useCloudI18n-B2lItQ6O.js} +2 -2
  206. package/dist/{useEditorCore-DOrGex_t.js → useEditorCore-Ck_hBiGA.js} +986 -915
  207. package/dist/{useI18n-BhAejA-x.js → useI18n-C1KcdX_K.js} +2 -2
  208. package/dist/{useMergeTag-Ce95YIOO.js → useMergeTag-DHCwRMfH.js} +4 -4
  209. package/dist/{usePopoverPosition-vjKJaqJf.js → usePopoverPosition-ClnEh_Cp.js} +13 -13
  210. package/dist/{vue.runtime.esm-bundler-B0xoGkDv.js → vue.runtime.esm-bundler-Xpz-L9Fn.js} +27 -22
  211. package/dist/{x-CkD6A1iB.js → x-C4lETLDx.js} +1 -1
  212. package/package.json +12 -12
  213. package/dist/DesignReferenceSidebar-C4pTMzQE.js +0 -264
  214. package/dist/TplModal-DPH4vV8M.js +0 -49
  215. package/dist/cdn/chunks/BlockPreviewCanvas-Dc4F4HzY.js.map +0 -1
  216. package/dist/cdn/chunks/CloudEditor-CeKaWWO5.js.map +0 -1
  217. package/dist/cdn/chunks/DesignReferenceSidebar-BjlaP69l.js +0 -223
  218. package/dist/cdn/chunks/TestEmailModal-CiPfOn2v.js.map +0 -1
  219. package/dist/cdn/chunks/TplModal-Cu4tBBnF.js +0 -50
  220. package/dist/cdn/chunks/TplModal-Cu4tBBnF.js.map +0 -1
  221. package/dist/cdn/chunks/dist-CiBEt0VR.js.map +0 -1
  222. package/dist/cdn/chunks/dist-CxTt8FRE.js.map +0 -1
  223. package/dist/cdn/chunks/keys-B5uoP9P7.js +0 -12
  224. package/dist/cdn/chunks/keys-B5uoP9P7.js.map +0 -1
  225. package/dist/cdn/chunks/liquid.browser-BJOEu6Cg.js.map +0 -1
  226. package/dist/cdn/chunks/src-BCJna-6p.js.map +0 -1
  227. package/dist/cdn/chunks/styles-BohMfIBd.js.map +0 -1
  228. package/dist/cdn/chunks/timeouts-Bmi_yePw.js +0 -6
  229. package/dist/cdn/chunks/tiptap-DRKu__AX.js.map +0 -1
  230. package/dist/cdn/chunks/useEditorCore-B_vwuKdI.js.map +0 -1
  231. package/dist/keys-BVlG5Ozc.js +0 -10
@@ -0,0 +1,223 @@
1
+ import { H as e, M as t, V as n, Z as r, ct as i, f as a, g as o, h as s, it as c, k as ee, m as te, n as ne, o as re, ot as ie, p as l, st as u, v as d, x as f, y as p, z as ae } from "./draggable-JcMTNF3U.js";
2
+ import "./timeouts-SsLMC4a3.js";
3
+ import { G as m, g as oe, i as se } from "./keys-BxPCfHBH.js";
4
+ import { St as ce, jt as le, n as h, pt as g, s as ue, xt as _ } from "./icons-Cp4ZIJw-.js";
5
+ import { t as de } from "./LoadingTrack-G2tuXqCJ.js";
6
+ import { t as v } from "./_plugin-vue_export-helper-B3ysoDQm.js";
7
+ import { n as fe } from "./useCloudI18n-CjVzv11v.js";
8
+ import { m as pe } from "./cloud-DOaGUdR0.js";
9
+ //#region src/cloud/components/DesignReferenceSidebar.vue?vue&type=script&setup=true&lang.ts
10
+ var me = {
11
+ key: 0,
12
+ class: "tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]"
13
+ }, he = { class: "tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3" }, ge = { class: "tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]" }, _e = { class: "tpl:flex-1 tpl:overflow-y-auto tpl:p-4" }, y = {
14
+ key: 0,
15
+ class: "tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center"
16
+ }, b = { class: "tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3" }, x = { class: "tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, S = {
17
+ key: 1,
18
+ class: "tpl:flex tpl:flex-col tpl:gap-4"
19
+ }, C = { class: "tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]" }, w = {
20
+ key: 0,
21
+ class: "tpl:flex tpl:flex-col tpl:gap-2"
22
+ }, T = { class: "tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]" }, E = ["src", "alt"], D = {
23
+ key: 1,
24
+ class: "tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2"
25
+ }, O = { class: "tpl:text-xs tpl:text-[var(--tpl-text-muted)]" }, k = { class: "tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]" }, A = { class: "tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]" }, j = ["accept"], M = { class: "tpl:flex tpl:flex-col tpl:gap-1.5" }, N = { class: "tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]" }, P = ["placeholder"], F = {
26
+ key: 0,
27
+ class: "tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]"
28
+ }, I = { class: "tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]" }, ve = { class: "tpl:flex tpl:gap-2" }, ye = {
29
+ key: 1,
30
+ class: "tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]"
31
+ }, be = ["disabled"], xe = { class: "tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]" }, L = /*#__PURE__*/ v(/* @__PURE__ */ f({
32
+ __name: "DesignReferenceSidebar",
33
+ props: {
34
+ visible: { type: Boolean },
35
+ hasExistingBlocks: { type: Boolean }
36
+ },
37
+ emits: ["close", "apply"],
38
+ setup(f, { emit: v }) {
39
+ let L = f, R = v, { t: z } = fe(), Se = m(oe, "DesignReferenceSidebar"), Ce = m(se, "DesignReferenceSidebar"), B = pe({
40
+ authManager: Ce,
41
+ getTemplateId: () => Se.state.template?.id ?? null,
42
+ onApply: (e) => R("apply", e)
43
+ }), V = r(null), H = r("image"), U = r(null), W = r(""), G = r(null), K = r(!1), q = r(!1), J = a(() => !B.isGenerating.value && U.value !== null);
44
+ function Y(e) {
45
+ H.value = e, Z();
46
+ }
47
+ function we(e) {
48
+ let t = e.target, n = t.files?.[0];
49
+ n && X(n), t.value = "";
50
+ }
51
+ function X(e) {
52
+ if (e.size > 10485760) {
53
+ B.error.value = z.designReference.fileTooLarge;
54
+ return;
55
+ }
56
+ if (H.value === "image") {
57
+ if (![
58
+ "image/png",
59
+ "image/jpeg",
60
+ "image/jpg",
61
+ "image/webp"
62
+ ].includes(e.type)) {
63
+ B.error.value = z.designReference.invalidFileType;
64
+ return;
65
+ }
66
+ } else if (H.value === "pdf" && e.type !== "application/pdf") {
67
+ B.error.value = z.designReference.invalidFileType;
68
+ return;
69
+ }
70
+ U.value = e, B.error.value = null, G.value && URL.revokeObjectURL(G.value), e.type.startsWith("image/") ? G.value = URL.createObjectURL(e) : G.value = null;
71
+ }
72
+ function Z() {
73
+ G.value &&= (URL.revokeObjectURL(G.value), null), U.value = null;
74
+ }
75
+ function Q(e) {
76
+ e.preventDefault(), q.value = !0;
77
+ }
78
+ function Te() {
79
+ q.value = !1;
80
+ }
81
+ function Ee(e) {
82
+ e.preventDefault(), q.value = !1;
83
+ let t = e.dataTransfer?.files?.[0];
84
+ t && X(t);
85
+ }
86
+ function $() {
87
+ if (!J.value) return;
88
+ if (L.hasExistingBlocks && !K.value) {
89
+ K.value = !0;
90
+ return;
91
+ }
92
+ K.value = !1;
93
+ let e = {};
94
+ W.value.trim() && (e.prompt = W.value.trim()), H.value === "image" && U.value ? e.imageUpload = U.value : H.value === "pdf" && U.value && (e.pdfUpload = U.value), B.generate(e);
95
+ }
96
+ function De() {
97
+ K.value = !1;
98
+ }
99
+ return ae(() => L.visible, (e) => {
100
+ e || (K.value = !1);
101
+ }), ee(() => {
102
+ G.value &&= (URL.revokeObjectURL(G.value), null);
103
+ }), (r, a) => (t(), te(ne, {
104
+ "enter-active-class": "tpl-design-slide-enter-active",
105
+ "enter-from-class": "tpl:translate-x-full",
106
+ "enter-to-class": "tpl:translate-x-0",
107
+ "leave-active-class": "tpl-design-slide-leave-active",
108
+ "leave-from-class": "tpl:translate-x-0",
109
+ "leave-to-class": "tpl:translate-x-full"
110
+ }, {
111
+ default: n(() => [f.visible ? (t(), o("div", me, [l("div", he, [l("div", ge, [p(c(g), {
112
+ size: 13,
113
+ "stroke-width": 2
114
+ }), l("span", null, i(c(z).designReference.title), 1)]), l("button", {
115
+ class: "tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:duration-150 tpl:text-[var(--tpl-text-muted)]",
116
+ onClick: a[0] ||= (e) => R("close")
117
+ }, [p(c(h), {
118
+ size: 14,
119
+ "stroke-width": 2
120
+ })])]), l("div", _e, [c(B).isGenerating.value ? (t(), o("div", y, [l("div", b, [p(de), l("p", x, i(c(z).designReference.generating), 1)])])) : (t(), o("div", S, [
121
+ l("div", C, [l("button", {
122
+ class: "tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150",
123
+ style: u({
124
+ backgroundColor: H.value === "image" ? "var(--tpl-bg)" : "transparent",
125
+ color: H.value === "image" ? "var(--tpl-primary)" : "var(--tpl-text-muted)",
126
+ boxShadow: H.value === "image" ? "var(--tpl-shadow)" : "none"
127
+ }),
128
+ onClick: a[1] ||= (e) => Y("image")
129
+ }, [p(c(ce), {
130
+ size: 12,
131
+ "stroke-width": 2
132
+ }), d(" " + i(c(z).designReference.uploadImage), 1)], 4), l("button", {
133
+ class: "tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150",
134
+ style: u({
135
+ backgroundColor: H.value === "pdf" ? "var(--tpl-bg)" : "transparent",
136
+ color: H.value === "pdf" ? "var(--tpl-primary)" : "var(--tpl-text-muted)",
137
+ boxShadow: H.value === "pdf" ? "var(--tpl-shadow)" : "none"
138
+ }),
139
+ onClick: a[2] ||= (e) => Y("pdf")
140
+ }, [p(c(_), {
141
+ size: 12,
142
+ "stroke-width": 2
143
+ }), d(" " + i(c(z).designReference.uploadPdf), 1)], 4)]),
144
+ l("div", null, [U.value ? (t(), o("div", w, [l("div", T, [G.value ? (t(), o("img", {
145
+ key: 0,
146
+ src: G.value,
147
+ alt: U.value.name,
148
+ class: "tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain"
149
+ }, null, 8, E)) : (t(), o("div", D, [p(c(_), {
150
+ size: 32,
151
+ "stroke-width": 1.5,
152
+ class: "tpl:text-[var(--tpl-text-dim)]"
153
+ }), l("span", O, i(U.value.name), 1)])), l("button", {
154
+ class: "tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:duration-150 tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]",
155
+ onClick: Z
156
+ }, [p(c(h), {
157
+ size: 12,
158
+ "stroke-width": 2
159
+ })])])])) : (t(), o("div", {
160
+ key: 1,
161
+ class: "tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors tpl:duration-150",
162
+ style: u({
163
+ borderColor: q.value ? "var(--tpl-primary)" : "var(--tpl-border-light)",
164
+ backgroundColor: q.value ? "var(--tpl-primary-light)" : "var(--tpl-bg)"
165
+ }),
166
+ onClick: a[3] ||= (e) => V.value?.click(),
167
+ onDragover: Q,
168
+ onDragleave: Te,
169
+ onDrop: Ee
170
+ }, [
171
+ p(c(ue), {
172
+ size: 24,
173
+ "stroke-width": 1.5,
174
+ class: "tpl:text-[var(--tpl-text-dim)]"
175
+ }),
176
+ l("span", k, i(c(z).designReference.dropHint), 1),
177
+ l("span", A, i(H.value === "image" ? c(z).designReference.acceptedImages : c(z).designReference.acceptedPdf), 1)
178
+ ], 36)), l("input", {
179
+ ref_key: "fileInput",
180
+ ref: V,
181
+ type: "file",
182
+ class: "tpl:hidden",
183
+ accept: H.value === "image" ? "image/png,image/jpeg,image/webp" : "application/pdf",
184
+ onChange: we
185
+ }, null, 40, j)]),
186
+ l("div", M, [l("label", N, i(c(z).designReference.promptLabel), 1), e(l("textarea", {
187
+ "onUpdate:modelValue": a[4] ||= (e) => W.value = e,
188
+ class: ie(["tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:duration-150 tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]", ["tpl-design-prompt-input"]]),
189
+ placeholder: c(z).designReference.promptPlaceholder,
190
+ rows: "3"
191
+ }, null, 8, P), [[re, W.value]])]),
192
+ K.value ? (t(), o("div", F, [l("p", I, i(c(z).designReference.replaceWarning), 1), l("div", ve, [l("button", {
193
+ class: "tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]",
194
+ style: { "background-color": "transparent" },
195
+ onClick: De
196
+ }, i(c(z).designReference.replaceCancel), 1), l("button", {
197
+ class: "tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]",
198
+ onClick: $
199
+ }, i(c(z).designReference.replaceConfirm), 1)])])) : s("", !0),
200
+ c(B).error.value ? (t(), o("div", ye, [p(c(le), {
201
+ size: 14,
202
+ "stroke-width": 2,
203
+ class: "tpl:mt-0.5 tpl:shrink-0"
204
+ }), l("span", null, i(c(z).designReference.error), 1)])) : s("", !0),
205
+ K.value ? s("", !0) : (t(), o("button", {
206
+ key: 2,
207
+ class: "tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]",
208
+ disabled: !J.value,
209
+ onClick: $
210
+ }, [p(c(g), {
211
+ size: 16,
212
+ "stroke-width": 2
213
+ }), d(" " + i(c(z).designReference.generate), 1)], 8, be)),
214
+ l("p", xe, i(c(z).aiMenu.disclaimer), 1)
215
+ ]))])])) : s("", !0)]),
216
+ _: 1
217
+ }));
218
+ }
219
+ }), [["__scopeId", "data-v-bdbf8d0d"]]);
220
+ //#endregion
221
+ export { L as default };
222
+
223
+ //# sourceMappingURL=DesignReferenceSidebar-DPqBr-ut.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DesignReferenceSidebar-BjlaP69l.js","names":[],"sources":["../../../src/cloud/components/DesignReferenceSidebar.vue","../../../src/cloud/components/DesignReferenceSidebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { MAX_UPLOAD_SIZE_BYTES } from \"../../constants/timeouts\";\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport { useDesignReference } from \"@templatical/core/cloud\";\nimport { EDITOR_KEY, AUTH_MANAGER_KEY, requireInject } from \"../../keys\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport {\n CircleAlert,\n FileImage,\n FileText,\n ImageUp,\n Upload,\n X,\n} from \"@lucide/vue\";\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n hasExistingBlocks: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"apply\", content: TemplateContent): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"DesignReferenceSidebar\");\nconst authManager = requireInject(AUTH_MANAGER_KEY, \"DesignReferenceSidebar\");\n\nconst designReference = useDesignReference({\n authManager,\n getTemplateId: () => editor.state.template?.id ?? null,\n onApply: (content) => emit(\"apply\", content),\n});\n\nconst fileInput = ref<HTMLInputElement | null>(null);\n\ntype SourceTab = \"image\" | \"pdf\";\n\nconst activeTab = ref<SourceTab>(\"image\");\nconst selectedFile = ref<File | null>(null);\nconst prompt = ref(\"\");\nconst filePreviewUrl = ref<string | null>(null);\nconst showConfirmation = ref(false);\nconst isDragging = ref(false);\n\nconst canGenerate = computed(() => {\n if (designReference.isGenerating.value) {\n return false;\n }\n\n return selectedFile.value !== null;\n});\n\nfunction selectTab(tab: SourceTab): void {\n activeTab.value = tab;\n clearFile();\n}\n\nfunction handleFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) {\n setFile(file);\n }\n // Reset input so same file can be selected again\n input.value = \"\";\n}\n\nfunction setFile(file: File): void {\n // Validate file size (10MB)\n if (file.size > MAX_UPLOAD_SIZE_BYTES) {\n designReference.error.value = cloudT.designReference.fileTooLarge;\n return;\n }\n\n // Validate file type\n if (activeTab.value === \"image\") {\n const validTypes = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/webp\"];\n if (!validTypes.includes(file.type)) {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n } else if (activeTab.value === \"pdf\") {\n if (file.type !== \"application/pdf\") {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n }\n\n selectedFile.value = file;\n designReference.error.value = null;\n\n // Create preview URL for images\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n }\n if (file.type.startsWith(\"image/\")) {\n filePreviewUrl.value = URL.createObjectURL(file);\n } else {\n filePreviewUrl.value = null;\n }\n}\n\nfunction clearFile(): void {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n selectedFile.value = null;\n}\n\nfunction handleDragOver(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = true;\n}\n\nfunction handleDragLeave(): void {\n isDragging.value = false;\n}\n\nfunction handleDrop(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = false;\n\n const file = event.dataTransfer?.files?.[0];\n if (file) {\n setFile(file);\n }\n}\n\nfunction handleGenerate(): void {\n if (!canGenerate.value) {\n return;\n }\n\n // Show confirmation if there are existing blocks\n if (props.hasExistingBlocks && !showConfirmation.value) {\n showConfirmation.value = true;\n return;\n }\n\n showConfirmation.value = false;\n\n const input: {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n } = {};\n\n if (prompt.value.trim()) {\n input.prompt = prompt.value.trim();\n }\n\n if (activeTab.value === \"image\" && selectedFile.value) {\n input.imageUpload = selectedFile.value;\n } else if (activeTab.value === \"pdf\" && selectedFile.value) {\n input.pdfUpload = selectedFile.value;\n }\n\n designReference.generate(input);\n}\n\nfunction cancelConfirmation(): void {\n showConfirmation.value = false;\n}\n\n// Reset state when panel closes\nwatch(\n () => props.visible,\n (isVisible) => {\n if (!isVisible) {\n showConfirmation.value = false;\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n});\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-design-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-design-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ImageUp :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.designReference.title }}</span>\n </div>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:duration-150 tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"designReference.isGenerating.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <div\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3\"\n >\n <LoadingTrack />\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.designReference.generating }}\n </p>\n </div>\n </div>\n\n <!-- Input form -->\n <div v-else class=\"tpl:flex tpl:flex-col tpl:gap-4\">\n <!-- Source tabs -->\n <div\n class=\"tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]\"\n >\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n backgroundColor:\n activeTab === 'image' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'image'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'image' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('image')\"\n >\n <FileImage :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadImage }}\n </button>\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n backgroundColor:\n activeTab === 'pdf' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'pdf'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'pdf' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('pdf')\"\n >\n <FileText :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadPdf }}\n </button>\n </div>\n\n <!-- File upload area (image or pdf) -->\n <div>\n <!-- Preview -->\n <div v-if=\"selectedFile\" class=\"tpl:flex tpl:flex-col tpl:gap-2\">\n <div\n class=\"tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]\"\n >\n <!-- Image preview -->\n <img\n v-if=\"filePreviewUrl\"\n :src=\"filePreviewUrl\"\n :alt=\"selectedFile.name\"\n class=\"tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain\"\n />\n <!-- PDF preview (icon-based) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2\"\n >\n <FileText\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\">\n {{ selectedFile.name }}\n </span>\n </div>\n <!-- Remove button -->\n <button\n class=\"tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:duration-150 tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]\"\n @click=\"clearFile\"\n >\n <X :size=\"12\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Drop zone -->\n <div\n v-else\n class=\"tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors tpl:duration-150\"\n :style=\"{\n borderColor: isDragging\n ? 'var(--tpl-primary)'\n : 'var(--tpl-border-light)',\n backgroundColor: isDragging\n ? 'var(--tpl-primary-light)'\n : 'var(--tpl-bg)',\n }\"\n @click=\"fileInput?.click()\"\n @dragover=\"handleDragOver\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop\"\n >\n <Upload\n :size=\"24\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span\n class=\"tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.dropHint }}\n </span>\n <span\n class=\"tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n activeTab === \"image\"\n ? cloudT.designReference.acceptedImages\n : cloudT.designReference.acceptedPdf\n }}\n </span>\n </div>\n <input\n ref=\"fileInput\"\n type=\"file\"\n class=\"tpl:hidden\"\n :accept=\"\n activeTab === 'image'\n ? 'image/png,image/jpeg,image/webp'\n : 'application/pdf'\n \"\n @change=\"handleFileSelect\"\n />\n </div>\n\n <!-- Prompt textarea -->\n <div class=\"tpl:flex tpl:flex-col tpl:gap-1.5\">\n <label\n class=\"tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.promptLabel }}\n </label>\n <textarea\n v-model=\"prompt\"\n class=\"tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:duration-150 tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]\"\n :class=\"['tpl-design-prompt-input']\"\n :placeholder=\"cloudT.designReference.promptPlaceholder\"\n rows=\"3\"\n />\n </div>\n\n <!-- Confirmation overlay -->\n <div\n v-if=\"showConfirmation\"\n class=\"tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]\"\n >\n <p class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\">\n {{ cloudT.designReference.replaceWarning }}\n </p>\n <div class=\"tpl:flex tpl:gap-2\">\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]\"\n style=\"background-color: transparent\"\n @click=\"cancelConfirmation\"\n >\n {{ cloudT.designReference.replaceCancel }}\n </button>\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]\"\n @click=\"handleGenerate\"\n >\n {{ cloudT.designReference.replaceConfirm }}\n </button>\n </div>\n </div>\n\n <!-- Error message -->\n <div\n v-if=\"designReference.error.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.designReference.error }}</span>\n </div>\n\n <!-- Generate button -->\n <button\n v-if=\"!showConfirmation\"\n class=\"tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]\"\n :disabled=\"!canGenerate\"\n @click=\"handleGenerate\"\n >\n <ImageUp :size=\"16\" :stroke-width=\"2\" />\n {{ cloudT.designReference.generate }}\n </button>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-design-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-prompt-input:focus {\n border-color: var(--tpl-primary);\n box-shadow: var(--tpl-ring);\n}\n\n.tpl-design-dropzone:hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { MAX_UPLOAD_SIZE_BYTES } from \"../../constants/timeouts\";\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport { useDesignReference } from \"@templatical/core/cloud\";\nimport { EDITOR_KEY, AUTH_MANAGER_KEY, requireInject } from \"../../keys\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport {\n CircleAlert,\n FileImage,\n FileText,\n ImageUp,\n Upload,\n X,\n} from \"@lucide/vue\";\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n hasExistingBlocks: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"apply\", content: TemplateContent): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"DesignReferenceSidebar\");\nconst authManager = requireInject(AUTH_MANAGER_KEY, \"DesignReferenceSidebar\");\n\nconst designReference = useDesignReference({\n authManager,\n getTemplateId: () => editor.state.template?.id ?? null,\n onApply: (content) => emit(\"apply\", content),\n});\n\nconst fileInput = ref<HTMLInputElement | null>(null);\n\ntype SourceTab = \"image\" | \"pdf\";\n\nconst activeTab = ref<SourceTab>(\"image\");\nconst selectedFile = ref<File | null>(null);\nconst prompt = ref(\"\");\nconst filePreviewUrl = ref<string | null>(null);\nconst showConfirmation = ref(false);\nconst isDragging = ref(false);\n\nconst canGenerate = computed(() => {\n if (designReference.isGenerating.value) {\n return false;\n }\n\n return selectedFile.value !== null;\n});\n\nfunction selectTab(tab: SourceTab): void {\n activeTab.value = tab;\n clearFile();\n}\n\nfunction handleFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) {\n setFile(file);\n }\n // Reset input so same file can be selected again\n input.value = \"\";\n}\n\nfunction setFile(file: File): void {\n // Validate file size (10MB)\n if (file.size > MAX_UPLOAD_SIZE_BYTES) {\n designReference.error.value = cloudT.designReference.fileTooLarge;\n return;\n }\n\n // Validate file type\n if (activeTab.value === \"image\") {\n const validTypes = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/webp\"];\n if (!validTypes.includes(file.type)) {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n } else if (activeTab.value === \"pdf\") {\n if (file.type !== \"application/pdf\") {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n }\n\n selectedFile.value = file;\n designReference.error.value = null;\n\n // Create preview URL for images\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n }\n if (file.type.startsWith(\"image/\")) {\n filePreviewUrl.value = URL.createObjectURL(file);\n } else {\n filePreviewUrl.value = null;\n }\n}\n\nfunction clearFile(): void {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n selectedFile.value = null;\n}\n\nfunction handleDragOver(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = true;\n}\n\nfunction handleDragLeave(): void {\n isDragging.value = false;\n}\n\nfunction handleDrop(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = false;\n\n const file = event.dataTransfer?.files?.[0];\n if (file) {\n setFile(file);\n }\n}\n\nfunction handleGenerate(): void {\n if (!canGenerate.value) {\n return;\n }\n\n // Show confirmation if there are existing blocks\n if (props.hasExistingBlocks && !showConfirmation.value) {\n showConfirmation.value = true;\n return;\n }\n\n showConfirmation.value = false;\n\n const input: {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n } = {};\n\n if (prompt.value.trim()) {\n input.prompt = prompt.value.trim();\n }\n\n if (activeTab.value === \"image\" && selectedFile.value) {\n input.imageUpload = selectedFile.value;\n } else if (activeTab.value === \"pdf\" && selectedFile.value) {\n input.pdfUpload = selectedFile.value;\n }\n\n designReference.generate(input);\n}\n\nfunction cancelConfirmation(): void {\n showConfirmation.value = false;\n}\n\n// Reset state when panel closes\nwatch(\n () => props.visible,\n (isVisible) => {\n if (!isVisible) {\n showConfirmation.value = false;\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n});\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-design-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-design-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ImageUp :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.designReference.title }}</span>\n </div>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:duration-150 tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"designReference.isGenerating.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <div\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3\"\n >\n <LoadingTrack />\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.designReference.generating }}\n </p>\n </div>\n </div>\n\n <!-- Input form -->\n <div v-else class=\"tpl:flex tpl:flex-col tpl:gap-4\">\n <!-- Source tabs -->\n <div\n class=\"tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]\"\n >\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n backgroundColor:\n activeTab === 'image' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'image'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'image' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('image')\"\n >\n <FileImage :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadImage }}\n </button>\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n backgroundColor:\n activeTab === 'pdf' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'pdf'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'pdf' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('pdf')\"\n >\n <FileText :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadPdf }}\n </button>\n </div>\n\n <!-- File upload area (image or pdf) -->\n <div>\n <!-- Preview -->\n <div v-if=\"selectedFile\" class=\"tpl:flex tpl:flex-col tpl:gap-2\">\n <div\n class=\"tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]\"\n >\n <!-- Image preview -->\n <img\n v-if=\"filePreviewUrl\"\n :src=\"filePreviewUrl\"\n :alt=\"selectedFile.name\"\n class=\"tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain\"\n />\n <!-- PDF preview (icon-based) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2\"\n >\n <FileText\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\">\n {{ selectedFile.name }}\n </span>\n </div>\n <!-- Remove button -->\n <button\n class=\"tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:duration-150 tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]\"\n @click=\"clearFile\"\n >\n <X :size=\"12\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Drop zone -->\n <div\n v-else\n class=\"tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors tpl:duration-150\"\n :style=\"{\n borderColor: isDragging\n ? 'var(--tpl-primary)'\n : 'var(--tpl-border-light)',\n backgroundColor: isDragging\n ? 'var(--tpl-primary-light)'\n : 'var(--tpl-bg)',\n }\"\n @click=\"fileInput?.click()\"\n @dragover=\"handleDragOver\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop\"\n >\n <Upload\n :size=\"24\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span\n class=\"tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.dropHint }}\n </span>\n <span\n class=\"tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n activeTab === \"image\"\n ? cloudT.designReference.acceptedImages\n : cloudT.designReference.acceptedPdf\n }}\n </span>\n </div>\n <input\n ref=\"fileInput\"\n type=\"file\"\n class=\"tpl:hidden\"\n :accept=\"\n activeTab === 'image'\n ? 'image/png,image/jpeg,image/webp'\n : 'application/pdf'\n \"\n @change=\"handleFileSelect\"\n />\n </div>\n\n <!-- Prompt textarea -->\n <div class=\"tpl:flex tpl:flex-col tpl:gap-1.5\">\n <label\n class=\"tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.promptLabel }}\n </label>\n <textarea\n v-model=\"prompt\"\n class=\"tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:duration-150 tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]\"\n :class=\"['tpl-design-prompt-input']\"\n :placeholder=\"cloudT.designReference.promptPlaceholder\"\n rows=\"3\"\n />\n </div>\n\n <!-- Confirmation overlay -->\n <div\n v-if=\"showConfirmation\"\n class=\"tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]\"\n >\n <p class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\">\n {{ cloudT.designReference.replaceWarning }}\n </p>\n <div class=\"tpl:flex tpl:gap-2\">\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]\"\n style=\"background-color: transparent\"\n @click=\"cancelConfirmation\"\n >\n {{ cloudT.designReference.replaceCancel }}\n </button>\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]\"\n @click=\"handleGenerate\"\n >\n {{ cloudT.designReference.replaceConfirm }}\n </button>\n </div>\n </div>\n\n <!-- Error message -->\n <div\n v-if=\"designReference.error.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.designReference.error }}</span>\n </div>\n\n <!-- Generate button -->\n <button\n v-if=\"!showConfirmation\"\n class=\"tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]\"\n :disabled=\"!canGenerate\"\n @click=\"handleGenerate\"\n >\n <ImageUp :size=\"16\" :stroke-width=\"2\" />\n {{ cloudT.designReference.generate }}\n </button>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-design-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-prompt-input:focus {\n border-color: var(--tpl-primary);\n box-shadow: var(--tpl-ring);\n}\n\n.tpl-design-dropzone:hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"DesignReferenceSidebar-DPqBr-ut.js","names":[],"sources":["../../../src/cloud/components/DesignReferenceSidebar.vue","../../../src/cloud/components/DesignReferenceSidebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { MAX_UPLOAD_SIZE_BYTES } from \"../../constants/timeouts\";\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport { useDesignReference } from \"@templatical/core/cloud\";\nimport { EDITOR_KEY, AUTH_MANAGER_KEY, requireInject } from \"../../keys\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport {\n CircleAlert,\n FileImage,\n FileText,\n ImageUp,\n Upload,\n X,\n} from \"@lucide/vue\";\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n hasExistingBlocks: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"apply\", content: TemplateContent): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"DesignReferenceSidebar\");\nconst authManager = requireInject(AUTH_MANAGER_KEY, \"DesignReferenceSidebar\");\n\nconst designReference = useDesignReference({\n authManager,\n getTemplateId: () => editor.state.template?.id ?? null,\n onApply: (content) => emit(\"apply\", content),\n});\n\nconst fileInput = ref<HTMLInputElement | null>(null);\n\ntype SourceTab = \"image\" | \"pdf\";\n\nconst activeTab = ref<SourceTab>(\"image\");\nconst selectedFile = ref<File | null>(null);\nconst prompt = ref(\"\");\nconst filePreviewUrl = ref<string | null>(null);\nconst showConfirmation = ref(false);\nconst isDragging = ref(false);\n\nconst canGenerate = computed(() => {\n if (designReference.isGenerating.value) {\n return false;\n }\n\n return selectedFile.value !== null;\n});\n\nfunction selectTab(tab: SourceTab): void {\n activeTab.value = tab;\n clearFile();\n}\n\nfunction handleFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) {\n setFile(file);\n }\n // Reset input so same file can be selected again\n input.value = \"\";\n}\n\nfunction setFile(file: File): void {\n // Validate file size (10MB)\n if (file.size > MAX_UPLOAD_SIZE_BYTES) {\n designReference.error.value = cloudT.designReference.fileTooLarge;\n return;\n }\n\n // Validate file type\n if (activeTab.value === \"image\") {\n const validTypes = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/webp\"];\n if (!validTypes.includes(file.type)) {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n } else if (activeTab.value === \"pdf\") {\n if (file.type !== \"application/pdf\") {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n }\n\n selectedFile.value = file;\n designReference.error.value = null;\n\n // Create preview URL for images\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n }\n if (file.type.startsWith(\"image/\")) {\n filePreviewUrl.value = URL.createObjectURL(file);\n } else {\n filePreviewUrl.value = null;\n }\n}\n\nfunction clearFile(): void {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n selectedFile.value = null;\n}\n\nfunction handleDragOver(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = true;\n}\n\nfunction handleDragLeave(): void {\n isDragging.value = false;\n}\n\nfunction handleDrop(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = false;\n\n const file = event.dataTransfer?.files?.[0];\n if (file) {\n setFile(file);\n }\n}\n\nfunction handleGenerate(): void {\n if (!canGenerate.value) {\n return;\n }\n\n // Show confirmation if there are existing blocks\n if (props.hasExistingBlocks && !showConfirmation.value) {\n showConfirmation.value = true;\n return;\n }\n\n showConfirmation.value = false;\n\n const input: {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n } = {};\n\n if (prompt.value.trim()) {\n input.prompt = prompt.value.trim();\n }\n\n if (activeTab.value === \"image\" && selectedFile.value) {\n input.imageUpload = selectedFile.value;\n } else if (activeTab.value === \"pdf\" && selectedFile.value) {\n input.pdfUpload = selectedFile.value;\n }\n\n designReference.generate(input);\n}\n\nfunction cancelConfirmation(): void {\n showConfirmation.value = false;\n}\n\n// Reset state when panel closes\nwatch(\n () => props.visible,\n (isVisible) => {\n if (!isVisible) {\n showConfirmation.value = false;\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n});\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-design-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-design-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ImageUp :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.designReference.title }}</span>\n </div>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:duration-150 tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"designReference.isGenerating.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <div\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3\"\n >\n <LoadingTrack />\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.designReference.generating }}\n </p>\n </div>\n </div>\n\n <!-- Input form -->\n <div v-else class=\"tpl:flex tpl:flex-col tpl:gap-4\">\n <!-- Source tabs -->\n <div\n class=\"tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]\"\n >\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n backgroundColor:\n activeTab === 'image' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'image'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'image' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('image')\"\n >\n <FileImage :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadImage }}\n </button>\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n backgroundColor:\n activeTab === 'pdf' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'pdf'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'pdf' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('pdf')\"\n >\n <FileText :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadPdf }}\n </button>\n </div>\n\n <!-- File upload area (image or pdf) -->\n <div>\n <!-- Preview -->\n <div v-if=\"selectedFile\" class=\"tpl:flex tpl:flex-col tpl:gap-2\">\n <div\n class=\"tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]\"\n >\n <!-- Image preview -->\n <img\n v-if=\"filePreviewUrl\"\n :src=\"filePreviewUrl\"\n :alt=\"selectedFile.name\"\n class=\"tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain\"\n />\n <!-- PDF preview (icon-based) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2\"\n >\n <FileText\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\">\n {{ selectedFile.name }}\n </span>\n </div>\n <!-- Remove button -->\n <button\n class=\"tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:duration-150 tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]\"\n @click=\"clearFile\"\n >\n <X :size=\"12\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Drop zone -->\n <div\n v-else\n class=\"tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors tpl:duration-150\"\n :style=\"{\n borderColor: isDragging\n ? 'var(--tpl-primary)'\n : 'var(--tpl-border-light)',\n backgroundColor: isDragging\n ? 'var(--tpl-primary-light)'\n : 'var(--tpl-bg)',\n }\"\n @click=\"fileInput?.click()\"\n @dragover=\"handleDragOver\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop\"\n >\n <Upload\n :size=\"24\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span\n class=\"tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.dropHint }}\n </span>\n <span\n class=\"tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n activeTab === \"image\"\n ? cloudT.designReference.acceptedImages\n : cloudT.designReference.acceptedPdf\n }}\n </span>\n </div>\n <input\n ref=\"fileInput\"\n type=\"file\"\n class=\"tpl:hidden\"\n :accept=\"\n activeTab === 'image'\n ? 'image/png,image/jpeg,image/webp'\n : 'application/pdf'\n \"\n @change=\"handleFileSelect\"\n />\n </div>\n\n <!-- Prompt textarea -->\n <div class=\"tpl:flex tpl:flex-col tpl:gap-1.5\">\n <label\n class=\"tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.promptLabel }}\n </label>\n <textarea\n v-model=\"prompt\"\n class=\"tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:duration-150 tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]\"\n :class=\"['tpl-design-prompt-input']\"\n :placeholder=\"cloudT.designReference.promptPlaceholder\"\n rows=\"3\"\n />\n </div>\n\n <!-- Confirmation overlay -->\n <div\n v-if=\"showConfirmation\"\n class=\"tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]\"\n >\n <p class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\">\n {{ cloudT.designReference.replaceWarning }}\n </p>\n <div class=\"tpl:flex tpl:gap-2\">\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]\"\n style=\"background-color: transparent\"\n @click=\"cancelConfirmation\"\n >\n {{ cloudT.designReference.replaceCancel }}\n </button>\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]\"\n @click=\"handleGenerate\"\n >\n {{ cloudT.designReference.replaceConfirm }}\n </button>\n </div>\n </div>\n\n <!-- Error message -->\n <div\n v-if=\"designReference.error.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.designReference.error }}</span>\n </div>\n\n <!-- Generate button -->\n <button\n v-if=\"!showConfirmation\"\n class=\"tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]\"\n :disabled=\"!canGenerate\"\n @click=\"handleGenerate\"\n >\n <ImageUp :size=\"16\" :stroke-width=\"2\" />\n {{ cloudT.designReference.generate }}\n </button>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-design-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-prompt-input:focus {\n border-color: var(--tpl-primary);\n box-shadow: var(--tpl-ring);\n}\n\n.tpl-design-dropzone:hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { MAX_UPLOAD_SIZE_BYTES } from \"../../constants/timeouts\";\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport { useDesignReference } from \"@templatical/core/cloud\";\nimport { EDITOR_KEY, AUTH_MANAGER_KEY, requireInject } from \"../../keys\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport {\n CircleAlert,\n FileImage,\n FileText,\n ImageUp,\n Upload,\n X,\n} from \"@lucide/vue\";\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n hasExistingBlocks: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"apply\", content: TemplateContent): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"DesignReferenceSidebar\");\nconst authManager = requireInject(AUTH_MANAGER_KEY, \"DesignReferenceSidebar\");\n\nconst designReference = useDesignReference({\n authManager,\n getTemplateId: () => editor.state.template?.id ?? null,\n onApply: (content) => emit(\"apply\", content),\n});\n\nconst fileInput = ref<HTMLInputElement | null>(null);\n\ntype SourceTab = \"image\" | \"pdf\";\n\nconst activeTab = ref<SourceTab>(\"image\");\nconst selectedFile = ref<File | null>(null);\nconst prompt = ref(\"\");\nconst filePreviewUrl = ref<string | null>(null);\nconst showConfirmation = ref(false);\nconst isDragging = ref(false);\n\nconst canGenerate = computed(() => {\n if (designReference.isGenerating.value) {\n return false;\n }\n\n return selectedFile.value !== null;\n});\n\nfunction selectTab(tab: SourceTab): void {\n activeTab.value = tab;\n clearFile();\n}\n\nfunction handleFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) {\n setFile(file);\n }\n // Reset input so same file can be selected again\n input.value = \"\";\n}\n\nfunction setFile(file: File): void {\n // Validate file size (10MB)\n if (file.size > MAX_UPLOAD_SIZE_BYTES) {\n designReference.error.value = cloudT.designReference.fileTooLarge;\n return;\n }\n\n // Validate file type\n if (activeTab.value === \"image\") {\n const validTypes = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/webp\"];\n if (!validTypes.includes(file.type)) {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n } else if (activeTab.value === \"pdf\") {\n if (file.type !== \"application/pdf\") {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n }\n\n selectedFile.value = file;\n designReference.error.value = null;\n\n // Create preview URL for images\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n }\n if (file.type.startsWith(\"image/\")) {\n filePreviewUrl.value = URL.createObjectURL(file);\n } else {\n filePreviewUrl.value = null;\n }\n}\n\nfunction clearFile(): void {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n selectedFile.value = null;\n}\n\nfunction handleDragOver(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = true;\n}\n\nfunction handleDragLeave(): void {\n isDragging.value = false;\n}\n\nfunction handleDrop(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = false;\n\n const file = event.dataTransfer?.files?.[0];\n if (file) {\n setFile(file);\n }\n}\n\nfunction handleGenerate(): void {\n if (!canGenerate.value) {\n return;\n }\n\n // Show confirmation if there are existing blocks\n if (props.hasExistingBlocks && !showConfirmation.value) {\n showConfirmation.value = true;\n return;\n }\n\n showConfirmation.value = false;\n\n const input: {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n } = {};\n\n if (prompt.value.trim()) {\n input.prompt = prompt.value.trim();\n }\n\n if (activeTab.value === \"image\" && selectedFile.value) {\n input.imageUpload = selectedFile.value;\n } else if (activeTab.value === \"pdf\" && selectedFile.value) {\n input.pdfUpload = selectedFile.value;\n }\n\n designReference.generate(input);\n}\n\nfunction cancelConfirmation(): void {\n showConfirmation.value = false;\n}\n\n// Reset state when panel closes\nwatch(\n () => props.visible,\n (isVisible) => {\n if (!isVisible) {\n showConfirmation.value = false;\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n});\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-design-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-design-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ImageUp :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.designReference.title }}</span>\n </div>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:duration-150 tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"designReference.isGenerating.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <div\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3\"\n >\n <LoadingTrack />\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.designReference.generating }}\n </p>\n </div>\n </div>\n\n <!-- Input form -->\n <div v-else class=\"tpl:flex tpl:flex-col tpl:gap-4\">\n <!-- Source tabs -->\n <div\n class=\"tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]\"\n >\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n backgroundColor:\n activeTab === 'image' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'image'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'image' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('image')\"\n >\n <FileImage :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadImage }}\n </button>\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150\"\n :style=\"{\n backgroundColor:\n activeTab === 'pdf' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'pdf'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'pdf' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('pdf')\"\n >\n <FileText :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadPdf }}\n </button>\n </div>\n\n <!-- File upload area (image or pdf) -->\n <div>\n <!-- Preview -->\n <div v-if=\"selectedFile\" class=\"tpl:flex tpl:flex-col tpl:gap-2\">\n <div\n class=\"tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]\"\n >\n <!-- Image preview -->\n <img\n v-if=\"filePreviewUrl\"\n :src=\"filePreviewUrl\"\n :alt=\"selectedFile.name\"\n class=\"tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain\"\n />\n <!-- PDF preview (icon-based) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2\"\n >\n <FileText\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\">\n {{ selectedFile.name }}\n </span>\n </div>\n <!-- Remove button -->\n <button\n class=\"tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:duration-150 tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]\"\n @click=\"clearFile\"\n >\n <X :size=\"12\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Drop zone -->\n <div\n v-else\n class=\"tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors tpl:duration-150\"\n :style=\"{\n borderColor: isDragging\n ? 'var(--tpl-primary)'\n : 'var(--tpl-border-light)',\n backgroundColor: isDragging\n ? 'var(--tpl-primary-light)'\n : 'var(--tpl-bg)',\n }\"\n @click=\"fileInput?.click()\"\n @dragover=\"handleDragOver\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop\"\n >\n <Upload\n :size=\"24\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span\n class=\"tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.dropHint }}\n </span>\n <span\n class=\"tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n activeTab === \"image\"\n ? cloudT.designReference.acceptedImages\n : cloudT.designReference.acceptedPdf\n }}\n </span>\n </div>\n <input\n ref=\"fileInput\"\n type=\"file\"\n class=\"tpl:hidden\"\n :accept=\"\n activeTab === 'image'\n ? 'image/png,image/jpeg,image/webp'\n : 'application/pdf'\n \"\n @change=\"handleFileSelect\"\n />\n </div>\n\n <!-- Prompt textarea -->\n <div class=\"tpl:flex tpl:flex-col tpl:gap-1.5\">\n <label\n class=\"tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.promptLabel }}\n </label>\n <textarea\n v-model=\"prompt\"\n class=\"tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:duration-150 tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]\"\n :class=\"['tpl-design-prompt-input']\"\n :placeholder=\"cloudT.designReference.promptPlaceholder\"\n rows=\"3\"\n />\n </div>\n\n <!-- Confirmation overlay -->\n <div\n v-if=\"showConfirmation\"\n class=\"tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]\"\n >\n <p class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\">\n {{ cloudT.designReference.replaceWarning }}\n </p>\n <div class=\"tpl:flex tpl:gap-2\">\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]\"\n style=\"background-color: transparent\"\n @click=\"cancelConfirmation\"\n >\n {{ cloudT.designReference.replaceCancel }}\n </button>\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]\"\n @click=\"handleGenerate\"\n >\n {{ cloudT.designReference.replaceConfirm }}\n </button>\n </div>\n </div>\n\n <!-- Error message -->\n <div\n v-if=\"designReference.error.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.designReference.error }}</span>\n </div>\n\n <!-- Generate button -->\n <button\n v-if=\"!showConfirmation\"\n class=\"tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]\"\n :disabled=\"!canGenerate\"\n @click=\"handleGenerate\"\n >\n <ImageUp :size=\"16\" :stroke-width=\"2\" />\n {{ cloudT.designReference.generate }}\n </button>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-design-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-prompt-input:focus {\n border-color: var(--tpl-primary);\n box-shadow: var(--tpl-ring);\n}\n\n.tpl-design-dropzone:hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { L as e, M as t, P as n, T as r, ct as i, f as a, g as o, h as s, it as c, m as l, ot as u, p as d, u as f, v as p, x as m, y as h } from "./draggable-D840DIZB.js";
2
- import { L as g, h as _ } from "./keys-B5uoP9P7.js";
3
- import { t as v } from "./useI18n-graz19nI.js";
4
- import { Vt as y, dt as b, jt as x, r as S, st as C, u as w } from "./icons-Cqxvwgz7.js";
1
+ import { L as e, M as t, P as n, T as r, ct as i, f as a, g as o, h as s, it as c, m as l, ot as u, p as d, u as f, v as p, x as m, y as h } from "./draggable-JcMTNF3U.js";
2
+ import { B as g, g as _ } from "./keys-BxPCfHBH.js";
3
+ import { t as v } from "./useI18n-DniEFeIl.js";
4
+ import { Vt as y, dt as b, jt as x, r as S, st as C, u as w } from "./icons-Cp4ZIJw-.js";
5
5
  //#region src/components/sidebar/IssuesPanel.vue?vue&type=script&setup=true&lang.ts
6
6
  var T = { class: "tpl:flex tpl:flex-col tpl:gap-4 tpl:p-4" }, E = { class: "tpl:flex tpl:items-center tpl:gap-2" }, D = { class: "tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]" }, O = ["title"], k = {
7
7
  key: 0,
@@ -95,4 +95,4 @@ var T = { class: "tpl:flex tpl:flex-col tpl:gap-4 tpl:p-4" }, E = { class: "tpl:
95
95
  //#endregion
96
96
  export { R as default };
97
97
 
98
- //# sourceMappingURL=IssuesPanel-CkkEnhxZ.js.map
98
+ //# sourceMappingURL=IssuesPanel-DoQWb23r.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IssuesPanel-CkkEnhxZ.js","names":[],"sources":["../../../src/components/sidebar/IssuesPanel.vue","../../../src/components/sidebar/IssuesPanel.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, inject } from \"vue\";\nimport {\n ListChecks,\n AlertCircle,\n AlertTriangle,\n Info,\n ArrowRight,\n Wrench,\n} from \"@lucide/vue\";\nimport { useI18n } from \"../../composables/useI18n\";\nimport { TEMPLATE_LINT_KEY, EDITOR_KEY } from \"../../keys\";\nimport type { LintIssue } from \"../../composables/useTemplateLint\";\n\nconst { t, format } = useI18n();\nconst lint = inject(TEMPLATE_LINT_KEY, null);\nconst editor = inject(EDITOR_KEY, null);\n\nconst errors = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"error\"),\n);\nconst warnings = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"warning\"),\n);\nconst infos = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"info\"),\n);\n\nconst totalCount = computed(\n () => errors.value.length + warnings.value.length + infos.value.length,\n);\n\nfunction jumpTo(issue: LintIssue): void {\n if (!editor) return;\n if (issue.blockId) editor.selectBlock(issue.blockId);\n}\n\nfunction applyFix(issue: LintIssue): void {\n lint?.applyFix(issue);\n}\n</script>\n\n<template>\n <div class=\"tpl:flex tpl:flex-col tpl:gap-4 tpl:p-4\">\n <header class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <ListChecks :size=\"16\" :stroke-width=\"1.5\" />\n <h3\n class=\"tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]\"\n >\n {{ t.issues.panelTitle }}\n </h3>\n <span\n v-if=\"totalCount > 0\"\n class=\"tpl:ml-auto tpl:rounded-full tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-0.5 tpl:text-[11px] tpl:text-[var(--tpl-text-muted)]\"\n :title=\"format(t.issues.issueCountTooltip, { count: totalCount })\"\n >\n {{ totalCount }}\n </span>\n </header>\n\n <div\n v-if=\"!lint || lint.unavailable.value\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n <!-- Quality package not available; render nothing visible beyond a hint. -->\n </div>\n\n <div\n v-else-if=\"totalCount === 0\"\n class=\"tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-3 tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.issues.emptyState }}\n </div>\n\n <template v-else>\n <section\n v-for=\"group in [\n {\n key: 'errors',\n title: t.issues.groupErrors,\n icon: AlertCircle,\n items: errors,\n tone: 'tpl:text-[var(--tpl-danger)]',\n },\n {\n key: 'warnings',\n title: t.issues.groupWarnings,\n icon: AlertTriangle,\n items: warnings,\n tone: 'tpl:text-[var(--tpl-warning)]',\n },\n {\n key: 'info',\n title: t.issues.groupInfo,\n icon: Info,\n items: infos,\n tone: 'tpl:text-[var(--tpl-text-muted)]',\n },\n ]\"\n :key=\"group.key\"\n >\n <header\n v-if=\"group.items.length > 0\"\n class=\"tpl:mb-2 tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-[11px] tpl:font-semibold tpl:uppercase tpl:tracking-wide\"\n :class=\"group.tone\"\n >\n <component :is=\"group.icon\" :size=\"12\" :stroke-width=\"2\" />\n {{ group.title }}\n <span class=\"tpl:ml-auto tpl:font-normal tpl:opacity-70\">\n {{ group.items.length }}\n </span>\n </header>\n <ul\n v-if=\"group.items.length > 0\"\n class=\"tpl:m-0 tpl:mb-3 tpl:flex tpl:list-none tpl:flex-col tpl:gap-2 tpl:p-0\"\n >\n <li\n v-for=\"issue in group.items\"\n :key=\"`${issue.ruleId}-${issue.blockId ?? 'template'}`\"\n class=\"tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-3\"\n >\n <p class=\"tpl:m-0 tpl:mb-2 tpl:text-xs tpl:text-[var(--tpl-text)]\">\n {{ issue.message }}\n </p>\n <p\n class=\"tpl:m-0 tpl:mb-2 tpl:font-mono tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ issue.ruleId }}\n </p>\n <div class=\"tpl:flex tpl:gap-1.5\">\n <button\n v-if=\"issue.blockId\"\n type=\"button\"\n class=\"tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-[11px] tpl:font-medium tpl:text-[var(--tpl-text)]\"\n @click=\"jumpTo(issue)\"\n >\n <ArrowRight :size=\"10\" :stroke-width=\"2\" />\n {{ t.issues.jump }}\n </button>\n <button\n v-if=\"issue.fix\"\n type=\"button\"\n class=\"tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-md tpl:bg-[var(--tpl-primary)] tpl:px-2 tpl:py-1 tpl:text-[11px] tpl:font-medium tpl:text-white\"\n :title=\"issue.fix.description\"\n @click=\"applyFix(issue)\"\n >\n <Wrench :size=\"10\" :stroke-width=\"2\" />\n {{ t.issues.fix }}\n </button>\n </div>\n </li>\n </ul>\n </section>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject } from \"vue\";\nimport {\n ListChecks,\n AlertCircle,\n AlertTriangle,\n Info,\n ArrowRight,\n Wrench,\n} from \"@lucide/vue\";\nimport { useI18n } from \"../../composables/useI18n\";\nimport { TEMPLATE_LINT_KEY, EDITOR_KEY } from \"../../keys\";\nimport type { LintIssue } from \"../../composables/useTemplateLint\";\n\nconst { t, format } = useI18n();\nconst lint = inject(TEMPLATE_LINT_KEY, null);\nconst editor = inject(EDITOR_KEY, null);\n\nconst errors = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"error\"),\n);\nconst warnings = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"warning\"),\n);\nconst infos = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"info\"),\n);\n\nconst totalCount = computed(\n () => errors.value.length + warnings.value.length + infos.value.length,\n);\n\nfunction jumpTo(issue: LintIssue): void {\n if (!editor) return;\n if (issue.blockId) editor.selectBlock(issue.blockId);\n}\n\nfunction applyFix(issue: LintIssue): void {\n lint?.applyFix(issue);\n}\n</script>\n\n<template>\n <div class=\"tpl:flex tpl:flex-col tpl:gap-4 tpl:p-4\">\n <header class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <ListChecks :size=\"16\" :stroke-width=\"1.5\" />\n <h3\n class=\"tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]\"\n >\n {{ t.issues.panelTitle }}\n </h3>\n <span\n v-if=\"totalCount > 0\"\n class=\"tpl:ml-auto tpl:rounded-full tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-0.5 tpl:text-[11px] tpl:text-[var(--tpl-text-muted)]\"\n :title=\"format(t.issues.issueCountTooltip, { count: totalCount })\"\n >\n {{ totalCount }}\n </span>\n </header>\n\n <div\n v-if=\"!lint || lint.unavailable.value\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n <!-- Quality package not available; render nothing visible beyond a hint. -->\n </div>\n\n <div\n v-else-if=\"totalCount === 0\"\n class=\"tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-3 tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.issues.emptyState }}\n </div>\n\n <template v-else>\n <section\n v-for=\"group in [\n {\n key: 'errors',\n title: t.issues.groupErrors,\n icon: AlertCircle,\n items: errors,\n tone: 'tpl:text-[var(--tpl-danger)]',\n },\n {\n key: 'warnings',\n title: t.issues.groupWarnings,\n icon: AlertTriangle,\n items: warnings,\n tone: 'tpl:text-[var(--tpl-warning)]',\n },\n {\n key: 'info',\n title: t.issues.groupInfo,\n icon: Info,\n items: infos,\n tone: 'tpl:text-[var(--tpl-text-muted)]',\n },\n ]\"\n :key=\"group.key\"\n >\n <header\n v-if=\"group.items.length > 0\"\n class=\"tpl:mb-2 tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-[11px] tpl:font-semibold tpl:uppercase tpl:tracking-wide\"\n :class=\"group.tone\"\n >\n <component :is=\"group.icon\" :size=\"12\" :stroke-width=\"2\" />\n {{ group.title }}\n <span class=\"tpl:ml-auto tpl:font-normal tpl:opacity-70\">\n {{ group.items.length }}\n </span>\n </header>\n <ul\n v-if=\"group.items.length > 0\"\n class=\"tpl:m-0 tpl:mb-3 tpl:flex tpl:list-none tpl:flex-col tpl:gap-2 tpl:p-0\"\n >\n <li\n v-for=\"issue in group.items\"\n :key=\"`${issue.ruleId}-${issue.blockId ?? 'template'}`\"\n class=\"tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-3\"\n >\n <p class=\"tpl:m-0 tpl:mb-2 tpl:text-xs tpl:text-[var(--tpl-text)]\">\n {{ issue.message }}\n </p>\n <p\n class=\"tpl:m-0 tpl:mb-2 tpl:font-mono tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ issue.ruleId }}\n </p>\n <div class=\"tpl:flex tpl:gap-1.5\">\n <button\n v-if=\"issue.blockId\"\n type=\"button\"\n class=\"tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-[11px] tpl:font-medium tpl:text-[var(--tpl-text)]\"\n @click=\"jumpTo(issue)\"\n >\n <ArrowRight :size=\"10\" :stroke-width=\"2\" />\n {{ t.issues.jump }}\n </button>\n <button\n v-if=\"issue.fix\"\n type=\"button\"\n class=\"tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-md tpl:bg-[var(--tpl-primary)] tpl:px-2 tpl:py-1 tpl:text-[11px] tpl:font-medium tpl:text-white\"\n :title=\"issue.fix.description\"\n @click=\"applyFix(issue)\"\n >\n <Wrench :size=\"10\" :stroke-width=\"2\" />\n {{ t.issues.fix }}\n </button>\n </div>\n </li>\n </ul>\n </section>\n </template>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"IssuesPanel-DoQWb23r.js","names":[],"sources":["../../../src/components/sidebar/IssuesPanel.vue","../../../src/components/sidebar/IssuesPanel.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, inject } from \"vue\";\nimport {\n ListChecks,\n AlertCircle,\n AlertTriangle,\n Info,\n ArrowRight,\n Wrench,\n} from \"@lucide/vue\";\nimport { useI18n } from \"../../composables/useI18n\";\nimport { TEMPLATE_LINT_KEY, EDITOR_KEY } from \"../../keys\";\nimport type { LintIssue } from \"../../composables/useTemplateLint\";\n\nconst { t, format } = useI18n();\nconst lint = inject(TEMPLATE_LINT_KEY, null);\nconst editor = inject(EDITOR_KEY, null);\n\nconst errors = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"error\"),\n);\nconst warnings = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"warning\"),\n);\nconst infos = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"info\"),\n);\n\nconst totalCount = computed(\n () => errors.value.length + warnings.value.length + infos.value.length,\n);\n\nfunction jumpTo(issue: LintIssue): void {\n if (!editor) return;\n if (issue.blockId) editor.selectBlock(issue.blockId);\n}\n\nfunction applyFix(issue: LintIssue): void {\n lint?.applyFix(issue);\n}\n</script>\n\n<template>\n <div class=\"tpl:flex tpl:flex-col tpl:gap-4 tpl:p-4\">\n <header class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <ListChecks :size=\"16\" :stroke-width=\"1.5\" />\n <h3\n class=\"tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]\"\n >\n {{ t.issues.panelTitle }}\n </h3>\n <span\n v-if=\"totalCount > 0\"\n class=\"tpl:ml-auto tpl:rounded-full tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-0.5 tpl:text-[11px] tpl:text-[var(--tpl-text-muted)]\"\n :title=\"format(t.issues.issueCountTooltip, { count: totalCount })\"\n >\n {{ totalCount }}\n </span>\n </header>\n\n <div\n v-if=\"!lint || lint.unavailable.value\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n <!-- Quality package not available; render nothing visible beyond a hint. -->\n </div>\n\n <div\n v-else-if=\"totalCount === 0\"\n class=\"tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-3 tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.issues.emptyState }}\n </div>\n\n <template v-else>\n <section\n v-for=\"group in [\n {\n key: 'errors',\n title: t.issues.groupErrors,\n icon: AlertCircle,\n items: errors,\n tone: 'tpl:text-[var(--tpl-danger)]',\n },\n {\n key: 'warnings',\n title: t.issues.groupWarnings,\n icon: AlertTriangle,\n items: warnings,\n tone: 'tpl:text-[var(--tpl-warning)]',\n },\n {\n key: 'info',\n title: t.issues.groupInfo,\n icon: Info,\n items: infos,\n tone: 'tpl:text-[var(--tpl-text-muted)]',\n },\n ]\"\n :key=\"group.key\"\n >\n <header\n v-if=\"group.items.length > 0\"\n class=\"tpl:mb-2 tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-[11px] tpl:font-semibold tpl:uppercase tpl:tracking-wide\"\n :class=\"group.tone\"\n >\n <component :is=\"group.icon\" :size=\"12\" :stroke-width=\"2\" />\n {{ group.title }}\n <span class=\"tpl:ml-auto tpl:font-normal tpl:opacity-70\">\n {{ group.items.length }}\n </span>\n </header>\n <ul\n v-if=\"group.items.length > 0\"\n class=\"tpl:m-0 tpl:mb-3 tpl:flex tpl:list-none tpl:flex-col tpl:gap-2 tpl:p-0\"\n >\n <li\n v-for=\"issue in group.items\"\n :key=\"`${issue.ruleId}-${issue.blockId ?? 'template'}`\"\n class=\"tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-3\"\n >\n <p class=\"tpl:m-0 tpl:mb-2 tpl:text-xs tpl:text-[var(--tpl-text)]\">\n {{ issue.message }}\n </p>\n <p\n class=\"tpl:m-0 tpl:mb-2 tpl:font-mono tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ issue.ruleId }}\n </p>\n <div class=\"tpl:flex tpl:gap-1.5\">\n <button\n v-if=\"issue.blockId\"\n type=\"button\"\n class=\"tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-[11px] tpl:font-medium tpl:text-[var(--tpl-text)]\"\n @click=\"jumpTo(issue)\"\n >\n <ArrowRight :size=\"10\" :stroke-width=\"2\" />\n {{ t.issues.jump }}\n </button>\n <button\n v-if=\"issue.fix\"\n type=\"button\"\n class=\"tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-md tpl:bg-[var(--tpl-primary)] tpl:px-2 tpl:py-1 tpl:text-[11px] tpl:font-medium tpl:text-white\"\n :title=\"issue.fix.description\"\n @click=\"applyFix(issue)\"\n >\n <Wrench :size=\"10\" :stroke-width=\"2\" />\n {{ t.issues.fix }}\n </button>\n </div>\n </li>\n </ul>\n </section>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject } from \"vue\";\nimport {\n ListChecks,\n AlertCircle,\n AlertTriangle,\n Info,\n ArrowRight,\n Wrench,\n} from \"@lucide/vue\";\nimport { useI18n } from \"../../composables/useI18n\";\nimport { TEMPLATE_LINT_KEY, EDITOR_KEY } from \"../../keys\";\nimport type { LintIssue } from \"../../composables/useTemplateLint\";\n\nconst { t, format } = useI18n();\nconst lint = inject(TEMPLATE_LINT_KEY, null);\nconst editor = inject(EDITOR_KEY, null);\n\nconst errors = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"error\"),\n);\nconst warnings = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"warning\"),\n);\nconst infos = computed(() =>\n (lint?.issues.value ?? []).filter((i) => i.severity === \"info\"),\n);\n\nconst totalCount = computed(\n () => errors.value.length + warnings.value.length + infos.value.length,\n);\n\nfunction jumpTo(issue: LintIssue): void {\n if (!editor) return;\n if (issue.blockId) editor.selectBlock(issue.blockId);\n}\n\nfunction applyFix(issue: LintIssue): void {\n lint?.applyFix(issue);\n}\n</script>\n\n<template>\n <div class=\"tpl:flex tpl:flex-col tpl:gap-4 tpl:p-4\">\n <header class=\"tpl:flex tpl:items-center tpl:gap-2\">\n <ListChecks :size=\"16\" :stroke-width=\"1.5\" />\n <h3\n class=\"tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]\"\n >\n {{ t.issues.panelTitle }}\n </h3>\n <span\n v-if=\"totalCount > 0\"\n class=\"tpl:ml-auto tpl:rounded-full tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-0.5 tpl:text-[11px] tpl:text-[var(--tpl-text-muted)]\"\n :title=\"format(t.issues.issueCountTooltip, { count: totalCount })\"\n >\n {{ totalCount }}\n </span>\n </header>\n\n <div\n v-if=\"!lint || lint.unavailable.value\"\n class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n <!-- Quality package not available; render nothing visible beyond a hint. -->\n </div>\n\n <div\n v-else-if=\"totalCount === 0\"\n class=\"tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-3 tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ t.issues.emptyState }}\n </div>\n\n <template v-else>\n <section\n v-for=\"group in [\n {\n key: 'errors',\n title: t.issues.groupErrors,\n icon: AlertCircle,\n items: errors,\n tone: 'tpl:text-[var(--tpl-danger)]',\n },\n {\n key: 'warnings',\n title: t.issues.groupWarnings,\n icon: AlertTriangle,\n items: warnings,\n tone: 'tpl:text-[var(--tpl-warning)]',\n },\n {\n key: 'info',\n title: t.issues.groupInfo,\n icon: Info,\n items: infos,\n tone: 'tpl:text-[var(--tpl-text-muted)]',\n },\n ]\"\n :key=\"group.key\"\n >\n <header\n v-if=\"group.items.length > 0\"\n class=\"tpl:mb-2 tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-[11px] tpl:font-semibold tpl:uppercase tpl:tracking-wide\"\n :class=\"group.tone\"\n >\n <component :is=\"group.icon\" :size=\"12\" :stroke-width=\"2\" />\n {{ group.title }}\n <span class=\"tpl:ml-auto tpl:font-normal tpl:opacity-70\">\n {{ group.items.length }}\n </span>\n </header>\n <ul\n v-if=\"group.items.length > 0\"\n class=\"tpl:m-0 tpl:mb-3 tpl:flex tpl:list-none tpl:flex-col tpl:gap-2 tpl:p-0\"\n >\n <li\n v-for=\"issue in group.items\"\n :key=\"`${issue.ruleId}-${issue.blockId ?? 'template'}`\"\n class=\"tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-3\"\n >\n <p class=\"tpl:m-0 tpl:mb-2 tpl:text-xs tpl:text-[var(--tpl-text)]\">\n {{ issue.message }}\n </p>\n <p\n class=\"tpl:m-0 tpl:mb-2 tpl:font-mono tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ issue.ruleId }}\n </p>\n <div class=\"tpl:flex tpl:gap-1.5\">\n <button\n v-if=\"issue.blockId\"\n type=\"button\"\n class=\"tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-[11px] tpl:font-medium tpl:text-[var(--tpl-text)]\"\n @click=\"jumpTo(issue)\"\n >\n <ArrowRight :size=\"10\" :stroke-width=\"2\" />\n {{ t.issues.jump }}\n </button>\n <button\n v-if=\"issue.fix\"\n type=\"button\"\n class=\"tpl:flex tpl:items-center tpl:gap-1 tpl:rounded-md tpl:bg-[var(--tpl-primary)] tpl:px-2 tpl:py-1 tpl:text-[11px] tpl:font-medium tpl:text-white\"\n :title=\"issue.fix.description\"\n @click=\"applyFix(issue)\"\n >\n <Wrench :size=\"10\" :stroke-width=\"2\" />\n {{ t.issues.fix }}\n </button>\n </div>\n </li>\n </ul>\n </section>\n </template>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { M as e, g as t } from "./draggable-D840DIZB.js";
1
+ import { M as e, g as t } from "./draggable-JcMTNF3U.js";
2
2
  import { t as n } from "./_plugin-vue_export-helper-B3ysoDQm.js";
3
3
  //#region src/components/LoadingTrack.vue
4
4
  var r = {}, i = { class: "tpl-loading-track" };
@@ -9,4 +9,4 @@ var o = /*#__PURE__*/ n(r, [["render", a], ["__scopeId", "data-v-1ed538ec"]]);
9
9
  //#endregion
10
10
  export { o as t };
11
11
 
12
- //# sourceMappingURL=LoadingTrack-D-CW2tUa.js.map
12
+ //# sourceMappingURL=LoadingTrack-G2tuXqCJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LoadingTrack-D-CW2tUa.js","names":[],"sources":["../../../src/components/LoadingTrack.vue"],"sourcesContent":["<template>\n <div class=\"tpl-loading-track\"></div>\n</template>\n\n<style scoped>\n.tpl-loading-track {\n height: 3px;\n width: 100%;\n border-radius: 9999px;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n color-mix(in srgb, var(--tpl-primary) 10%, transparent) 15%,\n color-mix(in srgb, var(--tpl-primary) 30%, transparent) 30%,\n var(--tpl-primary) 50%,\n color-mix(in srgb, var(--tpl-primary) 30%, transparent) 70%,\n color-mix(in srgb, var(--tpl-primary) 10%, transparent) 85%,\n transparent 100%\n );\n background-size: 200% 100%;\n animation: tpl-loading-flow 3s ease-in-out infinite;\n}\n\n@keyframes tpl-loading-flow {\n 0% {\n background-position: 100% 0;\n }\n 100% {\n background-position: -100% 0;\n }\n}\n</style>\n"],"mappings":";;;kBACO,OAAM,oBAAmB;;aAA9B,EAAqC,OAArC,CAAqC"}
1
+ {"version":3,"file":"LoadingTrack-G2tuXqCJ.js","names":[],"sources":["../../../src/components/LoadingTrack.vue"],"sourcesContent":["<template>\n <div class=\"tpl-loading-track\"></div>\n</template>\n\n<style scoped>\n.tpl-loading-track {\n height: 3px;\n width: 100%;\n border-radius: 9999px;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n color-mix(in srgb, var(--tpl-primary) 10%, transparent) 15%,\n color-mix(in srgb, var(--tpl-primary) 30%, transparent) 30%,\n var(--tpl-primary) 50%,\n color-mix(in srgb, var(--tpl-primary) 30%, transparent) 70%,\n color-mix(in srgb, var(--tpl-primary) 10%, transparent) 85%,\n transparent 100%\n );\n background-size: 200% 100%;\n animation: tpl-loading-flow 3s ease-in-out infinite;\n}\n\n@keyframes tpl-loading-flow {\n 0% {\n background-position: 100% 0;\n }\n 100% {\n background-position: -100% 0;\n }\n}\n</style>\n"],"mappings":";;;YACO,IAAA,EAAA,OAAM,oBAAmB;;CAA9B,OAAA,EAAA,GAAA,EAAqC,OAArC,CAAqC"}
@@ -1,8 +1,8 @@
1
- import { M as e, P as t, T as n, ct as r, f as i, g as a, h as o, it as s, m as c, p as l, st as u, u as d, x as f } from "./draggable-D840DIZB.js";
2
- import { l as p } from "./src-BCJna-6p.js";
3
- import { T as m } from "./keys-B5uoP9P7.js";
4
- import { t as h } from "./useI18n-graz19nI.js";
5
- import { $ as g, D as _, T as v, p as y } from "./icons-Cqxvwgz7.js";
1
+ import { M as e, P as t, T as n, ct as r, f as i, g as a, h as o, it as s, m as c, p as l, st as u, u as d, x as f } from "./draggable-JcMTNF3U.js";
2
+ import { u as p } from "./src-CZjSXPYq.js";
3
+ import { E as m } from "./keys-BxPCfHBH.js";
4
+ import { t as h } from "./useI18n-DniEFeIl.js";
5
+ import { $ as g, E as _, T as v, p as y } from "./icons-Cp4ZIJw-.js";
6
6
  //#region src/components/ViewportToggle.vue?vue&type=script&setup=true&lang.ts
7
7
  var b = ["aria-label"], x = [
8
8
  "aria-checked",
@@ -124,4 +124,4 @@ var b = ["aria-label"], x = [
124
124
  //#endregion
125
125
  export { S as n, T as t };
126
126
 
127
- //# sourceMappingURL=MergeTagModeToggle-DmtR300G.js.map
127
+ //# sourceMappingURL=MergeTagModeToggle-CWuVC3MU.js.map