@templatical/editor 0.39.0 → 0.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/README.md +2 -4
  2. package/dist/{AiChatSidebar-jVlXXND3.js → AiChatSidebar-pOxCZWz9.js} +14 -14
  3. package/dist/{AiFeatureMenu-C1HCntyQ.js → AiFeatureMenu-Bljk6Qjv.js} +7 -7
  4. package/dist/{BlockIssueBadge-JhNgcUmZ.js → BlockIssueBadge-D5oGxOQP.js} +5 -5
  5. package/dist/{BlockPreviewCanvas-C_rA5LJN.js → BlockPreviewCanvas-DXGjUECG.js} +27 -27
  6. package/dist/{CloudHeaderExtras-DvYyNsPB.js → CloudHeaderExtras-DaocwNmy.js} +5 -5
  7. package/dist/{CloudPanels-CDPhPVdd.js → CloudPanels-CyZAnSJY.js} +7 -7
  8. package/dist/{CollaboratorBar-Co9UPoB0.js → CollaboratorBar-C7Zca3g1.js} +4 -4
  9. package/dist/{CommentsPanel-CRcVN9Ri.js → CommentsPanel-CNOb7YCm.js} +2 -2
  10. package/dist/{CommentsSidebar-gDU977br.js → CommentsSidebar-VmwjU9va.js} +14 -14
  11. package/dist/{CountdownBlock-CEzrfe5R.js → CountdownBlock-DSvbf3qU.js} +3 -3
  12. package/dist/{CountdownToolbar-B00zhkNJ.js → CountdownToolbar-C2kfS6Oy.js} +31 -30
  13. package/dist/{DesignReferenceSidebar-DedivZZl.js → DesignReferenceSidebar-QC4gEUWp.js} +11 -11
  14. package/dist/{IssuesPanel-C-PjdmAV.js → IssuesPanel-DL2Xr14_.js} +8 -8
  15. package/dist/{LoadingTrack-BlTL4zFv.js → LoadingTrack-C2jKCU2d.js} +1 -1
  16. package/dist/LogicTagInsertButton-D8IwH-9Z.js +1071 -0
  17. package/dist/{MediaPanels-BpQNY8YX.js → MediaPanels-Cc4UkfG1.js} +2 -2
  18. package/dist/MergeTagInput-QI-5KG2R.js +81 -0
  19. package/dist/{MergeTagModeToggle-DGuzSAdX.js → MergeTagModeToggle-D793Bj_E.js} +14 -55
  20. package/dist/{ParagraphEditor-jMKLLTa8.js → ParagraphEditor-DkkPSexG.js} +65 -66
  21. package/dist/{RestoreVersionDialog-DG1jUdBM.js → RestoreVersionDialog-BgueZnZr.js} +5 -5
  22. package/dist/{RichTextEditorContent-JrNEg0kv.js → RichTextEditorContent-BC5UTVnb.js} +11 -11
  23. package/dist/{SaveBlockDialog-C0KC-OKs.js → SaveBlockDialog-BuTuVlLr.js} +12 -11
  24. package/dist/{SavedBlocksBrowserModal-zyOiRgWZ.js → SavedBlocksBrowserModal-Srhix8BB.js} +17 -16
  25. package/dist/{SavedBlocksPanels-epMd799w.js → SavedBlocksPanels-B2iScCS-.js} +2 -2
  26. package/dist/{SavedBlocksPickBar-CJqqQ3jd.js → SavedBlocksPickBar-cI7bDQQi.js} +4 -4
  27. package/dist/{TemplateScoringPanel-m2FOeaai.js → TemplateScoringPanel-C2Rdlyn6.js} +16 -16
  28. package/dist/TemplateSettings-C_5leDdF.js +245 -0
  29. package/dist/{TestEmailModal-D58kYkMV.js → TestEmailModal-DJ5q_u4N.js} +10 -10
  30. package/dist/{TestEmailPanel-BmFVBIQt.js → TestEmailPanel-CP24UGst.js} +2 -2
  31. package/dist/{TitleEditor-C4BGPXnf.js → TitleEditor-QBBOXtxx.js} +15 -15
  32. package/dist/ToggleSwitch-JvQ_CmI1.js +102 -0
  33. package/dist/Toolbar-COD2TW20.js +2426 -0
  34. package/dist/{TplModal-BIDJw4Kj.js → TplModal-C8xGjC1l.js} +5 -5
  35. package/dist/{VersionHistoryMenu-dt_aZQfh.js → VersionHistoryMenu-BVQityes.js} +10 -10
  36. package/dist/{VersionHistoryPanels-B_5SBRrr.js → VersionHistoryPanels-BrK6na4A.js} +2 -2
  37. package/dist/{VersionPreviewBanner-DttvOkwd.js → VersionPreviewBanner-BaMSgA1O.js} +3 -3
  38. package/dist/{blockTypeIcons-CzTizYmK.js → blockTypeIcons-CdXugKyV.js} +16 -37
  39. package/dist/bundle-stats.json +8 -8
  40. package/dist/cdn/chunks/{AiChatSidebar-DeZl9Tk0.js → AiChatSidebar-CjSEoK4x.js} +8 -8
  41. package/dist/cdn/chunks/{AiChatSidebar-DeZl9Tk0.js.map → AiChatSidebar-CjSEoK4x.js.map} +1 -1
  42. package/dist/cdn/chunks/{AiFeatureMenu-Bv8jMu9p.js → AiFeatureMenu-l0K5TOSn.js} +6 -6
  43. package/dist/cdn/chunks/{AiFeatureMenu-Bv8jMu9p.js.map → AiFeatureMenu-l0K5TOSn.js.map} +1 -1
  44. package/dist/cdn/chunks/{BlockIssueBadge-B6PpoOPv.js → BlockIssueBadge-9hHpaXb9.js} +5 -5
  45. package/dist/cdn/chunks/{BlockIssueBadge-B6PpoOPv.js.map → BlockIssueBadge-9hHpaXb9.js.map} +1 -1
  46. package/dist/cdn/chunks/{BlockPreviewCanvas-DfEtDosD.js → BlockPreviewCanvas-lQrAdgG3.js} +30 -30
  47. package/dist/cdn/chunks/{BlockPreviewCanvas-DfEtDosD.js.map → BlockPreviewCanvas-lQrAdgG3.js.map} +1 -1
  48. package/dist/cdn/chunks/{CloudHeaderExtras-Hk98ub-C.js → CloudHeaderExtras-CXNe7Q-4.js} +5 -5
  49. package/dist/cdn/chunks/{CloudHeaderExtras-Hk98ub-C.js.map → CloudHeaderExtras-CXNe7Q-4.js.map} +1 -1
  50. package/dist/cdn/chunks/{CloudPanels-Ba3GLmvF.js → CloudPanels-bHhh9AUA.js} +6 -6
  51. package/dist/cdn/chunks/{CloudPanels-Ba3GLmvF.js.map → CloudPanels-bHhh9AUA.js.map} +1 -1
  52. package/dist/cdn/chunks/{CollaboratorBar-D2dCQ9gg.js → CollaboratorBar-DgqcaGGI.js} +5 -5
  53. package/dist/cdn/chunks/{CollaboratorBar-D2dCQ9gg.js.map → CollaboratorBar-DgqcaGGI.js.map} +1 -1
  54. package/dist/cdn/chunks/{CommentsPanel-CV2HveQk.js → CommentsPanel-Cy4TlTHC.js} +3 -3
  55. package/dist/cdn/chunks/{CommentsPanel-CV2HveQk.js.map → CommentsPanel-Cy4TlTHC.js.map} +1 -1
  56. package/dist/cdn/chunks/{CommentsSidebar-Dok_vaRc.js → CommentsSidebar-C7oAP3Mx.js} +5 -5
  57. package/dist/cdn/chunks/{CommentsSidebar-Dok_vaRc.js.map → CommentsSidebar-C7oAP3Mx.js.map} +1 -1
  58. package/dist/cdn/chunks/{CountdownBlock-DGDl3ota.js → CountdownBlock-DdC8Lg5F.js} +4 -4
  59. package/dist/cdn/chunks/{CountdownBlock-DGDl3ota.js.map → CountdownBlock-DdC8Lg5F.js.map} +1 -1
  60. package/dist/cdn/chunks/{CountdownToolbar-B9Rin64t.js → CountdownToolbar-CN9h4nlC.js} +22 -21
  61. package/dist/cdn/chunks/{CountdownToolbar-B9Rin64t.js.map → CountdownToolbar-CN9h4nlC.js.map} +1 -1
  62. package/dist/cdn/chunks/{DesignReferenceSidebar-eCuTFak2.js → DesignReferenceSidebar-Bjo0M-AY.js} +7 -7
  63. package/dist/cdn/chunks/{DesignReferenceSidebar-eCuTFak2.js.map → DesignReferenceSidebar-Bjo0M-AY.js.map} +1 -1
  64. package/dist/cdn/chunks/{IssuesPanel-CP7FEzw7.js → IssuesPanel-DdFk-Blf.js} +6 -6
  65. package/dist/cdn/chunks/{IssuesPanel-CP7FEzw7.js.map → IssuesPanel-DdFk-Blf.js.map} +1 -1
  66. package/dist/cdn/chunks/{LoadingTrack-Cm3TDKb3.js → LoadingTrack-Ba5xh5HD.js} +2 -2
  67. package/dist/cdn/chunks/{LoadingTrack-Cm3TDKb3.js.map → LoadingTrack-Ba5xh5HD.js.map} +1 -1
  68. package/dist/cdn/chunks/LogicTagInsertButton-DpyPozop.js +1035 -0
  69. package/dist/cdn/chunks/LogicTagInsertButton-DpyPozop.js.map +1 -0
  70. package/dist/cdn/chunks/{MediaPanels-TYrKKHX5.js → MediaPanels-kX9AZQ7K.js} +3 -3
  71. package/dist/cdn/chunks/{MediaPanels-TYrKKHX5.js.map → MediaPanels-kX9AZQ7K.js.map} +1 -1
  72. package/dist/cdn/chunks/MergeTagInput-ERJr7bP_.js +83 -0
  73. package/dist/cdn/chunks/MergeTagInput-ERJr7bP_.js.map +1 -0
  74. package/dist/cdn/chunks/{MergeTagModeToggle-QGTUIWWo.js → MergeTagModeToggle-n3nvSNeQ.js} +5 -5
  75. package/dist/cdn/chunks/{MergeTagModeToggle-QGTUIWWo.js.map → MergeTagModeToggle-n3nvSNeQ.js.map} +1 -1
  76. package/dist/cdn/chunks/{ParagraphEditor-D1tsPv4v.js → ParagraphEditor-DO4RzP8l.js} +40 -40
  77. package/dist/cdn/chunks/{ParagraphEditor-D1tsPv4v.js.map → ParagraphEditor-DO4RzP8l.js.map} +1 -1
  78. package/dist/cdn/chunks/{RestoreVersionDialog-BeCxNPLS.js → RestoreVersionDialog-CzZ_sFnz.js} +5 -5
  79. package/dist/cdn/chunks/{RestoreVersionDialog-BeCxNPLS.js.map → RestoreVersionDialog-CzZ_sFnz.js.map} +1 -1
  80. package/dist/cdn/chunks/{RichTextEditorContent-BBxzACFQ.js → RichTextEditorContent-Ch5zeyZ7.js} +8 -8
  81. package/dist/cdn/chunks/{RichTextEditorContent-BBxzACFQ.js.map → RichTextEditorContent-Ch5zeyZ7.js.map} +1 -1
  82. package/dist/cdn/chunks/{SaveBlockDialog-CLgh_g7H.js → SaveBlockDialog-LgxYrXyx.js} +10 -9
  83. package/dist/cdn/chunks/{SaveBlockDialog-CLgh_g7H.js.map → SaveBlockDialog-LgxYrXyx.js.map} +1 -1
  84. package/dist/cdn/chunks/{SavedBlocksBrowserModal-B4TcUJJe.js → SavedBlocksBrowserModal-CdeSsTpb.js} +9 -9
  85. package/dist/cdn/chunks/{SavedBlocksBrowserModal-B4TcUJJe.js.map → SavedBlocksBrowserModal-CdeSsTpb.js.map} +1 -1
  86. package/dist/cdn/chunks/{SavedBlocksPanels-CaBsHoRC.js → SavedBlocksPanels-B5hakNJj.js} +3 -3
  87. package/dist/cdn/chunks/{SavedBlocksPanels-CaBsHoRC.js.map → SavedBlocksPanels-B5hakNJj.js.map} +1 -1
  88. package/dist/cdn/chunks/{SavedBlocksPickBar-iG35XCDx.js → SavedBlocksPickBar-Cl6PLwwV.js} +5 -5
  89. package/dist/cdn/chunks/{SavedBlocksPickBar-iG35XCDx.js.map → SavedBlocksPickBar-Cl6PLwwV.js.map} +1 -1
  90. package/dist/cdn/chunks/{TemplateScoringPanel-DuQJBykq.js → TemplateScoringPanel--JxR6CsQ.js} +6 -6
  91. package/dist/cdn/chunks/{TemplateScoringPanel-DuQJBykq.js.map → TemplateScoringPanel--JxR6CsQ.js.map} +1 -1
  92. package/dist/cdn/chunks/TemplateSettings-DjXiiiNr.js +207 -0
  93. package/dist/cdn/chunks/TemplateSettings-DjXiiiNr.js.map +1 -0
  94. package/dist/cdn/chunks/{TestEmailModal-D6Woss3r.js → TestEmailModal-BAuDxJtD.js} +9 -9
  95. package/dist/cdn/chunks/{TestEmailModal-D6Woss3r.js.map → TestEmailModal-BAuDxJtD.js.map} +1 -1
  96. package/dist/cdn/chunks/{TestEmailPanel-CWQFB7J3.js → TestEmailPanel-GUGZisLp.js} +3 -3
  97. package/dist/cdn/chunks/{TestEmailPanel-CWQFB7J3.js.map → TestEmailPanel-GUGZisLp.js.map} +1 -1
  98. package/dist/cdn/chunks/{TitleEditor-CbY1tgSl.js → TitleEditor-uKu33Nwr.js} +12 -12
  99. package/dist/cdn/chunks/{TitleEditor-CbY1tgSl.js.map → TitleEditor-uKu33Nwr.js.map} +1 -1
  100. package/dist/cdn/chunks/ToggleSwitch-CDy8OfcB.js +104 -0
  101. package/dist/cdn/chunks/ToggleSwitch-CDy8OfcB.js.map +1 -0
  102. package/dist/cdn/chunks/Toolbar-dxDYwN5E.js +2385 -0
  103. package/dist/cdn/chunks/Toolbar-dxDYwN5E.js.map +1 -0
  104. package/dist/cdn/chunks/{TplModal-CGpp-d_r.js → TplModal-DuwS2ifK.js} +5 -5
  105. package/dist/cdn/chunks/{TplModal-CGpp-d_r.js.map → TplModal-DuwS2ifK.js.map} +1 -1
  106. package/dist/cdn/chunks/{VersionHistoryMenu-ByVJXDbK.js → VersionHistoryMenu-Dij1pTEb.js} +6 -6
  107. package/dist/cdn/chunks/{VersionHistoryMenu-ByVJXDbK.js.map → VersionHistoryMenu-Dij1pTEb.js.map} +1 -1
  108. package/dist/cdn/chunks/{VersionHistoryPanels-CQJ5OggF.js → VersionHistoryPanels-GeR6MStB.js} +3 -3
  109. package/dist/cdn/chunks/{VersionHistoryPanels-CQJ5OggF.js.map → VersionHistoryPanels-GeR6MStB.js.map} +1 -1
  110. package/dist/cdn/chunks/{VersionPreviewBanner-G4lLbfr8.js → VersionPreviewBanner-Df3FVlig.js} +4 -4
  111. package/dist/cdn/chunks/{VersionPreviewBanner-G4lLbfr8.js.map → VersionPreviewBanner-Df3FVlig.js.map} +1 -1
  112. package/dist/cdn/chunks/{blockTypeIcons-CQY-vxdM.js → blockTypeIcons-raBjStuv.js} +2 -2
  113. package/dist/cdn/chunks/{blockTypeIcons-CQY-vxdM.js.map → blockTypeIcons-raBjStuv.js.map} +1 -1
  114. package/dist/cdn/chunks/{cloud-BLgCKP7Z.js → cloud-eaXyxZ8l.js} +2 -2
  115. package/dist/cdn/chunks/{cloud-BLgCKP7Z.js.map → cloud-eaXyxZ8l.js.map} +1 -1
  116. package/dist/cdn/chunks/{createCloudRuntime-ClvtMBF1.js → createCloudRuntime-D5bXzcTe.js} +6 -6
  117. package/dist/cdn/chunks/{createCloudRuntime-ClvtMBF1.js.map → createCloudRuntime-D5bXzcTe.js.map} +1 -1
  118. package/dist/cdn/chunks/{dist-BW6Y49zE.js → dist-BRZhN8qJ.js} +4 -4
  119. package/dist/cdn/chunks/dist-BRZhN8qJ.js.map +1 -0
  120. package/dist/cdn/chunks/{dist-CAFTQ6Y2.js → dist-CXB2_kBa.js} +27 -22
  121. package/dist/cdn/chunks/dist-CXB2_kBa.js.map +1 -0
  122. package/dist/cdn/chunks/{draggable-kbOhCgnk.js → draggable-IB4x6w2O.js} +1477 -1470
  123. package/dist/cdn/chunks/draggable-IB4x6w2O.js.map +1 -0
  124. package/dist/cdn/chunks/{editor-modal-B6IdQWlf.js → editor-modal-C_xYN_66.js} +7 -7
  125. package/dist/cdn/chunks/{editor-modal-B6IdQWlf.js.map → editor-modal-C_xYN_66.js.map} +1 -1
  126. package/dist/cdn/chunks/en-BwfjKb4M.js +2 -0
  127. package/dist/cdn/chunks/{extensions-D2YIhF7u.js → extensions-Bhu8UEE5.js} +105 -45
  128. package/dist/cdn/chunks/extensions-Bhu8UEE5.js.map +1 -0
  129. package/dist/cdn/chunks/{icons-DdrAicM2.js → icons-BKkJ-5xF.js} +43 -43
  130. package/dist/cdn/chunks/{icons-DdrAicM2.js.map → icons-BKkJ-5xF.js.map} +1 -1
  131. package/dist/cdn/chunks/{keys-DXYJTLZF.js → keys-dJbD1QPs.js} +2 -2
  132. package/dist/cdn/chunks/{keys-DXYJTLZF.js.map → keys-dJbD1QPs.js.map} +1 -1
  133. package/dist/cdn/chunks/socialIcons-9VrG8X3m.js +1054 -0
  134. package/dist/cdn/chunks/socialIcons-9VrG8X3m.js.map +1 -0
  135. package/dist/cdn/chunks/{src-fn7uy1FD.js → src-CZ-W8YBa.js} +3 -3
  136. package/dist/cdn/chunks/{src-fn7uy1FD.js.map → src-CZ-W8YBa.js.map} +1 -1
  137. package/dist/cdn/chunks/templateSettingsFields-YCFVBVYh.js +36 -0
  138. package/dist/cdn/chunks/templateSettingsFields-YCFVBVYh.js.map +1 -0
  139. package/dist/cdn/chunks/{tiptap-Epe8m3Vo.js → tiptap-DhLuKyDc.js} +2776 -2773
  140. package/dist/cdn/chunks/tiptap-DhLuKyDc.js.map +1 -0
  141. package/dist/cdn/chunks/{useAliveFlag-CT9gjvO_.js → useAliveFlag-DAlQLbM2.js} +2 -2
  142. package/dist/cdn/chunks/{useAliveFlag-CT9gjvO_.js.map → useAliveFlag-DAlQLbM2.js.map} +1 -1
  143. package/dist/cdn/chunks/{useCloudI18n-OezCj0cx.js → useCloudI18n-C09JcFS0.js} +3 -3
  144. package/dist/cdn/chunks/{useCloudI18n-OezCj0cx.js.map → useCloudI18n-C09JcFS0.js.map} +1 -1
  145. package/dist/cdn/chunks/useEditorCore-BHmIp1hW.js +2592 -0
  146. package/dist/cdn/chunks/useEditorCore-BHmIp1hW.js.map +1 -0
  147. package/dist/cdn/chunks/useEditorRoot-DFx2fXJP.js +10 -0
  148. package/dist/cdn/chunks/{useEditorRoot-ByHPMqYT.js.map → useEditorRoot-DFx2fXJP.js.map} +1 -1
  149. package/dist/cdn/chunks/{useI18n-BhE7ndNr.js → useI18n-DTZ9sIcv.js} +3 -3
  150. package/dist/cdn/chunks/{useI18n-BhE7ndNr.js.map → useI18n-DTZ9sIcv.js.map} +1 -1
  151. package/dist/cdn/chunks/useLogicTag-E2V0Xdcb.js +38 -0
  152. package/dist/cdn/chunks/useLogicTag-E2V0Xdcb.js.map +1 -0
  153. package/dist/cdn/chunks/{useMergeTag-DE2mpy1w.js → useMergeTag-BE8oDoha.js} +3 -3
  154. package/dist/cdn/chunks/{useMergeTag-DE2mpy1w.js.map → useMergeTag-BE8oDoha.js.map} +1 -1
  155. package/dist/cdn/chunks/{usePopoverPosition-BPL891uG.js → usePopoverPosition-gB9q-ql7.js} +3 -3
  156. package/dist/cdn/chunks/{usePopoverPosition-BPL891uG.js.map → usePopoverPosition-gB9q-ql7.js.map} +1 -1
  157. package/dist/cdn/chunks/{useScrollToBlock-DwF4pVur.js → useScrollToBlock-CtTXwmiU.js} +3 -3
  158. package/dist/cdn/chunks/{useScrollToBlock-DwF4pVur.js.map → useScrollToBlock-CtTXwmiU.js.map} +1 -1
  159. package/dist/cdn/editor.css +1 -1
  160. package/dist/cdn/editor.js +809 -3337
  161. package/dist/cdn/editor.js.map +1 -1
  162. package/dist/{check-9xX6RVHz.js → check-eqb2JhqU.js} +1 -1
  163. package/dist/{chevron-down-J5hFJ6TL.js → chevron-down-Dkr-7Ywl.js} +1 -1
  164. package/dist/{chevron-right-BJuo5PQ-.js → chevron-right-Bge4XF_B.js} +1 -1
  165. package/dist/{chevron-up-Qfi5k52_.js → chevron-up-CQAyl0kC.js} +1 -1
  166. package/dist/{circle-alert-BiArYmkB.js → circle-alert-CYgTHKWr.js} +1 -1
  167. package/dist/{clock-BkYJZ7Y0.js → clock-BgSJZJP5.js} +1 -1
  168. package/dist/{cloud-DdidMW6f.js → cloud-C9xWZXhg.js} +1 -1
  169. package/dist/{copy-BRLUNHwF.js → copy-mw6PVnOJ.js} +1 -1
  170. package/dist/{createCloudRuntime-CNFXaTNQ.js → createCloudRuntime-BGd5--Bq.js} +5 -5
  171. package/dist/{createLucideIcon-CDDkF1Tm.js → createLucideIcon-BxY5yz5u.js} +6 -6
  172. package/dist/{dist-D8i1ixHK.js → dist-8VFzbeu9.js} +3 -3
  173. package/dist/{dist-DBirAJIs.js → dist-BDuPwOyn.js} +26 -21
  174. package/dist/{dist-CtF9STPS.js → dist-BJM3eFyT.js} +1 -1
  175. package/dist/{dist-DkcA6epL.js → dist-BdHF7nyq.js} +3 -3
  176. package/dist/{dist-ByT5fgKq.js → dist-Bl4rxpX9.js} +1 -1
  177. package/dist/{dist-BVqAYoRB.js → dist-BmsLcnrO.js} +4 -4
  178. package/dist/{dist-CtMXAH7a.js → dist-BxVnMgXZ.js} +1 -1
  179. package/dist/{dist-DC-3T0ED.js → dist-CQSVro7b.js} +1 -1
  180. package/dist/{dist-f7HXo6j6.js → dist-DQbOebGW.js} +1 -1
  181. package/dist/{dist-DL9334yz.js → dist-DerFNpDY.js} +3 -3
  182. package/dist/{dist-D08oVYhr.js → dist-Djmzp6wi.js} +1 -1
  183. package/dist/{dist-D7WY8VPq.js → dist-DyrEOKEJ.js} +1 -1
  184. package/dist/{dist-DzdeVn-W.js → dist-EDkj3Ub1.js} +1 -1
  185. package/dist/{dist-C1tsW_99.js → dist-wyXxj3R1.js} +1 -1
  186. package/dist/{editor-modal-uAEB6xKz.js → editor-modal-OPhP71YO.js} +20 -20
  187. package/dist/en-CjNopehs.js +2 -0
  188. package/dist/extensions-DRN-elXT.js +1645 -0
  189. package/dist/{eye-DwhBOaV8.js → eye-DphkRtAD.js} +1 -1
  190. package/dist/{image-up-CiyQNZBt.js → image-up-Qi2BXD7T.js} +1 -1
  191. package/dist/{info-D6A1qEiF.js → info-VSyAs02q.js} +1 -1
  192. package/dist/{keys-DD1rl72F.js → keys-BdoSgsz9.js} +1 -1
  193. package/dist/{link-tKGmYWsB.js → link-CNuozGqD.js} +1 -1
  194. package/dist/{list-DjZQRpeI.js → list-BA0I5Wmu.js} +1 -1
  195. package/dist/{loader-circle-D9ZL3Sv0.js → loader-circle-z5eeqasv.js} +1 -1
  196. package/dist/{message-circle-KTHxCcpB.js → message-circle-BsQ9hEup.js} +1 -1
  197. package/dist/package-OkXfuRoO.js +25 -0
  198. package/dist/{pencil-Bq-nbQ7F.js → pencil-DFVFA7Dj.js} +1 -1
  199. package/dist/{plus-CRMnR4IG.js → plus-D8bkVjZ7.js} +1 -1
  200. package/dist/{refresh-cw-D7bYS5tm.js → refresh-cw-DPB7YFuz.js} +1 -1
  201. package/dist/{runtime-dom.esm-bundler-PnoZU512.js → runtime-dom.esm-bundler-BGbPz4-g.js} +2 -2
  202. package/dist/{search-DUo0YwPz.js → search-C-dCgqIa.js} +1 -1
  203. package/dist/{send-DaVMQphu.js → send-Cm2fy2zm.js} +1 -1
  204. package/dist/{shield-check-DxaaurL9.js → shield-check-COgBYFDF.js} +1 -1
  205. package/dist/smartphone-v0u_MOEV.js +46 -0
  206. package/dist/socialIcons-DkGcpEwC.js +1130 -0
  207. package/dist/{sparkles-D6T6k30e.js → sparkles-Ds0RF8Iu.js} +1 -1
  208. package/dist/style.css +1 -1
  209. package/dist/templateSettingsFields-YCFVBVYh.js +34 -0
  210. package/dist/templatical-editor.js +895 -3498
  211. package/dist/{text-align-start-vreFpmCX.js → text-align-start-DiavaIm6.js} +1 -1
  212. package/dist/{trash-DBv8MGY6.js → trash-DnOkfu2V.js} +1 -1
  213. package/dist/{triangle-alert-CmNS2LLv.js → triangle-alert-DGLAyXnh.js} +1 -1
  214. package/dist/{upload-DDB9Fs0P.js → upload-BBDme2cy.js} +1 -1
  215. package/dist/{useAliveFlag-oyByIcjy.js → useAliveFlag-BkKyhkwZ.js} +1 -1
  216. package/dist/{useCloudI18n-C1wuXik6.js → useCloudI18n-D1iedlP3.js} +2 -2
  217. package/dist/{useEditorCore-jfwgLThK.js → useEditorCore-C5APBjjV.js} +1140 -2325
  218. package/dist/{useEditorRoot-eVv4doqZ.js → useEditorRoot-BOxn5EfP.js} +2 -2
  219. package/dist/{useI18n-VOtdfENx.js → useI18n-Ds_-druD.js} +2 -2
  220. package/dist/useLogicTag-DoHfc08B.js +36 -0
  221. package/dist/{useMergeTag-CQM9pFca.js → useMergeTag-DXyum3kG.js} +2 -2
  222. package/dist/{usePopoverPosition-gZjRywai.js → usePopoverPosition-Du-Ah8E9.js} +2 -2
  223. package/dist/{useScrollToBlock-C0Ehnyl4.js → useScrollToBlock-DXQYPCnJ.js} +3 -3
  224. package/dist/{vue.runtime.esm-bundler-DShF3P6k.js → vue.runtime.esm-bundler-CyqhBwpY.js} +1133 -1126
  225. package/dist/{x-B7sgO_z8.js → x-3BHV3Q6K.js} +1 -1
  226. package/package.json +14 -14
  227. package/dist/ColorPicker-BTtN94te.js +0 -501
  228. package/dist/FieldRow-C8nOknr_.js +0 -128
  229. package/dist/MergeTagInput-Cw1RoMly.js +0 -509
  230. package/dist/MergeTagSuggestion-BXO3UIXW.js +0 -1329
  231. package/dist/cdn/chunks/ColorPicker-BaonTCAQ.js +0 -502
  232. package/dist/cdn/chunks/ColorPicker-BaonTCAQ.js.map +0 -1
  233. package/dist/cdn/chunks/FieldRow-D9OJhYeb.js +0 -130
  234. package/dist/cdn/chunks/FieldRow-D9OJhYeb.js.map +0 -1
  235. package/dist/cdn/chunks/MergeTagInput-CSIThqkz.js +0 -470
  236. package/dist/cdn/chunks/MergeTagInput-CSIThqkz.js.map +0 -1
  237. package/dist/cdn/chunks/MergeTagSuggestion-CY6WK8Eb.js +0 -215
  238. package/dist/cdn/chunks/MergeTagSuggestion-CY6WK8Eb.js.map +0 -1
  239. package/dist/cdn/chunks/dist-BW6Y49zE.js.map +0 -1
  240. package/dist/cdn/chunks/dist-CAFTQ6Y2.js.map +0 -1
  241. package/dist/cdn/chunks/draggable-kbOhCgnk.js.map +0 -1
  242. package/dist/cdn/chunks/en-DjunooBz.js +0 -2
  243. package/dist/cdn/chunks/extensions-D2YIhF7u.js.map +0 -1
  244. package/dist/cdn/chunks/tiptap-Epe8m3Vo.js.map +0 -1
  245. package/dist/cdn/chunks/useEditorCore-06PtcUi1.js +0 -3698
  246. package/dist/cdn/chunks/useEditorCore-06PtcUi1.js.map +0 -1
  247. package/dist/cdn/chunks/useEditorRoot-ByHPMqYT.js +0 -10
  248. package/dist/en-CQWkDCpm.js +0 -2
  249. package/dist/extensions-CcGj7OfS.js +0 -470
@@ -1,11 +1,11 @@
1
- import { B as e, P as t, Q as n, f as r } from "./draggable-kbOhCgnk.js";
2
- import { _ as i } from "./dist-BW6Y49zE.js";
3
- import { t as a } from "./dist-CAFTQ6Y2.js";
4
- import { U as o, i as s, t as c, u as l } from "./keys-DXYJTLZF.js";
1
+ import { B as e, P as t, Q as n, f as r } from "./draggable-IB4x6w2O.js";
2
+ import { _ as i } from "./dist-BRZhN8qJ.js";
3
+ import { t as a } from "./dist-CXB2_kBa.js";
4
+ import { U as o, i as s, t as c, u as l } from "./keys-dJbD1QPs.js";
5
5
  import { t as u } from "./timeouts-DHPZQ0G3.js";
6
6
  import { t as d } from "./logger-ByvdoAwq.js";
7
7
  import { t as f } from "./preRenderCustomBlocks-Bdpiiw4A.js";
8
- import { C as p, S as m, a as h, c as g, d as _, f as ee, g as te, h as ne, i as re, l as ie, m as ae, n as oe, o as se, p as ce, r as le, s as v, t as y, u as b, v as x, x as ue, y as de } from "./cloud-BLgCKP7Z.js";
8
+ import { C as p, S as m, a as h, c as g, d as _, f as ee, g as te, h as ne, i as re, l as ie, m as ae, n as oe, o as se, p as ce, r as le, s as v, t as y, u as b, v as x, x as ue, y as de } from "./cloud-eaXyxZ8l.js";
9
9
  //#region src/cloud/composables/useCloudFeatureFlags.ts
10
10
  function fe(e) {
11
11
  let { planConfigInstance: t, aiConfig: n, getTemplateId: i } = e;
@@ -382,4 +382,4 @@ async function C(i) {
382
382
  //#endregion
383
383
  export { C as bootstrapCloud };
384
384
 
385
- //# sourceMappingURL=createCloudRuntime-ClvtMBF1.js.map
385
+ //# sourceMappingURL=createCloudRuntime-D5bXzcTe.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createCloudRuntime-ClvtMBF1.js","names":[],"sources":["../../../src/cloud/composables/useCloudFeatureFlags.ts","../../../src/cloud/composables/useCloudPanelState.ts","../../../src/cloud/composables/useCloudSaveGate.ts","../../../src/cloud/composables/useCollabUndoWarning.ts","../../../src/cloud/collectSavedBlockIds.ts","../../../src/cloud/createCloudRuntime.ts"],"sourcesContent":["import { computed, type ComputedRef } from \"vue\";\nimport type {\n UsePlanConfigReturn,\n UseAiConfigReturn,\n} from \"@templatical/core/cloud\";\n\nexport interface UseCloudFeatureFlagsOptions {\n planConfigInstance: UsePlanConfigReturn;\n aiConfig: UseAiConfigReturn;\n /** The loaded template's id, or `null` before one exists. */\n getTemplateId: () => string | null;\n}\n\nexport interface UseCloudFeatureFlagsReturn {\n canUseAiGeneration: ComputedRef<boolean>;\n canSendTestEmail: ComputedRef<boolean>;\n hasTemplateSaved: ComputedRef<boolean>;\n templateLimit: ComputedRef<number | null>;\n templateCount: ComputedRef<number>;\n}\n\n/**\n * Every entitlement check Cloud makes, in one place.\n *\n * The containment rule this exists for: entitlement checks go through here,\n * never inline in a component and never across a package boundary. With five\n * plan features left there is little excuse to break it.\n *\n * Save status is deliberately not here — it lives on `useTemplatesFeature`, which\n * the one shared header reads, and was never an entitlement. Footer branding is\n * likewise not gated: `config.branding !== false` decides it on any plan.\n */\nexport function useCloudFeatureFlags(\n options: UseCloudFeatureFlagsOptions,\n): UseCloudFeatureFlagsReturn {\n const { planConfigInstance, aiConfig, getTemplateId } = options;\n\n const canUseAiGeneration = computed(\n () =>\n planConfigInstance.hasFeature(\"aiGeneration\") &&\n aiConfig.hasAnyMenuFeature.value,\n );\n const canSendTestEmail = computed(() =>\n planConfigInstance.hasFeature(\"testEmail\"),\n );\n const hasTemplateSaved = computed(() => getTemplateId() !== null);\n const templateLimit = computed(\n () => planConfigInstance.config.value?.limits.maxTemplates ?? null,\n );\n const templateCount = computed(\n () => planConfigInstance.config.value?.templateCount ?? 0,\n );\n\n return {\n canUseAiGeneration,\n canSendTestEmail,\n hasTemplateSaved,\n templateLimit,\n templateCount,\n };\n}\n","import { computed, ref, type ComputedRef, type Ref } from \"vue\";\nimport { onClickOutside } from \"@vueuse/core\";\nimport type { AiFeature } from \"../components/AiFeatureMenu.vue\";\n\nexport interface UseCloudPanelStateReturn {\n activePanel: Ref<RightPanel | null>;\n aiChatOpen: ComputedRef<boolean> & { value: boolean };\n scoringPanelOpen: ComputedRef<boolean> & { value: boolean };\n designReferenceOpen: ComputedRef<boolean> & { value: boolean };\n commentsOpen: ComputedRef<boolean> & { value: boolean };\n aiMenuOpen: Ref<boolean>;\n aiMenuRef: Ref<HTMLElement | null>;\n rightPanelOpen: ComputedRef<boolean>;\n activeAiFeature: ComputedRef<AiFeature | null>;\n aiButtonActive: ComputedRef<boolean>;\n toggleAiMenu: () => void;\n handleAiFeatureSelect: (feature: AiFeature) => void;\n}\n\ntype RightPanel = \"ai-chat\" | \"scoring\" | \"design-reference\" | \"comments\";\n\nexport function useCloudPanelState(): UseCloudPanelStateReturn {\n const activePanel = ref<RightPanel | null>(null);\n\n const aiChatOpen = computed({\n get: () => activePanel.value === \"ai-chat\",\n set: (v) => (activePanel.value = v ? \"ai-chat\" : null),\n });\n const scoringPanelOpen = computed({\n get: () => activePanel.value === \"scoring\",\n set: (v) => (activePanel.value = v ? \"scoring\" : null),\n });\n const designReferenceOpen = computed({\n get: () => activePanel.value === \"design-reference\",\n set: (v) => (activePanel.value = v ? \"design-reference\" : null),\n });\n const commentsOpen = computed({\n get: () => activePanel.value === \"comments\",\n set: (v) => (activePanel.value = v ? \"comments\" : null),\n });\n\n const aiMenuOpen = ref(false);\n const aiMenuRef = ref<HTMLElement | null>(null);\n\n const rightPanelOpen = computed(() => activePanel.value !== null);\n\n const activeAiFeature = computed<AiFeature | null>(() => {\n const p = activePanel.value;\n if (p === \"ai-chat\" || p === \"design-reference\" || p === \"scoring\")\n return p;\n return null;\n });\n\n const aiButtonActive = computed(\n () =>\n aiMenuOpen.value ||\n activePanel.value === \"ai-chat\" ||\n activePanel.value === \"design-reference\" ||\n activePanel.value === \"scoring\",\n );\n\n function toggleAiMenu(): void {\n aiMenuOpen.value = !aiMenuOpen.value;\n }\n\n function handleAiFeatureSelect(feature: AiFeature): void {\n aiMenuOpen.value = false;\n activePanel.value = activePanel.value === feature ? null : feature;\n }\n\n onClickOutside(aiMenuRef, () => {\n aiMenuOpen.value = false;\n });\n\n return {\n activePanel,\n aiChatOpen,\n scoringPanelOpen,\n designReferenceOpen,\n commentsOpen,\n aiMenuOpen,\n aiMenuRef,\n rightPanelOpen,\n activeAiFeature,\n aiButtonActive,\n toggleAiMenu,\n handleAiFeatureSelect,\n };\n}\n","import { computed, ref, type ComputedRef, type Ref } from \"vue\";\nimport type { PlanConfig } from \"@templatical/types\";\nimport type { LintIssue } from \"../../composables/useTemplateLint\";\n\nexport interface UseCloudSaveGateOptions {\n /** Reactive accessibility issues from `useTemplateLint`. */\n issues: Ref<LintIssue[]>;\n /** Reactive plan config from the server. */\n planConfig: Ref<PlanConfig | null>;\n}\n\nexport interface UseCloudSaveGateReturn {\n /** True when the gate would block a save click given current state. */\n shouldBlock: ComputedRef<boolean>;\n /** Errors that would block the save. Empty when `shouldBlock` is false. */\n blockingIssues: ComputedRef<LintIssue[]>;\n /** Modal visibility — toggled by `tryRunSave` and `cancel`. */\n modalOpen: Ref<boolean>;\n /**\n * Wraps a save callback. Returns `true` when the save was invoked\n * (blocking disabled or no errors), `false` when the modal opened\n * instead. Caller can `await` the returned promise to know when the\n * save settled.\n */\n tryRunSave: (run: () => Promise<unknown> | unknown) => Promise<boolean>;\n /**\n * Runs the save only when the gate would not block, and does **nothing** when\n * it would — no modal, no save, nothing pending. Returns whether it ran.\n *\n * This is the autosave path. A modal on a debounce timer would interrupt\n * typing, but simply saving anyway would demote `blockOnError` from a server\n * policy to a manual-save-only speed bump. Skipping leaves the template dirty\n * and the header saying \"unsaved\", which is true, and the reason stays visible\n * in the Issues panel. The next edit re-arms the debounce, so fixing the issue\n * is what lets the save through — no retry timer needed.\n */\n runUnlessBlocked: (run: () => Promise<unknown> | unknown) => Promise<boolean>;\n /** Force-run the pending save, bypassing the gate. */\n confirmAndSave: () => Promise<void>;\n /** Dismiss the modal without saving. */\n cancel: () => void;\n}\n\n/**\n * Cloud-only save-gate. When `planConfig.accessibility.blockOnError === true`\n * and the linter reports any error-severity issues, intercept the save\n * click and surface a confirmation modal listing the blockers. The user\n * can dismiss to fix issues, or click \"Save anyway\" to bypass — the gate\n * does NOT enforce a hard block, it surfaces a deliberate choice.\n *\n * Server policy is the source of truth for `blockOnError`; consumer-side\n * `accessibility` options can't override it.\n */\nexport function useCloudSaveGate(\n opts: UseCloudSaveGateOptions,\n): UseCloudSaveGateReturn {\n const modalOpen = ref(false);\n let pending: (() => Promise<unknown> | unknown) | null = null;\n\n const blockOnError = computed(\n () => opts.planConfig.value?.accessibility?.blockOnError === true,\n );\n\n const blockingIssues = computed(() =>\n blockOnError.value\n ? opts.issues.value.filter((i) => i.severity === \"error\")\n : [],\n );\n\n const shouldBlock = computed(() => blockingIssues.value.length > 0);\n\n async function tryRunSave(\n run: () => Promise<unknown> | unknown,\n ): Promise<boolean> {\n if (!shouldBlock.value) {\n await run();\n return true;\n }\n pending = run;\n modalOpen.value = true;\n return false;\n }\n\n async function runUnlessBlocked(\n run: () => Promise<unknown> | unknown,\n ): Promise<boolean> {\n if (shouldBlock.value) return false;\n await run();\n return true;\n }\n\n async function confirmAndSave(): Promise<void> {\n const run = pending;\n pending = null;\n modalOpen.value = false;\n if (run) {\n await run();\n }\n }\n\n function cancel(): void {\n pending = null;\n modalOpen.value = false;\n }\n\n return {\n shouldBlock,\n blockingIssues,\n modalOpen,\n tryRunSave,\n runUnlessBlocked,\n confirmAndSave,\n cancel,\n };\n}\n","import { type ComputedRef, type Ref, ref } from \"vue\";\nimport { useTimeoutFn } from \"@vueuse/core\";\nimport { COLLAB_UNDO_WARNING_MS } from \"../../constants/timeouts\";\n\nexport interface UseCollabUndoWarningOptions {\n /** Whether collaboration is currently enabled (reactive). */\n isCollaborationEnabled: ComputedRef<boolean>;\n /** Returns the current list of collaborators. */\n getCollaboratorCount: () => number;\n /** Whether the history stack has entries to undo. */\n canUndo: ComputedRef<boolean>;\n}\n\nexport interface UseCollabUndoWarningReturn {\n collabUndoWarningVisible: Ref<boolean>;\n showCollabUndoWarning: () => void;\n}\n\nexport function useCollabUndoWarning(\n options: UseCollabUndoWarningOptions,\n): UseCollabUndoWarningReturn {\n const { isCollaborationEnabled, getCollaboratorCount, canUndo } = options;\n\n const collabUndoWarningFired = ref(false);\n const collabUndoWarningVisible = ref(false);\n\n const { start: startCollabUndoWarningTimeout } = useTimeoutFn(\n () => {\n collabUndoWarningVisible.value = false;\n },\n COLLAB_UNDO_WARNING_MS,\n { immediate: false },\n );\n\n function showCollabUndoWarning(): void {\n if (\n collabUndoWarningFired.value ||\n !isCollaborationEnabled.value ||\n getCollaboratorCount() === 0 ||\n !canUndo.value\n ) {\n return;\n }\n\n collabUndoWarningFired.value = true;\n collabUndoWarningVisible.value = true;\n startCollabUndoWarningTimeout();\n }\n\n return {\n collabUndoWarningVisible,\n showCollabUndoWarning,\n };\n}\n","/**\n * Just enough of a stored template to walk its ids — deliberately structural\n * rather than `Template`, because the caller reads `editor.state`, which is\n * `DeepReadonly` and so not assignable to the mutable contract type.\n */\ninterface SavedBlockIdSource {\n content?: {\n blocks?: readonly {\n id: string;\n type: string;\n children?: readonly (readonly { id: string }[])[];\n }[];\n };\n}\n\n/**\n * Every block id present in the **stored** template, sections' children\n * included.\n *\n * This is the last thing the deleted Cloud editor core carried over the OSS one\n * (`savedBlockIds`), and it never belonged there: its only reader gates a\n * comment filter on whether the block exists server-side, which makes it a\n * *comments* dependency. It travels with that feature accordingly, and reaches\n * `CommentsSidebar` through `capabilities.comments.isBlockSaved`.\n *\n * Derived on demand rather than memoised: `state.template` only changes on a\n * create / load / save round-trip, and the one caller runs on a user filtering\n * the comments panel.\n */\nexport function collectSavedBlockIds(\n template: SavedBlockIdSource | null | undefined,\n): Set<string> {\n const ids = new Set<string>();\n const blocks = template?.content?.blocks;\n if (!blocks) return ids;\n\n for (const block of blocks) {\n ids.add(block.id);\n if (block.type === \"section\" && block.children) {\n for (const column of block.children) {\n for (const child of column) {\n ids.add(child.id);\n }\n }\n }\n }\n return ids;\n}\n","import { computed, provide, ref, watch } from \"vue\";\nimport {\n AuthManager,\n isFatalAuthError,\n performHealthCheck,\n useAiConfig,\n useCollaboration,\n useCollaborationBroadcast,\n useExport,\n useMcpListener,\n usePlanConfig,\n resolveExportFonts,\n resolveWebSocketConfig,\n createCloudCommentsProvider,\n createCloudMediaProvider,\n createCloudRenderProvider,\n createCloudSavedBlocksProvider,\n createCloudTemplatesProvider,\n createCloudTestEmailProvider,\n createCloudVersionHistoryProvider,\n useTemplateScoring,\n useTestEmail,\n useWebSocket,\n type RealtimeChannel,\n} from \"@templatical/core/cloud\";\nimport type { UseEditorReturn } from \"@templatical/core\";\nimport type {\n CommentsOptions,\n CommentsProvider,\n EditorUser,\n MediaOptions,\n MediaProvider,\n RenderProvider,\n SavedBlocksOptions,\n SavedBlocksProvider,\n Template,\n TemplateContent,\n TemplatePatch,\n TemplatesOptions,\n TemplatesProvider,\n TestEmailOptions,\n TestEmailProvider,\n VersionHistoryOptions,\n VersionHistoryProvider,\n} from \"@templatical/types\";\n\nimport type { CloudTranslations } from \"../i18n\";\nimport { preRenderCustomBlocks } from \"../utils/preRenderCustomBlocks\";\nimport { logger } from \"../utils/logger\";\nimport type { UseEditorCoreReturn } from \"../composables/useEditorCore\";\nimport {\n AI_CONFIG_KEY,\n AUTH_MANAGER_KEY,\n CLOUD_TRANSLATIONS_KEY,\n SCORING_KEY,\n} from \"../keys\";\n\nimport { useCloudFeatureFlags } from \"./composables/useCloudFeatureFlags\";\nimport { useCloudPanelState } from \"./composables/useCloudPanelState\";\nimport {\n useCloudSaveGate,\n type UseCloudSaveGateReturn,\n} from \"./composables/useCloudSaveGate\";\nimport {\n useCollabUndoWarning,\n type UseCollabUndoWarningReturn,\n} from \"./composables/useCollabUndoWarning\";\nimport { collectSavedBlockIds } from \"./collectSavedBlockIds\";\nimport type {\n CloudAttachContext,\n CloudAttachment,\n CloudCollaborationInstance,\n CloudReady,\n CloudReadyContext,\n CloudRuntime,\n} from \"./runtime\";\nimport type { TemplaticalCloudEditorConfig } from \"./cloudConfig\";\n\nexport interface BootstrapCloudOptions {\n config: TemplaticalCloudEditorConfig;\n cloudTranslations: CloudTranslations;\n}\n\n/**\n * What {@link bootstrapCloud} hands back: a set of ordinary `init()` config\n * values, plus the runtime for the few things that must run inside the editor\n * component's `setup()`.\n */\nexport interface CloudBootstrap {\n runtime: CloudRuntime;\n providers: {\n templates: TemplatesProvider;\n render: RenderProvider;\n versionHistory: VersionHistoryProvider;\n /** Absent when `savedBlocks: false` — the feature is then off entirely. */\n savedBlocks?: SavedBlocksProvider;\n testEmail: TestEmailProvider;\n comments: CommentsProvider;\n /** Absent when `media: false` — Browse is then off unless `onRequestMedia` is set. */\n media?: MediaProvider;\n };\n /**\n * Who is editing, from the JWT — `init({ user })`'s value for a Cloud session.\n *\n * `undefined` when the project's token carries no `user` claim, which makes\n * comments unavailable rather than anonymous. Not a key `initCloud()` accepts:\n * Cloud's comment writes are signed against this same claim, so a\n * consumer-supplied identity would only be able to disagree with it.\n */\n user?: EditorUser;\n}\n\n/**\n * Pick only the event members off a consumer-supplied `templates` value.\n *\n * A whitelist, never a spread. The config type says `TemplatesOptions`, but a\n * JavaScript consumer is unchecked, so the object can carry anything —\n * `load`/`create`/`save` are already shadowed by the literal defining them\n * after the spread, and this drops everything else so the guarantee never\n * depends on that ordering surviving a later edit.\n *\n * Each member is also type-checked, not merely truthiness-checked: a value\n * like `onSaved: \"yes\"` would otherwise reach core and throw at save time,\n * inside a call the consumer never made.\n */\nfunction eventsOf(value: TemplatesOptions | undefined): TemplatesOptions {\n if (!value) return {};\n const { onSaved, onCreated, onLoaded } = value;\n return {\n ...(typeof onSaved === \"function\" ? { onSaved } : {}),\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onLoaded === \"function\" ? { onLoaded } : {}),\n };\n}\n\n/**\n * Fails to compile when `TemplatesOptions` gains a member outside the six\n * named below. Cloud picks that object apart by name in two places —\n * `eventsOf` above and `initCloud`'s merge in `index.ts` — so a seventh\n * member forces a **deliberate decision** about which of the two forwards\n * it. The check cannot make that decision itself: adding the new name to the\n * `Exclude` list below satisfies the compiler on its own and forwards\n * nothing by itself, and it has no way to tell an event (belongs in\n * `eventsOf`) from config (belongs in the `index.ts` merge).\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below\n * is what forces the check — it fails to compile the moment a member falls\n * outside the six named here.\n */\ntype _TemplatesOptionsForwarded =\n Exclude<\n keyof TemplatesOptions,\n | \"autoSave\"\n | \"unsavedChangesGuard\"\n | \"nameField\"\n | \"onSaved\"\n | \"onCreated\"\n | \"onLoaded\"\n > extends never\n ? true\n : never;\nconst _templatesOptionsForwarded: _TemplatesOptionsForwarded = true;\n\n/**\n * Pick only the event members off a consumer-supplied `comments` value.\n *\n * A whitelist, never a spread. The config type says `CommentsOptions`, but a\n * JavaScript consumer is unchecked, so the object can carry anything —\n * `list`/`create`/`update`/`delete`/`setResolved` are already shadowed by the\n * spread of Cloud's own adapter that follows this in the provider literal, and\n * this drops everything else so the guarantee never depends on that ordering\n * surviving a later edit.\n *\n * Each member is also type-checked, not merely truthiness-checked: a value\n * like `onCreated: \"yes\"` would otherwise reach core and throw at\n * comment-creation time, inside a call the consumer never made.\n */\nfunction commentEventsOf(\n value: false | CommentsOptions | undefined,\n): CommentsOptions {\n if (!value) return {};\n const { onCreated, onUpdated, onDeleted, onResolved, onUnresolved } = value;\n return {\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onUpdated === \"function\" ? { onUpdated } : {}),\n ...(typeof onDeleted === \"function\" ? { onDeleted } : {}),\n ...(typeof onResolved === \"function\" ? { onResolved } : {}),\n ...(typeof onUnresolved === \"function\" ? { onUnresolved } : {}),\n };\n}\n\n/**\n * Fails to compile when `CommentsOptions` gains a member outside the five\n * named below. Every member of `CommentsOptions` is an event, and\n * `commentEventsOf` above is the only place that forwards them — unlike\n * `TemplatesOptions`, there is no second merge in `index.ts`, since comments\n * carries no config booleans for that merge to combine. A sixth member has\n * exactly one place to be added: this list and `commentEventsOf`'s destructure,\n * together.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below is\n * what forces the check — it fails to compile the moment a member falls\n * outside the five named here.\n */\ntype _CommentsOptionsForwarded =\n Exclude<\n keyof CommentsOptions,\n \"onCreated\" | \"onUpdated\" | \"onDeleted\" | \"onResolved\" | \"onUnresolved\"\n > extends never\n ? true\n : never;\nconst _commentsOptionsForwarded: _CommentsOptionsForwarded = true;\n\n/**\n * Pick only the event members off a consumer-supplied `savedBlocks` value.\n *\n * A whitelist, never a spread. `savedBlocks` accepts a boolean, an\n * events-only `SavedBlocksOptions`, or a full `SavedBlocksProvider` — this is\n * only ever called on the first two, since a full provider replaces Cloud's\n * adapter outright and is used as-is (see `consumerSavedBlocks` below). A\n * non-object value (`true`, `undefined`, `false`) carries no keys to pick, so\n * it returns `{}` rather than throwing on the destructure.\n *\n * Each member is also type-checked, not merely truthiness-checked: a value\n * like `onCreated: \"yes\"` would otherwise reach core and throw at\n * saved-block-creation time, inside a call the consumer never made.\n */\nfunction savedBlocksEventsOf(\n value: TemplaticalCloudEditorConfig[\"savedBlocks\"],\n): SavedBlocksOptions {\n if (typeof value !== \"object\" || value === null) return {};\n const { onCreated, onUpdated, onDeleted } = value;\n return {\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onUpdated === \"function\" ? { onUpdated } : {}),\n ...(typeof onDeleted === \"function\" ? { onDeleted } : {}),\n };\n}\n\n/**\n * Fails to compile when `SavedBlocksOptions` gains a member outside the three\n * named below. `savedBlocksEventsOf` above is the only place that forwards\n * them, so a fourth member has exactly one place to be added: this list and\n * that function's destructure, together.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below\n * is what forces the check — it fails to compile the moment a member falls\n * outside the three named here.\n */\ntype _SavedBlocksOptionsForwarded =\n Exclude<\n keyof SavedBlocksOptions,\n \"onCreated\" | \"onUpdated\" | \"onDeleted\"\n > extends never\n ? true\n : never;\nconst _savedBlocksOptionsForwarded: _SavedBlocksOptionsForwarded = true;\n\n/**\n * Pick `onSent` and `defaultRecipient` off a consumer-supplied `testEmail`\n * value.\n *\n * A whitelist, like `savedBlocksEventsOf` — but note what it does NOT pick:\n * `includeMjml` and `allowedRecipients` stay Cloud's own whenever Cloud's\n * sender is in play, so they are never read here even though\n * `TestEmailOptions` declares them (see `_TestEmailOptionsForwarded` below).\n * `defaultRecipient` has no such conflict — Cloud's provider never defines\n * it, and `useTestEmailFeature` already discards a value outside\n * `allowedRecipients`, so a consumer's choice can only ever pre-fill an\n * address already on Cloud's own signed list, never smuggle in one outside\n * it. `onSent` is a plain notification with no conflict either, so both\n * cross over.\n *\n * The result is assigned ONTO Cloud's own provider with `Object.assign`\n * (never spread together with it) at the call site — that provider's\n * `allowedRecipients` is a live getter over the JWT-derived allowlist, and a\n * spread reads every own property through `[[Get]]`, freezing the getter's\n * current value into a plain property on the new object. `Object.assign`\n * with the cloud provider as the *target* only ever writes the keys this\n * function returns, so the getter is never read and never disturbed.\n */\nfunction testEmailEventsOf(\n value: TemplaticalCloudEditorConfig[\"testEmail\"],\n): Pick<TestEmailOptions, \"onSent\" | \"defaultRecipient\"> {\n if (typeof value !== \"object\" || value === null) return {};\n const { onSent, defaultRecipient } = value;\n return {\n ...(typeof onSent === \"function\" ? { onSent } : {}),\n ...(typeof defaultRecipient === \"string\" ? { defaultRecipient } : {}),\n };\n}\n\n/**\n * Fails to compile when `TestEmailOptions` gains a member outside the four\n * named below. `onSent` and `defaultRecipient` are forwarded by\n * `testEmailEventsOf` above; `includeMjml` and `allowedRecipients` stay\n * Cloud's own whenever Cloud's sender is in play (Cloud renders server-side\n * rather than from a client MJML pass, and the allowlist is the signed one\n * from the project's JWT, not a client-supplied one). A fifth member still\n * forces a deliberate decision the same way a fourth `SavedBlocksOptions`\n * member does: whether it joins the forwarded pair or stays excluded for the\n * same reason as the other two.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below\n * is what forces the check — it fails to compile the moment a member falls\n * outside the four named here.\n */\ntype _TestEmailOptionsForwarded =\n Exclude<\n keyof TestEmailOptions,\n \"includeMjml\" | \"allowedRecipients\" | \"defaultRecipient\" | \"onSent\"\n > extends never\n ? true\n : never;\nconst _testEmailOptionsForwarded: _TestEmailOptionsForwarded = true;\n\n/**\n * Pick only the event members off a consumer-supplied `media` value.\n *\n * A whitelist, never a spread. `media` accepts `false`, an events-only\n * {@link MediaOptions}, or a full {@link MediaProvider} — this is only ever\n * called on the first two, since a full provider replaces Cloud's adapter\n * outright and is used as-is (see `consumerMedia` below). A non-object\n * value (`undefined`, `false`) carries no keys to pick, so it returns `{}`\n * rather than throwing on the destructure.\n *\n * What it does NOT pick: `maxFileSize` and `mimeTypes` stay Cloud's own\n * whenever Cloud's store is in play (Cloud's plan owns those limits), so\n * they are never read here even though `MediaOptions` declares them (see\n * `_MediaOptionsForwarded` below).\n *\n * The result is assigned ONTO Cloud's own provider with `Object.assign`\n * (never spread together with it) at the call site — that provider's\n * `storage` / `maxFileSize` / `mimeTypes` read plan config live, and a\n * spread reads every own property through `[[Get]]`, freezing each\n * getter's current value into a plain property on the new object.\n * `Object.assign` with the cloud provider as the *target* only ever\n * writes the keys this function returns, so those getters are never\n * read and never disturbed.\n */\nfunction mediaEventsOf(\n value: TemplaticalCloudEditorConfig[\"media\"],\n): Pick<MediaOptions, \"onCreated\" | \"onUpdated\" | \"onDeleted\"> {\n if (typeof value !== \"object\" || value === null) return {};\n const { onCreated, onUpdated, onDeleted } = value;\n return {\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onUpdated === \"function\" ? { onUpdated } : {}),\n ...(typeof onDeleted === \"function\" ? { onDeleted } : {}),\n };\n}\n\n/**\n * Fails to compile when `MediaOptions` gains a member outside the five\n * named below. `onCreated` / `onUpdated` / `onDeleted` are forwarded by\n * `mediaEventsOf` above; `maxFileSize` and `mimeTypes` stay Cloud's own\n * whenever Cloud's store is in play (Cloud's plan owns those limits). A\n * sixth member still forces a deliberate decision the same way a fifth\n * `TestEmailOptions` member does: whether it joins the forwarded trio or\n * stays excluded for the same reason as the other two.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias\n * nothing reads, so a `never` result would sit there silently. The\n * assignment below is what forces the check — it fails to compile the\n * moment a member falls outside the five named here.\n */\ntype _MediaOptionsForwarded =\n Exclude<\n keyof MediaOptions,\n \"onCreated\" | \"onUpdated\" | \"onDeleted\" | \"maxFileSize\" | \"mimeTypes\"\n > extends never\n ? true\n : never;\nconst _mediaOptionsForwarded: _MediaOptionsForwarded = true;\n\n/**\n * Pick only the event members off a consumer-supplied `versionHistory`\n * value.\n *\n * A whitelist, never a spread — the config type says `VersionHistoryOptions`,\n * but a JavaScript consumer is unchecked, so the object can carry anything.\n * `versionHistory` never accepts a full provider (see the rejected-keys block\n * below), so unlike `savedBlocksEventsOf` / `testEmailEventsOf` this is\n * always called on the whole config value.\n */\nfunction versionHistoryEventsOf(\n value: VersionHistoryOptions | undefined,\n): VersionHistoryOptions {\n if (!value) return {};\n const { onCreated, onRestored } = value;\n return {\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onRestored === \"function\" ? { onRestored } : {}),\n };\n}\n\n/**\n * Fails to compile when `VersionHistoryOptions` gains a member outside the\n * two named below. `versionHistoryEventsOf` above is the only place that\n * forwards them, so a third member has exactly one place to be added: this\n * list and that function's destructure, together.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below\n * is what forces the check — it fails to compile the moment a member falls\n * outside the two named here.\n */\ntype _VersionHistoryOptionsForwarded =\n Exclude<keyof VersionHistoryOptions, \"onCreated\" | \"onRestored\"> extends never\n ? true\n : never;\nconst _versionHistoryOptionsForwarded: _VersionHistoryOptionsForwarded = true;\n\n/**\n * A comma list with a final \"and\" — \"a\"; \"a and b\"; \"a, b and c\". The\n * ignored-methods warnings below each name however many storage methods a\n * consumer actually passed, and `Array.join(\" and \")` only reads correctly\n * for exactly two.\n */\nfunction joinWithAnd(items: string[]): string {\n if (items.length < 2) return items.join(\"\");\n if (items.length === 2) return items.join(\" and \");\n return `${items.slice(0, -1).join(\", \")} and ${items[items.length - 1]}`;\n}\n\n/**\n * Cloud's bootstrap and adapter wiring, in one place, run **before the editor\n * mounts**.\n *\n * This replaces `useCloudInitialization`, which owned a second `useEditor`, a\n * second `useEditorCore` and a post-mount async dance with its own loading and\n * error states. The dance is gone: auth, the health check and the plan fetch all\n * resolve here, and a failure rejects `initCloud()` rather than mounting an\n * editor that cannot work. What is left is adapter construction.\n *\n * Two things deliberately stay Cloud-only:\n *\n * - **Entitlements.** In an all-BYO world there are no plans, so `planConfig` is\n * Cloud's commercial layer above the provider set rather than a provider\n * itself. It is down to five booleans, each metering a resource Cloud buys.\n * - **Mid-session failure.** `init()` cannot fail after it mounts and should not\n * grow the ability, so the error overlay lives on this side of the seam.\n */\nexport async function bootstrapCloud(\n options: BootstrapCloudOptions,\n): Promise<CloudBootstrap> {\n const { config, cloudTranslations } = options;\n\n // --- Late-bound editor access ---------------------------------------------\n //\n // The providers below are built before there is an editor to read. Each\n // reaches it through these holders, filled by `attach()` / `ready()` — which is\n // what lets them be handed to `init()` as ordinary config keys.\n let editorRef: UseEditorReturn | null = null;\n let coreRef: UseEditorCoreReturn | null = null;\n let websocketRef: ReturnType<typeof useWebSocket> | null = null;\n let collaboration: CloudCollaborationInstance | null = null;\n let collabWarning: UseCollabUndoWarningReturn | null = null;\n let saveGate: UseCloudSaveGateReturn | null = null;\n\n const sessionError = ref<Error | null>(null);\n const lockedBlocks = ref<Map<string, unknown>>(new Map());\n /**\n * Cloud's presence channel, forward-declared for the comments adapter's\n * `subscribe`. `useWebSocket` can only be built in `attach()` (it needs the\n * editor), while the provider is handed to `init()` before that — so the adapter\n * watches this and rebinds when the real channel lands.\n */\n const commentChannel = ref<RealtimeChannel | null>(null);\n\n function requireEditor(): UseEditorReturn {\n if (!editorRef) {\n throw new Error(\"[Templatical] The Cloud editor is not mounted yet.\");\n }\n return editorRef;\n }\n\n function getTemplateId(): string | null {\n return editorRef?.state.template?.id ?? null;\n }\n\n // --- Auth + plan ----------------------------------------------------------\n\n const authManager = new AuthManager({\n ...config.auth,\n // Only a *fatal* refusal raises the overlay. A 4xx means the endpoint\n // rejected the credentials, so every subsequent request fails the same way\n // and the session really is over. A network blip or a 5xx resolves on its\n // own, and blanking a mounted editor over one interrupts someone mid-edit on\n // a template that is probably unsaved — a worse outcome than the blip.\n //\n // The consumer hears about both: `onError` fires either way, and\n // `AuthManager` re-throws regardless, so a caller that cannot proceed still\n // finds out.\n onError: (error: Error) => {\n if (isFatalAuthError(error)) {\n sessionError.value = error;\n }\n config.onError?.(error);\n },\n });\n\n const planConfigInstance = usePlanConfig({\n authManager,\n onError: config.onError,\n });\n\n await authManager.initialize();\n\n const healthResult = await performHealthCheck({ authManager });\n if (!healthResult.api.ok) {\n throw new Error(\"Health check failed: API is not reachable\");\n }\n if (!healthResult.auth.ok) {\n throw new Error(\n `Health check failed: authentication error${healthResult.auth.error ? ` - ${healthResult.auth.error}` : \"\"}`,\n );\n }\n if (!healthResult.websocket.ok) {\n logger.warn(\n \"WebSocket health check failed:\",\n healthResult.websocket.error ?? \"unknown error\",\n \"-- real-time features will be disabled.\",\n );\n }\n\n await planConfigInstance.fetchConfig();\n\n // The bootstrap itself is what the overlay would have covered, and it just\n // succeeded — so anything `onError` recorded on the way here is stale.\n sessionError.value = null;\n\n // --- Rejected consumer keys ----------------------------------------------\n //\n // `render` is not declared on `TemplaticalCloudEditorConfig`, so it only\n // fires for JavaScript consumers — warned rather than silently dropped,\n // because the symptom (a store that stays empty while Cloud's fills up)\n // reads as a broken provider rather than a rejected one. `templates`,\n // `comments` and `versionHistory` ARE declared, but typed narrowly as\n // `TemplatesOptions`, `CommentsOptions` and `VersionHistoryOptions` — a\n // JavaScript consumer can still hand over a full provider, so its storage\n // methods are named and ignored the same way, while any events they carry\n // reach `eventsOf` / `commentEventsOf` / `versionHistoryEventsOf` below\n // regardless of this check.\n const consumerTemplates = (config as { templates?: Record<string, unknown> })\n .templates;\n // Presence, not `typeof === \"function\"` — see the matching comment on\n // `ignoredCommentMethods` below: a stated-but-ignored decision like\n // `save: false` is as much a signal as a stray function override.\n const ignoredTemplateMethods = [\"load\", \"create\", \"save\"].filter(\n (key) => typeof consumerTemplates?.[key] !== \"undefined\",\n );\n if (ignoredTemplateMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredTemplateMethods.map((key) => `templates.${key}`),\n )} — the template id is the join key for collaboration, ` +\n \"version history, comments, AI rewrite, scoring and the server-side \" +\n \"export, so an id Cloud never issued would degrade all six. Your \" +\n \"event handlers were kept. Use init() to bring your own storage.\",\n );\n }\n const consumerVersionHistory = (\n config as { versionHistory?: Record<string, unknown> }\n ).versionHistory;\n // Presence, not `typeof === \"function\"`: a stated-but-ignored decision like\n // `restore: false` is as much a signal as a stray function override, and\n // both must be named here or the consumer never learns it was dropped.\n const ignoredVersionHistoryMethods = [\n \"list\",\n \"get\",\n \"create\",\n \"restore\",\n ].filter((key) => typeof consumerVersionHistory?.[key] !== \"undefined\");\n if (ignoredVersionHistoryMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredVersionHistoryMethods.map((key) => `versionHistory.${key}`),\n )} — a version is keyed to a template id Cloud issued, so Cloud owns ` +\n \"its history. Your event handlers were kept. Use init() to bring \" +\n \"your own storage.\",\n );\n }\n const consumerComments = (config as { comments?: Record<string, unknown> })\n .comments;\n // Presence, not `typeof === \"function\"`: a stated-but-ignored decision like\n // `create: false` is as much a signal as a stray function override, and both\n // must be named here or the consumer never learns it was dropped.\n const ignoredCommentMethods = [\n \"list\",\n \"create\",\n \"update\",\n \"delete\",\n \"setResolved\",\n \"subscribe\",\n ].filter((key) => typeof consumerComments?.[key] !== \"undefined\");\n if (ignoredCommentMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredCommentMethods.map((key) => `comments.${key}`),\n )} — a comment is keyed to a template id Cloud issued, and its ` +\n \"author is signed by the auth token, so Cloud owns the conversation. \" +\n \"Your event handlers were kept. Use init() to bring your own storage.\",\n );\n }\n // Rejected for a different reason than the three above: not the join key, but\n // because Cloud renders on its own for test email, scheduled sends and API\n // exports (`createCloudTestEmailProvider` calls `exportHtml` directly). A\n // consumer provider would have changed `toMjml()` / `toHtml()` and nothing\n // else, so what the user previewed and exported was not what Cloud delivered —\n // and Cloud's output is a deliberate superset (countdown GIFs, composited video\n // thumbnails), so the consumer's was also worse for those blocks.\n if ((config as { render?: unknown }).render) {\n logger.warn(\n \"initCloud does not accept a `render` provider — Cloud renders \" +\n \"server-side for test email, sends and exports, so a supplied renderer \" +\n \"would change only what you preview and export, never what Cloud \" +\n \"delivers. The supplied provider is ignored. For your own MJML, call \" +\n \"renderToMjml(editor.getContent()) from @templatical/renderer.\",\n );\n }\n\n // --- Providers ------------------------------------------------------------\n\n function connectRealtime(template: Template): void {\n const websocketConfig = planConfigInstance.config.value?.websocket;\n if (!websocketRef || !websocketConfig) return;\n websocketRef.connect(template.id, resolveWebSocketConfig(websocketConfig));\n }\n\n const baseTemplates = createCloudTemplatesProvider(authManager);\n const baseCreate = baseTemplates.create;\n const baseSave = baseTemplates.save;\n\n /**\n * Cloud's templates adapter plus the choreography the template id anchors:\n * the websocket joins the template's presence channel. The consumer's\n * `onSaved` / `onCreated` / `onLoaded` ride along via `eventsOf` — core calls\n * them once the editor has settled, so the adapter itself never invokes them.\n *\n * That choreography belongs in the adapter rather than in an editor-side\n * lifecycle composable, because it *is* adapter business — Cloud is what keys\n * realtime off the id it issued. `useCloudLifecycle` existed only to hold it.\n *\n * `save` pre-renders custom blocks, which is why it is wrapped too.\n */\n const templates: TemplatesProvider = {\n ...eventsOf(config.templates),\n load: async (id: string) => {\n const template = await baseTemplates.load(id);\n connectRealtime(template);\n return template;\n },\n create:\n typeof baseCreate === \"function\"\n ? async (input: { name?: string; content: TemplateContent }) => {\n const template = await baseCreate(input);\n connectRealtime(template);\n return template;\n }\n : false,\n save:\n typeof baseSave === \"function\"\n ? async (id: string, patch: TemplatePatch) => {\n if (coreRef && editorRef) {\n await preRenderCustomBlocks(\n editorRef.content.value,\n coreRef.registry,\n );\n }\n return baseSave(id, patch);\n }\n : false,\n };\n\n // Always Cloud's — see the rejected-keys block above. Cloud renders\n // independently for delivery, so a second renderer could only disagree with it.\n const render: RenderProvider = createCloudRenderProvider({\n authManager,\n getTemplateId,\n // Plain `editor.save()`: the templates adapter below already pre-renders\n // custom blocks on every save, which is exactly what the render endpoint\n // needs, since it exports from the stored copy rather than from\n // `payload.content`.\n save: () => requireEditor().save(),\n });\n\n // The consumer's `onCreated` / `onRestored` ride along via\n // `versionHistoryEventsOf` — core calls them once the editor has settled, so\n // the adapter itself never invokes them. `versionHistory` never accepts a\n // full provider (see the rejected-keys block above), so this always merges\n // onto Cloud's own adapter, never onto a consumer's.\n const versionHistory: VersionHistoryProvider = {\n ...versionHistoryEventsOf(config.versionHistory),\n ...createCloudVersionHistoryProvider(authManager),\n };\n\n // Realtime is the adapter's own business: `subscribe` binds the presence channel\n // above, so `useCommentListener` in `@templatical/core` never learns that Pusher\n // exists and a BYO provider with an SSE stream slots into the same seam. The\n // consumer's `onCreated` / `onUpdated` / `onDeleted` / `onResolved` /\n // `onUnresolved` ride along via `commentEventsOf` — core calls them once the\n // editor has settled, so the adapter itself never invokes them.\n const comments: CommentsProvider = {\n ...commentEventsOf(config.comments),\n ...createCloudCommentsProvider({\n authManager,\n channel: commentChannel,\n getSocketId: () => websocketRef?.getSocketId() ?? null,\n }),\n };\n\n // From the JWT, not from config. Cloud signs comment writes against this same\n // claim, so a consumer-supplied identity could only disagree with it — and a\n // token without the claim leaves comments unavailable rather than anonymous.\n const cloudUser: EditorUser | undefined = authManager.userConfig\n ? { id: authManager.userConfig.id, name: authManager.userConfig.name }\n : undefined;\n\n // A consumer may pass their own store instead of a boolean, in which case it\n // replaces Cloud's outright — discriminated on `list`, the one required\n // method every full provider carries, never on `typeof === \"object\"`: an\n // events-only `SavedBlocksOptions` (`{ onCreated }`) is an object too, and\n // reading it as the provider would leave `list` undefined and crash the\n // library on first browse. That path is deliberately NOT plan-gated:\n // `savedModules` licenses Cloud's *storage*, and someone else's backend\n // isn't Cloud's to sell — `isSavedBlocksAvailable` below keys off this same\n // discriminated value for that reason.\n const consumerSavedBlocks =\n typeof (config.savedBlocks as SavedBlocksProvider | undefined)?.list ===\n \"function\"\n ? (config.savedBlocks as SavedBlocksProvider)\n : null;\n // A malformed provider — e.g. `create` / `update` / `delete` with no\n // working `list` — fails the discriminator above and falls through to\n // Cloud's own store, so those methods are silently unused rather than\n // replacing anything. Named here the same way `templates` / `comments` /\n // `versionHistory` name their own ignored methods, so the drop isn't a\n // console-free mystery.\n if (\n consumerSavedBlocks === null &&\n typeof config.savedBlocks === \"object\" &&\n config.savedBlocks !== null\n ) {\n const suppliedSavedBlocks = config.savedBlocks as Record<string, unknown>;\n const ignoredSavedBlocksMethods = [\n \"list\",\n \"create\",\n \"update\",\n \"delete\",\n ].filter((key) => typeof suppliedSavedBlocks[key] !== \"undefined\");\n if (ignoredSavedBlocksMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredSavedBlocksMethods.map((key) => `savedBlocks.${key}`),\n )} — a provider needs a working list to replace Cloud's store, and ` +\n \"this value has none, so it configures Cloud's own store instead. \" +\n \"Your event handlers were kept. Use init() to bring your own storage.\",\n );\n }\n }\n // The consumer's `onCreated` / `onUpdated` / `onDeleted` ride along via\n // `savedBlocksEventsOf` when Cloud's own adapter is used — core calls them\n // once the editor has settled, so the adapter itself never invokes them. A\n // full consumer provider carries its own events already and is used as-is,\n // so this merge only ever runs on Cloud's side of the `??`.\n const savedBlocks: SavedBlocksProvider | undefined =\n config.savedBlocks === false\n ? undefined\n : (consumerSavedBlocks ?? {\n ...savedBlocksEventsOf(config.savedBlocks),\n ...createCloudSavedBlocksProvider(authManager),\n });\n\n // Cloud's test-email *config* — plan enablement plus the signed allowlist, both\n // carried by the JWT `authManager.initialize()` already resolved above. Hence\n // the constant `isAuthReady`: there is no window where it is false.\n const testEmailConfig = useTestEmail({\n authManager,\n isAuthReady: ref(true),\n });\n\n // Cloud's own send path renders through the export endpoint directly: the\n // adapter derives HTML from the *saved* template and applies\n // `onBeforeTestEmail` to it, which is a narrower job than the render contract.\n const exporter = useExport({ authManager });\n\n // Discriminated on `send`, the one required method every full provider\n // carries — never on raw truthiness, which an events-only `TestEmailOptions`\n // (`{ onSent }`) also satisfies and would leave `send` undefined, crashing\n // the dialog on send. `isTestEmailAvailable` below keys off this same\n // discriminated value so an events-only value stays plan-gated rather than\n // reading as \"consumer's own sender\".\n const consumerTestEmail =\n typeof (config.testEmail as TestEmailProvider | undefined)?.send ===\n \"function\"\n ? (config.testEmail as TestEmailProvider)\n : null;\n // `send` reaching here means it failed the discriminator above — e.g.\n // `send: null` — so it is named the same way a malformed `savedBlocks`\n // value's storage methods are. `includeMjml` / `allowedRecipients` are\n // named for a different reason: they are not part of this key's options\n // arm (see `cloudConfig.ts`), but TypeScript does not actually refuse\n // them — both are valid members of the sibling `TestEmailProvider` arm, so\n // the union's excess-property check passes them through regardless of\n // which arm the caller intended. All three log a warning naming them\n // rather than dropping with no console trace.\n if (\n consumerTestEmail === null &&\n typeof config.testEmail === \"object\" &&\n config.testEmail !== null\n ) {\n const suppliedTestEmail = config.testEmail as Record<string, unknown>;\n const ignoredTestEmailMembers = [\n \"send\",\n \"includeMjml\",\n \"allowedRecipients\",\n ].filter((key) => typeof suppliedTestEmail[key] !== \"undefined\");\n if (ignoredTestEmailMembers.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredTestEmailMembers.map((key) => `testEmail.${key}`),\n )} — a provider needs a working send to replace Cloud's sender ` +\n \"outright, and Cloud renders server-side with the signed \" +\n \"allowlist from your project's JWT either way, so none of these \" +\n \"apply here. Your event handlers were kept.\",\n );\n }\n }\n const testEmail: TestEmailProvider =\n consumerTestEmail ??\n // `Object.assign`, not a spread: `createCloudTestEmailProvider`'s\n // `allowedRecipients` is a live getter (see `testEmailEventsOf`'s doc\n // comment for why a spread would freeze it). The cloud provider is the\n // assignment *target* here, so its getter is never read — only the keys\n // `testEmailEventsOf` returns are ever written onto it.\n //\n // Asymmetric with `savedBlocks` / `versionHistory` on purpose, not by\n // drift: those two spread Cloud's provider LAST, so even a whitelist that\n // let something unexpected through could never displace a Cloud method —\n // two lines of defence. Here `testEmailEventsOf`'s return type is the\n // only barrier, because Cloud is the assignment target rather than a\n // second spread source. Copying the sibling shape (`{ ...events,\n // ...createCloudTestEmailProvider(...) }`) would reintroduce the exact\n // getter-freezing bug this construction exists to avoid.\n Object.assign(\n createCloudTestEmailProvider({\n authManager,\n getTemplateId,\n save: () => requireEditor().save(),\n exportHtml: (templateId: string) =>\n exporter.exportHtml(templateId, resolveExportFonts(config.fonts)),\n allowedEmails: testEmailConfig.allowedEmails,\n getSignature: testEmailConfig.getSignature,\n onBeforeTestEmail: config.onBeforeTestEmail,\n }),\n testEmailEventsOf(config.testEmail),\n );\n\n // A consumer may pass their own store instead of omitting the key or\n // passing `false`, in which case it replaces Cloud's outright —\n // discriminated on `list`, the one required method every full provider\n // carries, never on `typeof === \"object\"`: an events-only `MediaOptions`\n // (`{ onCreated }`) is an object too, and reading it as the provider\n // would leave `list` undefined and crash the library on first browse.\n // That path is deliberately NOT plan-gated: there is no media plan\n // feature. The plan licenses Cloud's *storage*, and someone else's\n // backend isn't Cloud's to sell.\n const consumerMedia =\n typeof (config.media as MediaProvider | undefined)?.list === \"function\"\n ? (config.media as MediaProvider)\n : null;\n // A malformed provider — e.g. `create` / `update` / `delete` with no\n // working `list` — fails the discriminator above and falls through to\n // Cloud's own store, so those methods are silently unused rather than\n // replacing anything. Named here the same way `savedBlocks` names its\n // own ignored methods, so the drop isn't a console-free mystery.\n // `maxFileSize` / `mimeTypes` are named for a different reason: they\n // are valid `MediaOptions` members but Cloud's plan owns those limits\n // whenever Cloud's store is in play.\n if (\n consumerMedia === null &&\n typeof config.media === \"object\" &&\n config.media !== null\n ) {\n const suppliedMedia = config.media as Record<string, unknown>;\n const ignoredMediaMethods = [\"list\", \"create\", \"update\", \"delete\"].filter(\n (key) => typeof suppliedMedia[key] !== \"undefined\",\n );\n if (ignoredMediaMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredMediaMethods.map((key) => `media.${key}`),\n )} — a provider needs a working list to replace Cloud's store, and ` +\n \"this value has none, so it configures Cloud's own store instead. \" +\n \"Your event handlers were kept. Use init() to bring your own storage.\",\n );\n }\n const ignoredMediaLimits = [\"maxFileSize\", \"mimeTypes\"].filter(\n (key) => typeof suppliedMedia[key] !== \"undefined\",\n );\n if (ignoredMediaLimits.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredMediaLimits.map((key) => `media.${key}`),\n )} — Cloud's plan owns those limits whenever Cloud's store is in ` +\n \"play. Your event handlers were kept.\",\n );\n }\n }\n const media: MediaProvider | undefined =\n config.media === false\n ? undefined\n : (consumerMedia ??\n // `Object.assign`, not a spread: `createCloudMediaProvider`'s\n // `storage` / `maxFileSize` / `mimeTypes` read plan config live\n // (see `mediaEventsOf`'s doc comment for why a spread would freeze\n // the getters). The cloud provider is the assignment *target*\n // here, so its getters are never read — only the keys\n // `mediaEventsOf` returns are ever written onto it.\n Object.assign(\n createCloudMediaProvider(\n authManager,\n () => planConfigInstance.config.value,\n ),\n mediaEventsOf(config.media),\n ));\n\n // --- Setup-time wiring ----------------------------------------------------\n\n const aiConfig = useAiConfig(config.ai);\n const scoringInstance = useTemplateScoring({ authManager, getTemplateId });\n\n const featureFlags = useCloudFeatureFlags({\n planConfigInstance,\n aiConfig,\n getTemplateId,\n });\n\n const isCollaborationEnabled = computed(\n () =>\n !!config.collaboration?.enabled &&\n planConfigInstance.hasFeature(\"collaboration\"),\n );\n\n function attach(context: CloudAttachContext): CloudAttachment {\n const editor = context.editor;\n editorRef = editor;\n\n provide(CLOUD_TRANSLATIONS_KEY, cloudTranslations);\n provide(AUTH_MANAGER_KEY, authManager);\n provide(AI_CONFIG_KEY, aiConfig);\n provide(SCORING_KEY, scoringInstance);\n\n const websocket = useWebSocket({ authManager, onError: config.onError });\n websocketRef = websocket;\n\n // Feeds the comments adapter's `subscribe`, which was handed to `init()` before\n // this socket existed.\n watch(\n websocket.channel,\n (channel) => {\n commentChannel.value = channel;\n },\n { immediate: true },\n );\n\n if (config.mcp?.enabled) {\n useMcpListener({\n editor,\n channel: websocket.channel,\n onOperation: config.mcp.onOperation,\n });\n }\n\n // Order matters: the broadcast wrapper replaces the editor's mutators so they\n // publish to peers, and `useEditorCore`'s history interceptor then wraps them\n // again to push history entries. Reversing it would push history for remote\n // operations and drift the two peers apart.\n if (config.collaboration?.enabled) {\n collaboration = useCollaboration({\n authManager,\n editor,\n channel: websocket.channel,\n onError: config.onError,\n onCollaboratorJoined: config.collaboration.onCollaboratorJoined,\n onCollaboratorLeft: config.collaboration.onCollaboratorLeft,\n onBlockLocked: config.collaboration.onBlockLocked,\n onBlockUnlocked: config.collaboration.onBlockUnlocked,\n }) as CloudCollaborationInstance;\n\n watch(\n () => collaboration!.lockedBlocks.value,\n (next) => {\n lockedBlocks.value = next;\n },\n { immediate: true },\n );\n\n useCollaborationBroadcast(editor, collaboration);\n }\n\n const panelState = useCloudPanelState();\n\n return {\n websocket,\n panelState,\n featureFlags,\n collaboration,\n isCollaborationEnabled,\n };\n }\n\n function ready(context: CloudReadyContext): CloudReady {\n const { core, capabilities } = context;\n coreRef = core;\n\n saveGate = useCloudSaveGate({\n issues: core.templateLint ? core.templateLint.issues : ref([]),\n planConfig: planConfigInstance.config,\n });\n\n collabWarning = useCollabUndoWarning({\n isCollaborationEnabled,\n getCollaboratorCount: () =>\n collaboration?.collaborators.value.length ?? 0,\n canUndo: core.history.canUndo,\n });\n\n // Mutated in place rather than re-provided: `useEditorCore` already provided\n // this exact object, so components injecting it see Cloud's entries on their\n // first render. Same pattern `versionHistory` uses in `Editor.vue`.\n //\n // `capabilities.comments` is *not* set here any more: comments became a shared\n // provider-backed feature, so `Editor.vue` builds the capability from\n // `useCommentsFeature` exactly as it does for saved blocks and test email, and\n // Cloud contributes only the two predicates below.\n capabilities.plan = planConfigInstance;\n capabilities.ai = aiConfig;\n\n // Registered unconditionally. `custom_blocks` and `theme_customization` used\n // to gate these — entitlements on editor capability the free editor grants,\n // and the only two things `applyPlanGates` would ever have had to do.\n if (config.customBlocks?.length) {\n core.registerCustomBlocks(config.customBlocks);\n }\n if (config.theme) {\n core.themeOverrides.value = config.theme;\n }\n\n return {\n saveGate,\n collabWarning,\n sessionError,\n retry: async () => {\n try {\n await authManager.initialize();\n sessionError.value = null;\n } catch (error) {\n sessionError.value =\n error instanceof Error ? error : new Error(\"Authentication failed\");\n }\n },\n };\n }\n\n const runtime: CloudRuntime = {\n lockedBlocks,\n isSavedBlocksAvailable: consumerSavedBlocks\n ? () => true\n : () =>\n config.savedBlocks !== false &&\n planConfigInstance.hasFeature(\"savedModules\"),\n isTestEmailAvailable: consumerTestEmail\n ? // Their sender, their rules — the `testEmail` plan feature licenses\n // Cloud's sending, and \"the template must be saved\" is a constraint of\n // Cloud's server-side render, not of an arbitrary backend.\n () => true\n : // All three matter and none implies another: the plan may grant the\n // feature while the project's token omits a recipient config, and Cloud\n // renders from the *saved* template so there must be one.\n () =>\n testEmailConfig.isEnabled.value &&\n featureFlags.canSendTestEmail.value &&\n featureFlags.hasTemplateSaved.value,\n // Three conditions, none implying another: the consumer may switch the feature\n // off, the plan meters comment storage and its realtime fan-out, and Cloud\n // anchors a comment to the *saved* template. (Whether a `user` exists is the\n // shared feature's own gate, not Cloud's.)\n isCommentsAvailable: () =>\n config.comments !== false &&\n planConfigInstance.hasFeature(\"commenting\") &&\n featureFlags.hasTemplateSaved.value,\n // A comment is anchored server-side, so a block that exists only on the canvas\n // has nothing stored to show. This is the last thing the deleted cloud editor\n // core carried (`savedBlockIds`), and it was always a comments concern rather\n // than an editor one.\n isBlockSaved: (blockId: string) =>\n collectSavedBlockIds(editorRef?.state.template ?? null).has(blockId),\n getSaveGate: () => saveGate,\n isRemoteOperation: () =>\n collaboration?._isProcessingRemoteOperation() ?? false,\n onBeforeUndo: () => collabWarning?.showCollabUndoWarning(),\n attach,\n ready,\n destroy() {\n websocketRef?.disconnect();\n config.onUnmount?.();\n },\n };\n\n return {\n runtime,\n providers: {\n templates,\n render,\n versionHistory,\n ...(savedBlocks ? { savedBlocks } : {}),\n testEmail,\n comments,\n ...(media ? { media } : {}),\n },\n user: cloudUser,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createCloudRuntime-D5bXzcTe.js","names":[],"sources":["../../../src/cloud/composables/useCloudFeatureFlags.ts","../../../src/cloud/composables/useCloudPanelState.ts","../../../src/cloud/composables/useCloudSaveGate.ts","../../../src/cloud/composables/useCollabUndoWarning.ts","../../../src/cloud/collectSavedBlockIds.ts","../../../src/cloud/createCloudRuntime.ts"],"sourcesContent":["import { computed, type ComputedRef } from \"vue\";\nimport type {\n UsePlanConfigReturn,\n UseAiConfigReturn,\n} from \"@templatical/core/cloud\";\n\nexport interface UseCloudFeatureFlagsOptions {\n planConfigInstance: UsePlanConfigReturn;\n aiConfig: UseAiConfigReturn;\n /** The loaded template's id, or `null` before one exists. */\n getTemplateId: () => string | null;\n}\n\nexport interface UseCloudFeatureFlagsReturn {\n canUseAiGeneration: ComputedRef<boolean>;\n canSendTestEmail: ComputedRef<boolean>;\n hasTemplateSaved: ComputedRef<boolean>;\n templateLimit: ComputedRef<number | null>;\n templateCount: ComputedRef<number>;\n}\n\n/**\n * Every entitlement check Cloud makes, in one place.\n *\n * The containment rule this exists for: entitlement checks go through here,\n * never inline in a component and never across a package boundary. With five\n * plan features left there is little excuse to break it.\n *\n * Save status is deliberately not here — it lives on `useTemplatesFeature`, which\n * the one shared header reads, and was never an entitlement. Footer branding is\n * likewise not gated: `config.branding !== false` decides it on any plan.\n */\nexport function useCloudFeatureFlags(\n options: UseCloudFeatureFlagsOptions,\n): UseCloudFeatureFlagsReturn {\n const { planConfigInstance, aiConfig, getTemplateId } = options;\n\n const canUseAiGeneration = computed(\n () =>\n planConfigInstance.hasFeature(\"aiGeneration\") &&\n aiConfig.hasAnyMenuFeature.value,\n );\n const canSendTestEmail = computed(() =>\n planConfigInstance.hasFeature(\"testEmail\"),\n );\n const hasTemplateSaved = computed(() => getTemplateId() !== null);\n const templateLimit = computed(\n () => planConfigInstance.config.value?.limits.maxTemplates ?? null,\n );\n const templateCount = computed(\n () => planConfigInstance.config.value?.templateCount ?? 0,\n );\n\n return {\n canUseAiGeneration,\n canSendTestEmail,\n hasTemplateSaved,\n templateLimit,\n templateCount,\n };\n}\n","import { computed, ref, type ComputedRef, type Ref } from \"vue\";\nimport { onClickOutside } from \"@vueuse/core\";\nimport type { AiFeature } from \"../components/AiFeatureMenu.vue\";\n\nexport interface UseCloudPanelStateReturn {\n activePanel: Ref<RightPanel | null>;\n aiChatOpen: ComputedRef<boolean> & { value: boolean };\n scoringPanelOpen: ComputedRef<boolean> & { value: boolean };\n designReferenceOpen: ComputedRef<boolean> & { value: boolean };\n commentsOpen: ComputedRef<boolean> & { value: boolean };\n aiMenuOpen: Ref<boolean>;\n aiMenuRef: Ref<HTMLElement | null>;\n rightPanelOpen: ComputedRef<boolean>;\n activeAiFeature: ComputedRef<AiFeature | null>;\n aiButtonActive: ComputedRef<boolean>;\n toggleAiMenu: () => void;\n handleAiFeatureSelect: (feature: AiFeature) => void;\n}\n\ntype RightPanel = \"ai-chat\" | \"scoring\" | \"design-reference\" | \"comments\";\n\nexport function useCloudPanelState(): UseCloudPanelStateReturn {\n const activePanel = ref<RightPanel | null>(null);\n\n const aiChatOpen = computed({\n get: () => activePanel.value === \"ai-chat\",\n set: (v) => (activePanel.value = v ? \"ai-chat\" : null),\n });\n const scoringPanelOpen = computed({\n get: () => activePanel.value === \"scoring\",\n set: (v) => (activePanel.value = v ? \"scoring\" : null),\n });\n const designReferenceOpen = computed({\n get: () => activePanel.value === \"design-reference\",\n set: (v) => (activePanel.value = v ? \"design-reference\" : null),\n });\n const commentsOpen = computed({\n get: () => activePanel.value === \"comments\",\n set: (v) => (activePanel.value = v ? \"comments\" : null),\n });\n\n const aiMenuOpen = ref(false);\n const aiMenuRef = ref<HTMLElement | null>(null);\n\n const rightPanelOpen = computed(() => activePanel.value !== null);\n\n const activeAiFeature = computed<AiFeature | null>(() => {\n const p = activePanel.value;\n if (p === \"ai-chat\" || p === \"design-reference\" || p === \"scoring\")\n return p;\n return null;\n });\n\n const aiButtonActive = computed(\n () =>\n aiMenuOpen.value ||\n activePanel.value === \"ai-chat\" ||\n activePanel.value === \"design-reference\" ||\n activePanel.value === \"scoring\",\n );\n\n function toggleAiMenu(): void {\n aiMenuOpen.value = !aiMenuOpen.value;\n }\n\n function handleAiFeatureSelect(feature: AiFeature): void {\n aiMenuOpen.value = false;\n activePanel.value = activePanel.value === feature ? null : feature;\n }\n\n onClickOutside(aiMenuRef, () => {\n aiMenuOpen.value = false;\n });\n\n return {\n activePanel,\n aiChatOpen,\n scoringPanelOpen,\n designReferenceOpen,\n commentsOpen,\n aiMenuOpen,\n aiMenuRef,\n rightPanelOpen,\n activeAiFeature,\n aiButtonActive,\n toggleAiMenu,\n handleAiFeatureSelect,\n };\n}\n","import { computed, ref, type ComputedRef, type Ref } from \"vue\";\nimport type { PlanConfig } from \"@templatical/types\";\nimport type { LintIssue } from \"../../composables/useTemplateLint\";\n\nexport interface UseCloudSaveGateOptions {\n /** Reactive accessibility issues from `useTemplateLint`. */\n issues: Ref<LintIssue[]>;\n /** Reactive plan config from the server. */\n planConfig: Ref<PlanConfig | null>;\n}\n\nexport interface UseCloudSaveGateReturn {\n /** True when the gate would block a save click given current state. */\n shouldBlock: ComputedRef<boolean>;\n /** Errors that would block the save. Empty when `shouldBlock` is false. */\n blockingIssues: ComputedRef<LintIssue[]>;\n /** Modal visibility — toggled by `tryRunSave` and `cancel`. */\n modalOpen: Ref<boolean>;\n /**\n * Wraps a save callback. Returns `true` when the save was invoked\n * (blocking disabled or no errors), `false` when the modal opened\n * instead. Caller can `await` the returned promise to know when the\n * save settled.\n */\n tryRunSave: (run: () => Promise<unknown> | unknown) => Promise<boolean>;\n /**\n * Runs the save only when the gate would not block, and does **nothing** when\n * it would — no modal, no save, nothing pending. Returns whether it ran.\n *\n * This is the autosave path. A modal on a debounce timer would interrupt\n * typing, but simply saving anyway would demote `blockOnError` from a server\n * policy to a manual-save-only speed bump. Skipping leaves the template dirty\n * and the header saying \"unsaved\", which is true, and the reason stays visible\n * in the Issues panel. The next edit re-arms the debounce, so fixing the issue\n * is what lets the save through — no retry timer needed.\n */\n runUnlessBlocked: (run: () => Promise<unknown> | unknown) => Promise<boolean>;\n /** Force-run the pending save, bypassing the gate. */\n confirmAndSave: () => Promise<void>;\n /** Dismiss the modal without saving. */\n cancel: () => void;\n}\n\n/**\n * Cloud-only save-gate. When `planConfig.accessibility.blockOnError === true`\n * and the linter reports any error-severity issues, intercept the save\n * click and surface a confirmation modal listing the blockers. The user\n * can dismiss to fix issues, or click \"Save anyway\" to bypass — the gate\n * does NOT enforce a hard block, it surfaces a deliberate choice.\n *\n * Server policy is the source of truth for `blockOnError`; consumer-side\n * `accessibility` options can't override it.\n */\nexport function useCloudSaveGate(\n opts: UseCloudSaveGateOptions,\n): UseCloudSaveGateReturn {\n const modalOpen = ref(false);\n let pending: (() => Promise<unknown> | unknown) | null = null;\n\n const blockOnError = computed(\n () => opts.planConfig.value?.accessibility?.blockOnError === true,\n );\n\n const blockingIssues = computed(() =>\n blockOnError.value\n ? opts.issues.value.filter((i) => i.severity === \"error\")\n : [],\n );\n\n const shouldBlock = computed(() => blockingIssues.value.length > 0);\n\n async function tryRunSave(\n run: () => Promise<unknown> | unknown,\n ): Promise<boolean> {\n if (!shouldBlock.value) {\n await run();\n return true;\n }\n pending = run;\n modalOpen.value = true;\n return false;\n }\n\n async function runUnlessBlocked(\n run: () => Promise<unknown> | unknown,\n ): Promise<boolean> {\n if (shouldBlock.value) return false;\n await run();\n return true;\n }\n\n async function confirmAndSave(): Promise<void> {\n const run = pending;\n pending = null;\n modalOpen.value = false;\n if (run) {\n await run();\n }\n }\n\n function cancel(): void {\n pending = null;\n modalOpen.value = false;\n }\n\n return {\n shouldBlock,\n blockingIssues,\n modalOpen,\n tryRunSave,\n runUnlessBlocked,\n confirmAndSave,\n cancel,\n };\n}\n","import { type ComputedRef, type Ref, ref } from \"vue\";\nimport { useTimeoutFn } from \"@vueuse/core\";\nimport { COLLAB_UNDO_WARNING_MS } from \"../../constants/timeouts\";\n\nexport interface UseCollabUndoWarningOptions {\n /** Whether collaboration is currently enabled (reactive). */\n isCollaborationEnabled: ComputedRef<boolean>;\n /** Returns the current list of collaborators. */\n getCollaboratorCount: () => number;\n /** Whether the history stack has entries to undo. */\n canUndo: ComputedRef<boolean>;\n}\n\nexport interface UseCollabUndoWarningReturn {\n collabUndoWarningVisible: Ref<boolean>;\n showCollabUndoWarning: () => void;\n}\n\nexport function useCollabUndoWarning(\n options: UseCollabUndoWarningOptions,\n): UseCollabUndoWarningReturn {\n const { isCollaborationEnabled, getCollaboratorCount, canUndo } = options;\n\n const collabUndoWarningFired = ref(false);\n const collabUndoWarningVisible = ref(false);\n\n const { start: startCollabUndoWarningTimeout } = useTimeoutFn(\n () => {\n collabUndoWarningVisible.value = false;\n },\n COLLAB_UNDO_WARNING_MS,\n { immediate: false },\n );\n\n function showCollabUndoWarning(): void {\n if (\n collabUndoWarningFired.value ||\n !isCollaborationEnabled.value ||\n getCollaboratorCount() === 0 ||\n !canUndo.value\n ) {\n return;\n }\n\n collabUndoWarningFired.value = true;\n collabUndoWarningVisible.value = true;\n startCollabUndoWarningTimeout();\n }\n\n return {\n collabUndoWarningVisible,\n showCollabUndoWarning,\n };\n}\n","/**\n * Just enough of a stored template to walk its ids — deliberately structural\n * rather than `Template`, because the caller reads `editor.state`, which is\n * `DeepReadonly` and so not assignable to the mutable contract type.\n */\ninterface SavedBlockIdSource {\n content?: {\n blocks?: readonly {\n id: string;\n type: string;\n children?: readonly (readonly { id: string }[])[];\n }[];\n };\n}\n\n/**\n * Every block id present in the **stored** template, sections' children\n * included.\n *\n * This is the last thing the deleted Cloud editor core carried over the OSS one\n * (`savedBlockIds`), and it never belonged there: its only reader gates a\n * comment filter on whether the block exists server-side, which makes it a\n * *comments* dependency. It travels with that feature accordingly, and reaches\n * `CommentsSidebar` through `capabilities.comments.isBlockSaved`.\n *\n * Derived on demand rather than memoised: `state.template` only changes on a\n * create / load / save round-trip, and the one caller runs on a user filtering\n * the comments panel.\n */\nexport function collectSavedBlockIds(\n template: SavedBlockIdSource | null | undefined,\n): Set<string> {\n const ids = new Set<string>();\n const blocks = template?.content?.blocks;\n if (!blocks) return ids;\n\n for (const block of blocks) {\n ids.add(block.id);\n if (block.type === \"section\" && block.children) {\n for (const column of block.children) {\n for (const child of column) {\n ids.add(child.id);\n }\n }\n }\n }\n return ids;\n}\n","import { computed, provide, ref, watch } from \"vue\";\nimport {\n AuthManager,\n isFatalAuthError,\n performHealthCheck,\n useAiConfig,\n useCollaboration,\n useCollaborationBroadcast,\n useExport,\n useMcpListener,\n usePlanConfig,\n resolveExportFonts,\n resolveWebSocketConfig,\n createCloudCommentsProvider,\n createCloudMediaProvider,\n createCloudRenderProvider,\n createCloudSavedBlocksProvider,\n createCloudTemplatesProvider,\n createCloudTestEmailProvider,\n createCloudVersionHistoryProvider,\n useTemplateScoring,\n useTestEmail,\n useWebSocket,\n type RealtimeChannel,\n} from \"@templatical/core/cloud\";\nimport type { UseEditorReturn } from \"@templatical/core\";\nimport type {\n CommentsOptions,\n CommentsProvider,\n EditorUser,\n MediaOptions,\n MediaProvider,\n RenderProvider,\n SavedBlocksOptions,\n SavedBlocksProvider,\n Template,\n TemplateContent,\n TemplatePatch,\n TemplatesOptions,\n TemplatesProvider,\n TestEmailOptions,\n TestEmailProvider,\n VersionHistoryOptions,\n VersionHistoryProvider,\n} from \"@templatical/types\";\n\nimport type { CloudTranslations } from \"../i18n\";\nimport { preRenderCustomBlocks } from \"../utils/preRenderCustomBlocks\";\nimport { logger } from \"../utils/logger\";\nimport type { UseEditorCoreReturn } from \"../composables/useEditorCore\";\nimport {\n AI_CONFIG_KEY,\n AUTH_MANAGER_KEY,\n CLOUD_TRANSLATIONS_KEY,\n SCORING_KEY,\n} from \"../keys\";\n\nimport { useCloudFeatureFlags } from \"./composables/useCloudFeatureFlags\";\nimport { useCloudPanelState } from \"./composables/useCloudPanelState\";\nimport {\n useCloudSaveGate,\n type UseCloudSaveGateReturn,\n} from \"./composables/useCloudSaveGate\";\nimport {\n useCollabUndoWarning,\n type UseCollabUndoWarningReturn,\n} from \"./composables/useCollabUndoWarning\";\nimport { collectSavedBlockIds } from \"./collectSavedBlockIds\";\nimport type {\n CloudAttachContext,\n CloudAttachment,\n CloudCollaborationInstance,\n CloudReady,\n CloudReadyContext,\n CloudRuntime,\n} from \"./runtime\";\nimport type { TemplaticalCloudEditorConfig } from \"./cloudConfig\";\n\nexport interface BootstrapCloudOptions {\n config: TemplaticalCloudEditorConfig;\n cloudTranslations: CloudTranslations;\n}\n\n/**\n * What {@link bootstrapCloud} hands back: a set of ordinary `init()` config\n * values, plus the runtime for the few things that must run inside the editor\n * component's `setup()`.\n */\nexport interface CloudBootstrap {\n runtime: CloudRuntime;\n providers: {\n templates: TemplatesProvider;\n render: RenderProvider;\n versionHistory: VersionHistoryProvider;\n /** Absent when `savedBlocks: false` — the feature is then off entirely. */\n savedBlocks?: SavedBlocksProvider;\n testEmail: TestEmailProvider;\n comments: CommentsProvider;\n /** Absent when `media: false` — Browse is then off unless `onRequestMedia` is set. */\n media?: MediaProvider;\n };\n /**\n * Who is editing, from the JWT — `init({ user })`'s value for a Cloud session.\n *\n * `undefined` when the project's token carries no `user` claim, which makes\n * comments unavailable rather than anonymous. Not a key `initCloud()` accepts:\n * Cloud's comment writes are signed against this same claim, so a\n * consumer-supplied identity would only be able to disagree with it.\n */\n user?: EditorUser;\n}\n\n/**\n * Pick only the event members off a consumer-supplied `templates` value.\n *\n * A whitelist, never a spread. The config type says `TemplatesOptions`, but a\n * JavaScript consumer is unchecked, so the object can carry anything —\n * `load`/`create`/`save` are already shadowed by the literal defining them\n * after the spread, and this drops everything else so the guarantee never\n * depends on that ordering surviving a later edit.\n *\n * Each member is also type-checked, not merely truthiness-checked: a value\n * like `onSaved: \"yes\"` would otherwise reach core and throw at save time,\n * inside a call the consumer never made.\n */\nfunction eventsOf(value: TemplatesOptions | undefined): TemplatesOptions {\n if (!value) return {};\n const { onSaved, onCreated, onLoaded } = value;\n return {\n ...(typeof onSaved === \"function\" ? { onSaved } : {}),\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onLoaded === \"function\" ? { onLoaded } : {}),\n };\n}\n\n/**\n * Fails to compile when `TemplatesOptions` gains a member outside the six\n * named below. Cloud picks that object apart by name in two places —\n * `eventsOf` above and `initCloud`'s merge in `index.ts` — so a seventh\n * member forces a **deliberate decision** about which of the two forwards\n * it. The check cannot make that decision itself: adding the new name to the\n * `Exclude` list below satisfies the compiler on its own and forwards\n * nothing by itself, and it has no way to tell an event (belongs in\n * `eventsOf`) from config (belongs in the `index.ts` merge).\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below\n * is what forces the check — it fails to compile the moment a member falls\n * outside the six named here.\n */\ntype _TemplatesOptionsForwarded =\n Exclude<\n keyof TemplatesOptions,\n | \"autoSave\"\n | \"unsavedChangesGuard\"\n | \"nameField\"\n | \"onSaved\"\n | \"onCreated\"\n | \"onLoaded\"\n > extends never\n ? true\n : never;\nconst _templatesOptionsForwarded: _TemplatesOptionsForwarded = true;\n\n/**\n * Pick only the event members off a consumer-supplied `comments` value.\n *\n * A whitelist, never a spread. The config type says `CommentsOptions`, but a\n * JavaScript consumer is unchecked, so the object can carry anything —\n * `list`/`create`/`update`/`delete`/`setResolved` are already shadowed by the\n * spread of Cloud's own adapter that follows this in the provider literal, and\n * this drops everything else so the guarantee never depends on that ordering\n * surviving a later edit.\n *\n * Each member is also type-checked, not merely truthiness-checked: a value\n * like `onCreated: \"yes\"` would otherwise reach core and throw at\n * comment-creation time, inside a call the consumer never made.\n */\nfunction commentEventsOf(\n value: false | CommentsOptions | undefined,\n): CommentsOptions {\n if (!value) return {};\n const { onCreated, onUpdated, onDeleted, onResolved, onUnresolved } = value;\n return {\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onUpdated === \"function\" ? { onUpdated } : {}),\n ...(typeof onDeleted === \"function\" ? { onDeleted } : {}),\n ...(typeof onResolved === \"function\" ? { onResolved } : {}),\n ...(typeof onUnresolved === \"function\" ? { onUnresolved } : {}),\n };\n}\n\n/**\n * Fails to compile when `CommentsOptions` gains a member outside the five\n * named below. Every member of `CommentsOptions` is an event, and\n * `commentEventsOf` above is the only place that forwards them — unlike\n * `TemplatesOptions`, there is no second merge in `index.ts`, since comments\n * carries no config booleans for that merge to combine. A sixth member has\n * exactly one place to be added: this list and `commentEventsOf`'s destructure,\n * together.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below is\n * what forces the check — it fails to compile the moment a member falls\n * outside the five named here.\n */\ntype _CommentsOptionsForwarded =\n Exclude<\n keyof CommentsOptions,\n \"onCreated\" | \"onUpdated\" | \"onDeleted\" | \"onResolved\" | \"onUnresolved\"\n > extends never\n ? true\n : never;\nconst _commentsOptionsForwarded: _CommentsOptionsForwarded = true;\n\n/**\n * Pick only the event members off a consumer-supplied `savedBlocks` value.\n *\n * A whitelist, never a spread. `savedBlocks` accepts a boolean, an\n * events-only `SavedBlocksOptions`, or a full `SavedBlocksProvider` — this is\n * only ever called on the first two, since a full provider replaces Cloud's\n * adapter outright and is used as-is (see `consumerSavedBlocks` below). A\n * non-object value (`true`, `undefined`, `false`) carries no keys to pick, so\n * it returns `{}` rather than throwing on the destructure.\n *\n * Each member is also type-checked, not merely truthiness-checked: a value\n * like `onCreated: \"yes\"` would otherwise reach core and throw at\n * saved-block-creation time, inside a call the consumer never made.\n */\nfunction savedBlocksEventsOf(\n value: TemplaticalCloudEditorConfig[\"savedBlocks\"],\n): SavedBlocksOptions {\n if (typeof value !== \"object\" || value === null) return {};\n const { onCreated, onUpdated, onDeleted } = value;\n return {\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onUpdated === \"function\" ? { onUpdated } : {}),\n ...(typeof onDeleted === \"function\" ? { onDeleted } : {}),\n };\n}\n\n/**\n * Fails to compile when `SavedBlocksOptions` gains a member outside the three\n * named below. `savedBlocksEventsOf` above is the only place that forwards\n * them, so a fourth member has exactly one place to be added: this list and\n * that function's destructure, together.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below\n * is what forces the check — it fails to compile the moment a member falls\n * outside the three named here.\n */\ntype _SavedBlocksOptionsForwarded =\n Exclude<\n keyof SavedBlocksOptions,\n \"onCreated\" | \"onUpdated\" | \"onDeleted\"\n > extends never\n ? true\n : never;\nconst _savedBlocksOptionsForwarded: _SavedBlocksOptionsForwarded = true;\n\n/**\n * Pick `onSent` and `defaultRecipient` off a consumer-supplied `testEmail`\n * value.\n *\n * A whitelist, like `savedBlocksEventsOf` — but note what it does NOT pick:\n * `includeMjml` and `allowedRecipients` stay Cloud's own whenever Cloud's\n * sender is in play, so they are never read here even though\n * `TestEmailOptions` declares them (see `_TestEmailOptionsForwarded` below).\n * `defaultRecipient` has no such conflict — Cloud's provider never defines\n * it, and `useTestEmailFeature` already discards a value outside\n * `allowedRecipients`, so a consumer's choice can only ever pre-fill an\n * address already on Cloud's own signed list, never smuggle in one outside\n * it. `onSent` is a plain notification with no conflict either, so both\n * cross over.\n *\n * The result is assigned ONTO Cloud's own provider with `Object.assign`\n * (never spread together with it) at the call site — that provider's\n * `allowedRecipients` is a live getter over the JWT-derived allowlist, and a\n * spread reads every own property through `[[Get]]`, freezing the getter's\n * current value into a plain property on the new object. `Object.assign`\n * with the cloud provider as the *target* only ever writes the keys this\n * function returns, so the getter is never read and never disturbed.\n */\nfunction testEmailEventsOf(\n value: TemplaticalCloudEditorConfig[\"testEmail\"],\n): Pick<TestEmailOptions, \"onSent\" | \"defaultRecipient\"> {\n if (typeof value !== \"object\" || value === null) return {};\n const { onSent, defaultRecipient } = value;\n return {\n ...(typeof onSent === \"function\" ? { onSent } : {}),\n ...(typeof defaultRecipient === \"string\" ? { defaultRecipient } : {}),\n };\n}\n\n/**\n * Fails to compile when `TestEmailOptions` gains a member outside the four\n * named below. `onSent` and `defaultRecipient` are forwarded by\n * `testEmailEventsOf` above; `includeMjml` and `allowedRecipients` stay\n * Cloud's own whenever Cloud's sender is in play (Cloud renders server-side\n * rather than from a client MJML pass, and the allowlist is the signed one\n * from the project's JWT, not a client-supplied one). A fifth member still\n * forces a deliberate decision the same way a fourth `SavedBlocksOptions`\n * member does: whether it joins the forwarded pair or stays excluded for the\n * same reason as the other two.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below\n * is what forces the check — it fails to compile the moment a member falls\n * outside the four named here.\n */\ntype _TestEmailOptionsForwarded =\n Exclude<\n keyof TestEmailOptions,\n \"includeMjml\" | \"allowedRecipients\" | \"defaultRecipient\" | \"onSent\"\n > extends never\n ? true\n : never;\nconst _testEmailOptionsForwarded: _TestEmailOptionsForwarded = true;\n\n/**\n * Pick only the event members off a consumer-supplied `media` value.\n *\n * A whitelist, never a spread. `media` accepts `false`, an events-only\n * {@link MediaOptions}, or a full {@link MediaProvider} — this is only ever\n * called on the first two, since a full provider replaces Cloud's adapter\n * outright and is used as-is (see `consumerMedia` below). A non-object\n * value (`undefined`, `false`) carries no keys to pick, so it returns `{}`\n * rather than throwing on the destructure.\n *\n * What it does NOT pick: `maxFileSize` and `mimeTypes` stay Cloud's own\n * whenever Cloud's store is in play (Cloud's plan owns those limits), so\n * they are never read here even though `MediaOptions` declares them (see\n * `_MediaOptionsForwarded` below).\n *\n * The result is assigned ONTO Cloud's own provider with `Object.assign`\n * (never spread together with it) at the call site — that provider's\n * `storage` / `maxFileSize` / `mimeTypes` read plan config live, and a\n * spread reads every own property through `[[Get]]`, freezing each\n * getter's current value into a plain property on the new object.\n * `Object.assign` with the cloud provider as the *target* only ever\n * writes the keys this function returns, so those getters are never\n * read and never disturbed.\n */\nfunction mediaEventsOf(\n value: TemplaticalCloudEditorConfig[\"media\"],\n): Pick<MediaOptions, \"onCreated\" | \"onUpdated\" | \"onDeleted\"> {\n if (typeof value !== \"object\" || value === null) return {};\n const { onCreated, onUpdated, onDeleted } = value;\n return {\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onUpdated === \"function\" ? { onUpdated } : {}),\n ...(typeof onDeleted === \"function\" ? { onDeleted } : {}),\n };\n}\n\n/**\n * Fails to compile when `MediaOptions` gains a member outside the five\n * named below. `onCreated` / `onUpdated` / `onDeleted` are forwarded by\n * `mediaEventsOf` above; `maxFileSize` and `mimeTypes` stay Cloud's own\n * whenever Cloud's store is in play (Cloud's plan owns those limits). A\n * sixth member still forces a deliberate decision the same way a fifth\n * `TestEmailOptions` member does: whether it joins the forwarded trio or\n * stays excluded for the same reason as the other two.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias\n * nothing reads, so a `never` result would sit there silently. The\n * assignment below is what forces the check — it fails to compile the\n * moment a member falls outside the five named here.\n */\ntype _MediaOptionsForwarded =\n Exclude<\n keyof MediaOptions,\n \"onCreated\" | \"onUpdated\" | \"onDeleted\" | \"maxFileSize\" | \"mimeTypes\"\n > extends never\n ? true\n : never;\nconst _mediaOptionsForwarded: _MediaOptionsForwarded = true;\n\n/**\n * Pick only the event members off a consumer-supplied `versionHistory`\n * value.\n *\n * A whitelist, never a spread — the config type says `VersionHistoryOptions`,\n * but a JavaScript consumer is unchecked, so the object can carry anything.\n * `versionHistory` never accepts a full provider (see the rejected-keys block\n * below), so unlike `savedBlocksEventsOf` / `testEmailEventsOf` this is\n * always called on the whole config value.\n */\nfunction versionHistoryEventsOf(\n value: VersionHistoryOptions | undefined,\n): VersionHistoryOptions {\n if (!value) return {};\n const { onCreated, onRestored } = value;\n return {\n ...(typeof onCreated === \"function\" ? { onCreated } : {}),\n ...(typeof onRestored === \"function\" ? { onRestored } : {}),\n };\n}\n\n/**\n * Fails to compile when `VersionHistoryOptions` gains a member outside the\n * two named below. `versionHistoryEventsOf` above is the only place that\n * forwards them, so a third member has exactly one place to be added: this\n * list and that function's destructure, together.\n *\n * The type alone checks nothing: TypeScript never evaluates an alias nothing\n * reads, so a `never` result would sit there silently. The assignment below\n * is what forces the check — it fails to compile the moment a member falls\n * outside the two named here.\n */\ntype _VersionHistoryOptionsForwarded =\n Exclude<keyof VersionHistoryOptions, \"onCreated\" | \"onRestored\"> extends never\n ? true\n : never;\nconst _versionHistoryOptionsForwarded: _VersionHistoryOptionsForwarded = true;\n\n/**\n * A comma list with a final \"and\" — \"a\"; \"a and b\"; \"a, b and c\". The\n * ignored-methods warnings below each name however many storage methods a\n * consumer actually passed, and `Array.join(\" and \")` only reads correctly\n * for exactly two.\n */\nfunction joinWithAnd(items: string[]): string {\n if (items.length < 2) return items.join(\"\");\n if (items.length === 2) return items.join(\" and \");\n return `${items.slice(0, -1).join(\", \")} and ${items[items.length - 1]}`;\n}\n\n/**\n * Cloud's bootstrap and adapter wiring, in one place, run **before the editor\n * mounts**.\n *\n * This replaces `useCloudInitialization`, which owned a second `useEditor`, a\n * second `useEditorCore` and a post-mount async dance with its own loading and\n * error states. The dance is gone: auth, the health check and the plan fetch all\n * resolve here, and a failure rejects `initCloud()` rather than mounting an\n * editor that cannot work. What is left is adapter construction.\n *\n * Two things deliberately stay Cloud-only:\n *\n * - **Entitlements.** In an all-BYO world there are no plans, so `planConfig` is\n * Cloud's commercial layer above the provider set rather than a provider\n * itself. It is down to five booleans, each metering a resource Cloud buys.\n * - **Mid-session failure.** `init()` cannot fail after it mounts and should not\n * grow the ability, so the error overlay lives on this side of the seam.\n */\nexport async function bootstrapCloud(\n options: BootstrapCloudOptions,\n): Promise<CloudBootstrap> {\n const { config, cloudTranslations } = options;\n\n // --- Late-bound editor access ---------------------------------------------\n //\n // The providers below are built before there is an editor to read. Each\n // reaches it through these holders, filled by `attach()` / `ready()` — which is\n // what lets them be handed to `init()` as ordinary config keys.\n let editorRef: UseEditorReturn | null = null;\n let coreRef: UseEditorCoreReturn | null = null;\n let websocketRef: ReturnType<typeof useWebSocket> | null = null;\n let collaboration: CloudCollaborationInstance | null = null;\n let collabWarning: UseCollabUndoWarningReturn | null = null;\n let saveGate: UseCloudSaveGateReturn | null = null;\n\n const sessionError = ref<Error | null>(null);\n const lockedBlocks = ref<Map<string, unknown>>(new Map());\n /**\n * Cloud's presence channel, forward-declared for the comments adapter's\n * `subscribe`. `useWebSocket` can only be built in `attach()` (it needs the\n * editor), while the provider is handed to `init()` before that — so the adapter\n * watches this and rebinds when the real channel lands.\n */\n const commentChannel = ref<RealtimeChannel | null>(null);\n\n function requireEditor(): UseEditorReturn {\n if (!editorRef) {\n throw new Error(\"[Templatical] The Cloud editor is not mounted yet.\");\n }\n return editorRef;\n }\n\n function getTemplateId(): string | null {\n return editorRef?.state.template?.id ?? null;\n }\n\n // --- Auth + plan ----------------------------------------------------------\n\n const authManager = new AuthManager({\n ...config.auth,\n // Only a *fatal* refusal raises the overlay. A 4xx means the endpoint\n // rejected the credentials, so every subsequent request fails the same way\n // and the session really is over. A network blip or a 5xx resolves on its\n // own, and blanking a mounted editor over one interrupts someone mid-edit on\n // a template that is probably unsaved — a worse outcome than the blip.\n //\n // The consumer hears about both: `onError` fires either way, and\n // `AuthManager` re-throws regardless, so a caller that cannot proceed still\n // finds out.\n onError: (error: Error) => {\n if (isFatalAuthError(error)) {\n sessionError.value = error;\n }\n config.onError?.(error);\n },\n });\n\n const planConfigInstance = usePlanConfig({\n authManager,\n onError: config.onError,\n });\n\n await authManager.initialize();\n\n const healthResult = await performHealthCheck({ authManager });\n if (!healthResult.api.ok) {\n throw new Error(\"Health check failed: API is not reachable\");\n }\n if (!healthResult.auth.ok) {\n throw new Error(\n `Health check failed: authentication error${healthResult.auth.error ? ` - ${healthResult.auth.error}` : \"\"}`,\n );\n }\n if (!healthResult.websocket.ok) {\n logger.warn(\n \"WebSocket health check failed:\",\n healthResult.websocket.error ?? \"unknown error\",\n \"-- real-time features will be disabled.\",\n );\n }\n\n await planConfigInstance.fetchConfig();\n\n // The bootstrap itself is what the overlay would have covered, and it just\n // succeeded — so anything `onError` recorded on the way here is stale.\n sessionError.value = null;\n\n // --- Rejected consumer keys ----------------------------------------------\n //\n // `render` is not declared on `TemplaticalCloudEditorConfig`, so it only\n // fires for JavaScript consumers — warned rather than silently dropped,\n // because the symptom (a store that stays empty while Cloud's fills up)\n // reads as a broken provider rather than a rejected one. `templates`,\n // `comments` and `versionHistory` ARE declared, but typed narrowly as\n // `TemplatesOptions`, `CommentsOptions` and `VersionHistoryOptions` — a\n // JavaScript consumer can still hand over a full provider, so its storage\n // methods are named and ignored the same way, while any events they carry\n // reach `eventsOf` / `commentEventsOf` / `versionHistoryEventsOf` below\n // regardless of this check.\n const consumerTemplates = (config as { templates?: Record<string, unknown> })\n .templates;\n // Presence, not `typeof === \"function\"` — see the matching comment on\n // `ignoredCommentMethods` below: a stated-but-ignored decision like\n // `save: false` is as much a signal as a stray function override.\n const ignoredTemplateMethods = [\"load\", \"create\", \"save\"].filter(\n (key) => typeof consumerTemplates?.[key] !== \"undefined\",\n );\n if (ignoredTemplateMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredTemplateMethods.map((key) => `templates.${key}`),\n )} — the template id is the join key for collaboration, ` +\n \"version history, comments, AI rewrite, scoring and the server-side \" +\n \"export, so an id Cloud never issued would degrade all six. Your \" +\n \"event handlers were kept. Use init() to bring your own storage.\",\n );\n }\n const consumerVersionHistory = (\n config as { versionHistory?: Record<string, unknown> }\n ).versionHistory;\n // Presence, not `typeof === \"function\"`: a stated-but-ignored decision like\n // `restore: false` is as much a signal as a stray function override, and\n // both must be named here or the consumer never learns it was dropped.\n const ignoredVersionHistoryMethods = [\n \"list\",\n \"get\",\n \"create\",\n \"restore\",\n ].filter((key) => typeof consumerVersionHistory?.[key] !== \"undefined\");\n if (ignoredVersionHistoryMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredVersionHistoryMethods.map((key) => `versionHistory.${key}`),\n )} — a version is keyed to a template id Cloud issued, so Cloud owns ` +\n \"its history. Your event handlers were kept. Use init() to bring \" +\n \"your own storage.\",\n );\n }\n const consumerComments = (config as { comments?: Record<string, unknown> })\n .comments;\n // Presence, not `typeof === \"function\"`: a stated-but-ignored decision like\n // `create: false` is as much a signal as a stray function override, and both\n // must be named here or the consumer never learns it was dropped.\n const ignoredCommentMethods = [\n \"list\",\n \"create\",\n \"update\",\n \"delete\",\n \"setResolved\",\n \"subscribe\",\n ].filter((key) => typeof consumerComments?.[key] !== \"undefined\");\n if (ignoredCommentMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredCommentMethods.map((key) => `comments.${key}`),\n )} — a comment is keyed to a template id Cloud issued, and its ` +\n \"author is signed by the auth token, so Cloud owns the conversation. \" +\n \"Your event handlers were kept. Use init() to bring your own storage.\",\n );\n }\n // Rejected for a different reason than the three above: not the join key, but\n // because Cloud renders on its own for test email, scheduled sends and API\n // exports (`createCloudTestEmailProvider` calls `exportHtml` directly). A\n // consumer provider would have changed `toMjml()` / `toHtml()` and nothing\n // else, so what the user previewed and exported was not what Cloud delivered —\n // and Cloud's output is a deliberate superset (countdown GIFs, composited video\n // thumbnails), so the consumer's was also worse for those blocks.\n if ((config as { render?: unknown }).render) {\n logger.warn(\n \"initCloud does not accept a `render` provider — Cloud renders \" +\n \"server-side for test email, sends and exports, so a supplied renderer \" +\n \"would change only what you preview and export, never what Cloud \" +\n \"delivers. The supplied provider is ignored. For your own MJML, call \" +\n \"renderToMjml(editor.getContent()) from @templatical/renderer.\",\n );\n }\n\n // --- Providers ------------------------------------------------------------\n\n function connectRealtime(template: Template): void {\n const websocketConfig = planConfigInstance.config.value?.websocket;\n if (!websocketRef || !websocketConfig) return;\n websocketRef.connect(template.id, resolveWebSocketConfig(websocketConfig));\n }\n\n const baseTemplates = createCloudTemplatesProvider(authManager);\n const baseCreate = baseTemplates.create;\n const baseSave = baseTemplates.save;\n\n /**\n * Cloud's templates adapter plus the choreography the template id anchors:\n * the websocket joins the template's presence channel. The consumer's\n * `onSaved` / `onCreated` / `onLoaded` ride along via `eventsOf` — core calls\n * them once the editor has settled, so the adapter itself never invokes them.\n *\n * That choreography belongs in the adapter rather than in an editor-side\n * lifecycle composable, because it *is* adapter business — Cloud is what keys\n * realtime off the id it issued. `useCloudLifecycle` existed only to hold it.\n *\n * `save` pre-renders custom blocks, which is why it is wrapped too.\n */\n const templates: TemplatesProvider = {\n ...eventsOf(config.templates),\n load: async (id: string) => {\n const template = await baseTemplates.load(id);\n connectRealtime(template);\n return template;\n },\n create:\n typeof baseCreate === \"function\"\n ? async (input: { name?: string; content: TemplateContent }) => {\n const template = await baseCreate(input);\n connectRealtime(template);\n return template;\n }\n : false,\n save:\n typeof baseSave === \"function\"\n ? async (id: string, patch: TemplatePatch) => {\n if (coreRef && editorRef) {\n await preRenderCustomBlocks(\n editorRef.content.value,\n coreRef.registry,\n );\n }\n return baseSave(id, patch);\n }\n : false,\n };\n\n // Always Cloud's — see the rejected-keys block above. Cloud renders\n // independently for delivery, so a second renderer could only disagree with it.\n const render: RenderProvider = createCloudRenderProvider({\n authManager,\n getTemplateId,\n // Plain `editor.save()`: the templates adapter below already pre-renders\n // custom blocks on every save, which is exactly what the render endpoint\n // needs, since it exports from the stored copy rather than from\n // `payload.content`.\n save: () => requireEditor().save(),\n });\n\n // The consumer's `onCreated` / `onRestored` ride along via\n // `versionHistoryEventsOf` — core calls them once the editor has settled, so\n // the adapter itself never invokes them. `versionHistory` never accepts a\n // full provider (see the rejected-keys block above), so this always merges\n // onto Cloud's own adapter, never onto a consumer's.\n const versionHistory: VersionHistoryProvider = {\n ...versionHistoryEventsOf(config.versionHistory),\n ...createCloudVersionHistoryProvider(authManager),\n };\n\n // Realtime is the adapter's own business: `subscribe` binds the presence channel\n // above, so `useCommentListener` in `@templatical/core` never learns that Pusher\n // exists and a BYO provider with an SSE stream slots into the same seam. The\n // consumer's `onCreated` / `onUpdated` / `onDeleted` / `onResolved` /\n // `onUnresolved` ride along via `commentEventsOf` — core calls them once the\n // editor has settled, so the adapter itself never invokes them.\n const comments: CommentsProvider = {\n ...commentEventsOf(config.comments),\n ...createCloudCommentsProvider({\n authManager,\n channel: commentChannel,\n getSocketId: () => websocketRef?.getSocketId() ?? null,\n }),\n };\n\n // From the JWT, not from config. Cloud signs comment writes against this same\n // claim, so a consumer-supplied identity could only disagree with it — and a\n // token without the claim leaves comments unavailable rather than anonymous.\n const cloudUser: EditorUser | undefined = authManager.userConfig\n ? { id: authManager.userConfig.id, name: authManager.userConfig.name }\n : undefined;\n\n // A consumer may pass their own store instead of a boolean, in which case it\n // replaces Cloud's outright — discriminated on `list`, the one required\n // method every full provider carries, never on `typeof === \"object\"`: an\n // events-only `SavedBlocksOptions` (`{ onCreated }`) is an object too, and\n // reading it as the provider would leave `list` undefined and crash the\n // library on first browse. That path is deliberately NOT plan-gated:\n // `savedModules` licenses Cloud's *storage*, and someone else's backend\n // isn't Cloud's to sell — `isSavedBlocksAvailable` below keys off this same\n // discriminated value for that reason.\n const consumerSavedBlocks =\n typeof (config.savedBlocks as SavedBlocksProvider | undefined)?.list ===\n \"function\"\n ? (config.savedBlocks as SavedBlocksProvider)\n : null;\n // A malformed provider — e.g. `create` / `update` / `delete` with no\n // working `list` — fails the discriminator above and falls through to\n // Cloud's own store, so those methods are silently unused rather than\n // replacing anything. Named here the same way `templates` / `comments` /\n // `versionHistory` name their own ignored methods, so the drop isn't a\n // console-free mystery.\n if (\n consumerSavedBlocks === null &&\n typeof config.savedBlocks === \"object\" &&\n config.savedBlocks !== null\n ) {\n const suppliedSavedBlocks = config.savedBlocks as Record<string, unknown>;\n const ignoredSavedBlocksMethods = [\n \"list\",\n \"create\",\n \"update\",\n \"delete\",\n ].filter((key) => typeof suppliedSavedBlocks[key] !== \"undefined\");\n if (ignoredSavedBlocksMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredSavedBlocksMethods.map((key) => `savedBlocks.${key}`),\n )} — a provider needs a working list to replace Cloud's store, and ` +\n \"this value has none, so it configures Cloud's own store instead. \" +\n \"Your event handlers were kept. Use init() to bring your own storage.\",\n );\n }\n }\n // The consumer's `onCreated` / `onUpdated` / `onDeleted` ride along via\n // `savedBlocksEventsOf` when Cloud's own adapter is used — core calls them\n // once the editor has settled, so the adapter itself never invokes them. A\n // full consumer provider carries its own events already and is used as-is,\n // so this merge only ever runs on Cloud's side of the `??`.\n const savedBlocks: SavedBlocksProvider | undefined =\n config.savedBlocks === false\n ? undefined\n : (consumerSavedBlocks ?? {\n ...savedBlocksEventsOf(config.savedBlocks),\n ...createCloudSavedBlocksProvider(authManager),\n });\n\n // Cloud's test-email *config* — plan enablement plus the signed allowlist, both\n // carried by the JWT `authManager.initialize()` already resolved above. Hence\n // the constant `isAuthReady`: there is no window where it is false.\n const testEmailConfig = useTestEmail({\n authManager,\n isAuthReady: ref(true),\n });\n\n // Cloud's own send path renders through the export endpoint directly: the\n // adapter derives HTML from the *saved* template and applies\n // `onBeforeTestEmail` to it, which is a narrower job than the render contract.\n const exporter = useExport({ authManager });\n\n // Discriminated on `send`, the one required method every full provider\n // carries — never on raw truthiness, which an events-only `TestEmailOptions`\n // (`{ onSent }`) also satisfies and would leave `send` undefined, crashing\n // the dialog on send. `isTestEmailAvailable` below keys off this same\n // discriminated value so an events-only value stays plan-gated rather than\n // reading as \"consumer's own sender\".\n const consumerTestEmail =\n typeof (config.testEmail as TestEmailProvider | undefined)?.send ===\n \"function\"\n ? (config.testEmail as TestEmailProvider)\n : null;\n // `send` reaching here means it failed the discriminator above — e.g.\n // `send: null` — so it is named the same way a malformed `savedBlocks`\n // value's storage methods are. `includeMjml` / `allowedRecipients` are\n // named for a different reason: they are not part of this key's options\n // arm (see `cloudConfig.ts`), but TypeScript does not actually refuse\n // them — both are valid members of the sibling `TestEmailProvider` arm, so\n // the union's excess-property check passes them through regardless of\n // which arm the caller intended. All three log a warning naming them\n // rather than dropping with no console trace.\n if (\n consumerTestEmail === null &&\n typeof config.testEmail === \"object\" &&\n config.testEmail !== null\n ) {\n const suppliedTestEmail = config.testEmail as Record<string, unknown>;\n const ignoredTestEmailMembers = [\n \"send\",\n \"includeMjml\",\n \"allowedRecipients\",\n ].filter((key) => typeof suppliedTestEmail[key] !== \"undefined\");\n if (ignoredTestEmailMembers.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredTestEmailMembers.map((key) => `testEmail.${key}`),\n )} — a provider needs a working send to replace Cloud's sender ` +\n \"outright, and Cloud renders server-side with the signed \" +\n \"allowlist from your project's JWT either way, so none of these \" +\n \"apply here. Your event handlers were kept.\",\n );\n }\n }\n const testEmail: TestEmailProvider =\n consumerTestEmail ??\n // `Object.assign`, not a spread: `createCloudTestEmailProvider`'s\n // `allowedRecipients` is a live getter (see `testEmailEventsOf`'s doc\n // comment for why a spread would freeze it). The cloud provider is the\n // assignment *target* here, so its getter is never read — only the keys\n // `testEmailEventsOf` returns are ever written onto it.\n //\n // Asymmetric with `savedBlocks` / `versionHistory` on purpose, not by\n // drift: those two spread Cloud's provider LAST, so even a whitelist that\n // let something unexpected through could never displace a Cloud method —\n // two lines of defence. Here `testEmailEventsOf`'s return type is the\n // only barrier, because Cloud is the assignment target rather than a\n // second spread source. Copying the sibling shape (`{ ...events,\n // ...createCloudTestEmailProvider(...) }`) would reintroduce the exact\n // getter-freezing bug this construction exists to avoid.\n Object.assign(\n createCloudTestEmailProvider({\n authManager,\n getTemplateId,\n save: () => requireEditor().save(),\n exportHtml: (templateId: string) =>\n exporter.exportHtml(templateId, resolveExportFonts(config.fonts)),\n allowedEmails: testEmailConfig.allowedEmails,\n getSignature: testEmailConfig.getSignature,\n onBeforeTestEmail: config.onBeforeTestEmail,\n }),\n testEmailEventsOf(config.testEmail),\n );\n\n // A consumer may pass their own store instead of omitting the key or\n // passing `false`, in which case it replaces Cloud's outright —\n // discriminated on `list`, the one required method every full provider\n // carries, never on `typeof === \"object\"`: an events-only `MediaOptions`\n // (`{ onCreated }`) is an object too, and reading it as the provider\n // would leave `list` undefined and crash the library on first browse.\n // That path is deliberately NOT plan-gated: there is no media plan\n // feature. The plan licenses Cloud's *storage*, and someone else's\n // backend isn't Cloud's to sell.\n const consumerMedia =\n typeof (config.media as MediaProvider | undefined)?.list === \"function\"\n ? (config.media as MediaProvider)\n : null;\n // A malformed provider — e.g. `create` / `update` / `delete` with no\n // working `list` — fails the discriminator above and falls through to\n // Cloud's own store, so those methods are silently unused rather than\n // replacing anything. Named here the same way `savedBlocks` names its\n // own ignored methods, so the drop isn't a console-free mystery.\n // `maxFileSize` / `mimeTypes` are named for a different reason: they\n // are valid `MediaOptions` members but Cloud's plan owns those limits\n // whenever Cloud's store is in play.\n if (\n consumerMedia === null &&\n typeof config.media === \"object\" &&\n config.media !== null\n ) {\n const suppliedMedia = config.media as Record<string, unknown>;\n const ignoredMediaMethods = [\"list\", \"create\", \"update\", \"delete\"].filter(\n (key) => typeof suppliedMedia[key] !== \"undefined\",\n );\n if (ignoredMediaMethods.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredMediaMethods.map((key) => `media.${key}`),\n )} — a provider needs a working list to replace Cloud's store, and ` +\n \"this value has none, so it configures Cloud's own store instead. \" +\n \"Your event handlers were kept. Use init() to bring your own storage.\",\n );\n }\n const ignoredMediaLimits = [\"maxFileSize\", \"mimeTypes\"].filter(\n (key) => typeof suppliedMedia[key] !== \"undefined\",\n );\n if (ignoredMediaLimits.length > 0) {\n logger.warn(\n `initCloud ignores ${joinWithAnd(\n ignoredMediaLimits.map((key) => `media.${key}`),\n )} — Cloud's plan owns those limits whenever Cloud's store is in ` +\n \"play. Your event handlers were kept.\",\n );\n }\n }\n const media: MediaProvider | undefined =\n config.media === false\n ? undefined\n : (consumerMedia ??\n // `Object.assign`, not a spread: `createCloudMediaProvider`'s\n // `storage` / `maxFileSize` / `mimeTypes` read plan config live\n // (see `mediaEventsOf`'s doc comment for why a spread would freeze\n // the getters). The cloud provider is the assignment *target*\n // here, so its getters are never read — only the keys\n // `mediaEventsOf` returns are ever written onto it.\n Object.assign(\n createCloudMediaProvider(\n authManager,\n () => planConfigInstance.config.value,\n ),\n mediaEventsOf(config.media),\n ));\n\n // --- Setup-time wiring ----------------------------------------------------\n\n const aiConfig = useAiConfig(config.ai);\n const scoringInstance = useTemplateScoring({ authManager, getTemplateId });\n\n const featureFlags = useCloudFeatureFlags({\n planConfigInstance,\n aiConfig,\n getTemplateId,\n });\n\n const isCollaborationEnabled = computed(\n () =>\n !!config.collaboration?.enabled &&\n planConfigInstance.hasFeature(\"collaboration\"),\n );\n\n function attach(context: CloudAttachContext): CloudAttachment {\n const editor = context.editor;\n editorRef = editor;\n\n provide(CLOUD_TRANSLATIONS_KEY, cloudTranslations);\n provide(AUTH_MANAGER_KEY, authManager);\n provide(AI_CONFIG_KEY, aiConfig);\n provide(SCORING_KEY, scoringInstance);\n\n const websocket = useWebSocket({ authManager, onError: config.onError });\n websocketRef = websocket;\n\n // Feeds the comments adapter's `subscribe`, which was handed to `init()` before\n // this socket existed.\n watch(\n websocket.channel,\n (channel) => {\n commentChannel.value = channel;\n },\n { immediate: true },\n );\n\n if (config.mcp?.enabled) {\n useMcpListener({\n editor,\n channel: websocket.channel,\n onOperation: config.mcp.onOperation,\n });\n }\n\n // Order matters: the broadcast wrapper replaces the editor's mutators so they\n // publish to peers, and `useEditorCore`'s history interceptor then wraps them\n // again to push history entries. Reversing it would push history for remote\n // operations and drift the two peers apart.\n if (config.collaboration?.enabled) {\n collaboration = useCollaboration({\n authManager,\n editor,\n channel: websocket.channel,\n onError: config.onError,\n onCollaboratorJoined: config.collaboration.onCollaboratorJoined,\n onCollaboratorLeft: config.collaboration.onCollaboratorLeft,\n onBlockLocked: config.collaboration.onBlockLocked,\n onBlockUnlocked: config.collaboration.onBlockUnlocked,\n }) as CloudCollaborationInstance;\n\n watch(\n () => collaboration!.lockedBlocks.value,\n (next) => {\n lockedBlocks.value = next;\n },\n { immediate: true },\n );\n\n useCollaborationBroadcast(editor, collaboration);\n }\n\n const panelState = useCloudPanelState();\n\n return {\n websocket,\n panelState,\n featureFlags,\n collaboration,\n isCollaborationEnabled,\n };\n }\n\n function ready(context: CloudReadyContext): CloudReady {\n const { core, capabilities } = context;\n coreRef = core;\n\n saveGate = useCloudSaveGate({\n issues: core.templateLint ? core.templateLint.issues : ref([]),\n planConfig: planConfigInstance.config,\n });\n\n collabWarning = useCollabUndoWarning({\n isCollaborationEnabled,\n getCollaboratorCount: () =>\n collaboration?.collaborators.value.length ?? 0,\n canUndo: core.history.canUndo,\n });\n\n // Mutated in place rather than re-provided: `useEditorCore` already provided\n // this exact object, so components injecting it see Cloud's entries on their\n // first render. Same pattern `versionHistory` uses in `Editor.vue`.\n //\n // `capabilities.comments` is *not* set here any more: comments became a shared\n // provider-backed feature, so `Editor.vue` builds the capability from\n // `useCommentsFeature` exactly as it does for saved blocks and test email, and\n // Cloud contributes only the two predicates below.\n capabilities.plan = planConfigInstance;\n capabilities.ai = aiConfig;\n\n // Registered unconditionally. `custom_blocks` and `theme_customization` used\n // to gate these — entitlements on editor capability the free editor grants,\n // and the only two things `applyPlanGates` would ever have had to do.\n if (config.customBlocks?.length) {\n core.registerCustomBlocks(config.customBlocks);\n }\n if (config.theme) {\n core.themeOverrides.value = config.theme;\n }\n\n return {\n saveGate,\n collabWarning,\n sessionError,\n retry: async () => {\n try {\n await authManager.initialize();\n sessionError.value = null;\n } catch (error) {\n sessionError.value =\n error instanceof Error ? error : new Error(\"Authentication failed\");\n }\n },\n };\n }\n\n const runtime: CloudRuntime = {\n lockedBlocks,\n isSavedBlocksAvailable: consumerSavedBlocks\n ? () => true\n : () =>\n config.savedBlocks !== false &&\n planConfigInstance.hasFeature(\"savedModules\"),\n isTestEmailAvailable: consumerTestEmail\n ? // Their sender, their rules — the `testEmail` plan feature licenses\n // Cloud's sending, and \"the template must be saved\" is a constraint of\n // Cloud's server-side render, not of an arbitrary backend.\n () => true\n : // All three matter and none implies another: the plan may grant the\n // feature while the project's token omits a recipient config, and Cloud\n // renders from the *saved* template so there must be one.\n () =>\n testEmailConfig.isEnabled.value &&\n featureFlags.canSendTestEmail.value &&\n featureFlags.hasTemplateSaved.value,\n // Three conditions, none implying another: the consumer may switch the feature\n // off, the plan meters comment storage and its realtime fan-out, and Cloud\n // anchors a comment to the *saved* template. (Whether a `user` exists is the\n // shared feature's own gate, not Cloud's.)\n isCommentsAvailable: () =>\n config.comments !== false &&\n planConfigInstance.hasFeature(\"commenting\") &&\n featureFlags.hasTemplateSaved.value,\n // A comment is anchored server-side, so a block that exists only on the canvas\n // has nothing stored to show. This is the last thing the deleted cloud editor\n // core carried (`savedBlockIds`), and it was always a comments concern rather\n // than an editor one.\n isBlockSaved: (blockId: string) =>\n collectSavedBlockIds(editorRef?.state.template ?? null).has(blockId),\n getSaveGate: () => saveGate,\n isRemoteOperation: () =>\n collaboration?._isProcessingRemoteOperation() ?? false,\n onBeforeUndo: () => collabWarning?.showCollabUndoWarning(),\n attach,\n ready,\n destroy() {\n websocketRef?.disconnect();\n config.onUnmount?.();\n },\n };\n\n return {\n runtime,\n providers: {\n templates,\n render,\n versionHistory,\n ...(savedBlocks ? { savedBlocks } : {}),\n testEmail,\n comments,\n ...(media ? { media } : {}),\n },\n user: cloudUser,\n };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { $ as e, B as t, C as n, E as r, K as i, Q as a, T as o, Y as s, et as c, j as l, k as u, q as d, rt as f } from "./draggable-kbOhCgnk.js";
2
- //#region ../../node_modules/.pnpm/@vueuse+shared@14.4.0_vue@3.5.42_typescript@6.0.3_/node_modules/@vueuse/shared/dist/index.js
1
+ import { $ as e, B as t, C as n, E as r, K as i, Q as a, T as o, Y as s, et as c, j as l, k as u, q as d, rt as f } from "./draggable-IB4x6w2O.js";
2
+ //#region ../../node_modules/.pnpm/@vueuse+shared@15.0.0_vue@3.5.43_typescript@6.0.3_/node_modules/@vueuse/shared/dist/index.js
3
3
  function p(e, t) {
4
4
  return i() ? (s(e, t), !0) : !1;
5
5
  }
@@ -20,7 +20,7 @@ function m() {
20
20
  }
21
21
  };
22
22
  }
23
- var h = /* @__PURE__ */ new WeakMap(), g = (...e) => {
23
+ var h = /* @__PURE__ */ new WeakMap(), g = /* @__NO_SIDE_EFFECTS__ */ (...e) => {
24
24
  let t = e[0], a = n()?.proxy ?? i();
25
25
  if (a == null && !o()) throw Error("injectLocal must be called in setup");
26
26
  return a && h.has(a) && t in h.get(a) ? h.get(a)[t] : r(...e);
@@ -176,4 +176,4 @@ function B(e, n, r) {
176
176
  //#endregion
177
177
  export { L as _, _ as a, B as b, x as c, N as d, A as f, I as g, M as h, g as i, v as l, p as m, O as n, C as o, F as p, S as r, b as s, m as t, k as u, R as v, z as y };
178
178
 
179
- //# sourceMappingURL=dist-BW6Y49zE.js.map
179
+ //# sourceMappingURL=dist-BRZhN8qJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dist-BRZhN8qJ.js","names":[],"sources":["../../../../../node_modules/.pnpm/@vueuse+shared@15.0.0_vue@3.5.43_typescript@6.0.3_/node_modules/@vueuse/shared/dist/index.js"],"sourcesContent":["import { computed, customRef, effectScope, getCurrentInstance, getCurrentScope, hasInjectionContext, inject, isReactive, isRef, nextTick, onBeforeMount, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowReadonly, shallowRef, toRef as toRef$1, toRefs as toRefs$1, toValue, unref, watch, watchEffect } from \"vue\";\n//#region computedEager/index.ts\n/**\n*\n* @deprecated This function will be removed in future version.\n*\n* Note: If you are using Vue 3.4+, you can straight use computed instead.\n* Because in Vue 3.4+, if computed new value does not change,\n* computed, effect, watch, watchEffect, render dependencies will not be triggered.\n* refer: https://github.com/vuejs/core/pull/5912\n*\n* @param fn effect function\n* @param options WatchOptionsBase\n* @returns readonly shallowRef\n*/\nfunction computedEager(fn, options) {\n\tvar _options$flush;\n\tconst result = shallowRef();\n\twatchEffect(() => {\n\t\tresult.value = fn();\n\t}, {\n\t\t...options,\n\t\tflush: (_options$flush = options === null || options === void 0 ? void 0 : options.flush) !== null && _options$flush !== void 0 ? _options$flush : \"sync\"\n\t});\n\treturn readonly(result);\n}\n/** @deprecated use `computedEager` instead */\nconst eagerComputed = computedEager;\n//#endregion\n//#region computedWithControl/index.ts\n/**\n* Explicitly define the deps of computed.\n*\n* @param source\n* @param fn\n*/\nfunction computedWithControl(source, fn, options = {}) {\n\tlet v = void 0;\n\tlet track;\n\tlet trigger;\n\tlet dirty = true;\n\tconst update = () => {\n\t\tdirty = true;\n\t\ttrigger();\n\t};\n\twatch(source, update, {\n\t\tflush: \"sync\",\n\t\t...options\n\t});\n\tconst get = typeof fn === \"function\" ? fn : fn.get;\n\tconst set = typeof fn === \"function\" ? void 0 : fn.set;\n\tconst result = customRef((_track, _trigger) => {\n\t\ttrack = _track;\n\t\ttrigger = _trigger;\n\t\treturn {\n\t\t\tget() {\n\t\t\t\tif (dirty) {\n\t\t\t\t\tv = get(v);\n\t\t\t\t\tdirty = false;\n\t\t\t\t}\n\t\t\t\ttrack();\n\t\t\t\treturn v;\n\t\t\t},\n\t\t\tset(v) {\n\t\t\t\tset === null || set === void 0 || set(v);\n\t\t\t}\n\t\t};\n\t});\n\tresult.trigger = update;\n\treturn result;\n}\n/** @deprecated use `computedWithControl` instead */\nconst controlledComputed = computedWithControl;\n//#endregion\n//#region createDisposableDirective/index.ts\n/**\n* Utility for authoring disposable directives. Reactive effects created within `mounted` directive hook will be tracked and automatically disposed when directive is unmounted.\n*\n* @see https://vueuse.org/createDisposableDirective\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction createDisposableDirective(origin = {}) {\n\tfunction isFunc(fn) {\n\t\treturn typeof fn === \"function\";\n\t}\n\tconst normalisedOrigin = isFunc(origin) ? {\n\t\tmounted: origin,\n\t\tupdated: origin\n\t} : origin;\n\tconst { mounted, unmounted } = normalisedOrigin;\n\tif (!isFunc(mounted)) return origin;\n\tconst scopeWeakMap = /* @__PURE__ */ new WeakMap();\n\treturn {\n\t\t...normalisedOrigin,\n\t\tmounted(el, binding, vNode, prevNode) {\n\t\t\tvar _scopeWeakMap$get;\n\t\t\tconst scope = (_scopeWeakMap$get = scopeWeakMap.get(el)) !== null && _scopeWeakMap$get !== void 0 ? _scopeWeakMap$get : effectScope();\n\t\t\tscopeWeakMap.set(el, scope);\n\t\t\tscope.run(() => {\n\t\t\t\tmounted === null || mounted === void 0 || mounted(el, binding, vNode, prevNode);\n\t\t\t});\n\t\t},\n\t\tunmounted(el, binding, vNode, prevNode) {\n\t\t\tvar _scopeWeakMap$get2;\n\t\t\t(_scopeWeakMap$get2 = scopeWeakMap.get(el)) === null || _scopeWeakMap$get2 === void 0 || _scopeWeakMap$get2.stop();\n\t\t\tscopeWeakMap.delete(el);\n\t\t\tif (isFunc(unmounted)) unmounted(el, binding, vNode, prevNode);\n\t\t}\n\t};\n}\n//#endregion\n//#region tryOnScopeDispose/index.ts\n/**\n* Call onScopeDispose() if it's inside an effect scope lifecycle, if not, do nothing\n*\n* @param fn\n*/\nfunction tryOnScopeDispose(fn, failSilently) {\n\tif (getCurrentScope()) {\n\t\tonScopeDispose(fn, failSilently);\n\t\treturn true;\n\t}\n\treturn false;\n}\n//#endregion\n//#region createEventHook/index.ts\n/**\n* Utility for creating event hooks\n*\n* @see https://vueuse.org/createEventHook\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction createEventHook() {\n\tconst fns = /* @__PURE__ */ new Set();\n\tconst off = (fn) => {\n\t\tfns.delete(fn);\n\t};\n\tconst clear = () => {\n\t\tfns.clear();\n\t};\n\tconst on = (fn) => {\n\t\tfns.add(fn);\n\t\tconst offFn = () => off(fn);\n\t\ttryOnScopeDispose(offFn);\n\t\treturn { off: offFn };\n\t};\n\tconst trigger = (...args) => {\n\t\treturn Promise.all(Array.from(fns).map((fn) => fn(...args)));\n\t};\n\treturn {\n\t\ton,\n\t\toff,\n\t\ttrigger,\n\t\tclear\n\t};\n}\n//#endregion\n//#region createGlobalState/index.ts\n/**\n* Keep states in the global scope to be reusable across Vue instances.\n*\n* @see https://vueuse.org/createGlobalState\n* @param stateFactory A factory function to create the state\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction createGlobalState(stateFactory) {\n\tlet initialized = false;\n\tlet state;\n\tconst scope = effectScope(true);\n\treturn ((...args) => {\n\t\tif (!initialized) {\n\t\t\tstate = scope.run(() => stateFactory(...args));\n\t\t\tinitialized = true;\n\t\t}\n\t\treturn state;\n\t});\n}\n//#endregion\n//#region provideLocal/map.ts\nconst localProvidedStateMap = /* @__PURE__ */ new WeakMap();\n//#endregion\n//#region injectLocal/index.ts\n/**\n* On the basis of `inject`, it is allowed to directly call inject to obtain the value after call provide in the same component.\n*\n* @example\n* ```ts\n* injectLocal('MyInjectionKey', 1)\n* const injectedValue = injectLocal('MyInjectionKey') // injectedValue === 1\n* ```\n*\n* @NO_SIDE_EFFECTS\n*/\nconst injectLocal = /* @__NO_SIDE_EFFECTS__ */ (...args) => {\n\tvar _getCurrentInstance;\n\tconst key = args[0];\n\tconst instance = (_getCurrentInstance = getCurrentInstance()) === null || _getCurrentInstance === void 0 ? void 0 : _getCurrentInstance.proxy;\n\tconst owner = instance !== null && instance !== void 0 ? instance : getCurrentScope();\n\tif (owner == null && !hasInjectionContext()) throw new Error(\"injectLocal must be called in setup\");\n\tif (owner && localProvidedStateMap.has(owner) && key in localProvidedStateMap.get(owner)) return localProvidedStateMap.get(owner)[key];\n\treturn inject(...args);\n};\n//#endregion\n//#region provideLocal/index.ts\n/**\n* On the basis of `provide`, it is allowed to directly call inject to obtain the value after call provide in the same component.\n*\n* @example\n* ```ts\n* provideLocal('MyInjectionKey', 1)\n* const injectedValue = injectLocal('MyInjectionKey') // injectedValue === 1\n* ```\n*/\nfunction provideLocal(key, value) {\n\tvar _getCurrentInstance;\n\tconst instance = (_getCurrentInstance = getCurrentInstance()) === null || _getCurrentInstance === void 0 ? void 0 : _getCurrentInstance.proxy;\n\tconst owner = instance !== null && instance !== void 0 ? instance : getCurrentScope();\n\tif (owner == null) throw new Error(\"provideLocal must be called in setup\");\n\tif (!localProvidedStateMap.has(owner)) localProvidedStateMap.set(owner, Object.create(null));\n\tconst localProvidedState = localProvidedStateMap.get(owner);\n\tlocalProvidedState[key] = value;\n\treturn provide(key, value);\n}\n//#endregion\n//#region createInjectionState/index.ts\n/* @__NO_SIDE_EFFECTS__ */\nfunction createInjectionState(composable, options) {\n\tconst key = (options === null || options === void 0 ? void 0 : options.injectionKey) || Symbol(composable.name || \"InjectionState\");\n\tconst defaultValue = options === null || options === void 0 ? void 0 : options.defaultValue;\n\tconst useProvidingState = (...args) => {\n\t\tconst state = composable(...args);\n\t\tprovideLocal(key, state);\n\t\treturn state;\n\t};\n\tconst useInjectedState = () => /* @__PURE__ */ injectLocal(key, defaultValue);\n\treturn [useProvidingState, useInjectedState];\n}\n//#endregion\n//#region createRef/index.ts\n/**\n* Returns a `deepRef` or `shallowRef` depending on the `deep` param.\n*\n* @example createRef(1) // ShallowRef<number>\n* @example createRef(1, false) // ShallowRef<number>\n* @example createRef(1, true) // Ref<number>\n* @example createRef(\"string\") // ShallowRef<string>\n* @example createRef<\"A\"|\"B\">(\"A\", true) // Ref<\"A\"|\"B\">\n*\n* @param value\n* @param deep\n* @returns the `deepRef` or `shallowRef`\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction createRef(value, deep) {\n\tif (deep === true) return ref(value);\n\telse return shallowRef(value);\n}\n//#endregion\n//#region utils/is.ts\nconst isClient = typeof window !== \"undefined\" && typeof document !== \"undefined\";\nconst isWorker = typeof WorkerGlobalScope !== \"undefined\" && globalThis instanceof WorkerGlobalScope;\nconst isDef = (val) => typeof val !== \"undefined\";\nconst notNullish = (val) => val != null;\nconst assert = (condition, ...infos) => {\n\tif (!condition) console.warn(...infos);\n};\nconst toString = Object.prototype.toString;\nconst isObject = (val) => toString.call(val) === \"[object Object]\";\nconst now = () => Date.now();\nconst timestamp = () => +Date.now();\nconst clamp = (n, min, max) => Math.min(max, Math.max(min, n));\nconst noop = () => {};\nconst rand = (min, max) => {\n\tmin = Math.ceil(min);\n\tmax = Math.floor(max);\n\treturn Math.floor(Math.random() * (max - min + 1)) + min;\n};\nconst hasOwn = (val, key) => Object.hasOwn(val, key);\nconst isIOS = /* #__PURE__ */ getIsIOS();\nfunction getIsIOS() {\n\tvar _window, _window2, _window3;\n\treturn isClient && !!((_window = window) === null || _window === void 0 || (_window = _window.navigator) === null || _window === void 0 ? void 0 : _window.userAgent) && (/iP(?:ad|hone|od)/.test(window.navigator.userAgent) || ((_window2 = window) === null || _window2 === void 0 || (_window2 = _window2.navigator) === null || _window2 === void 0 ? void 0 : _window2.maxTouchPoints) > 2 && /iPad|Macintosh/.test((_window3 = window) === null || _window3 === void 0 ? void 0 : _window3.navigator.userAgent));\n}\n//#endregion\n//#region toRef/index.ts\nfunction toRef(...args) {\n\tif (args.length !== 1) return toRef$1(...args);\n\tconst r = args[0];\n\treturn typeof r === \"function\" ? readonly(customRef(() => ({\n\t\tget: r,\n\t\tset: noop\n\t}))) : ref(r);\n}\n//#endregion\n//#region utils/filters.ts\nfunction createFilterWrapper(filter, fn) {\n\tfunction wrapper(...args) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tPromise.resolve(filter(() => fn.apply(this, args), {\n\t\t\t\tfn,\n\t\t\t\tthisArg: this,\n\t\t\t\targs\n\t\t\t})).then(resolve).catch(reject);\n\t\t});\n\t}\n\tif (\"cancel\" in filter) Object.assign(wrapper, {\n\t\tcancel: filter.cancel,\n\t\tflush: filter.flush,\n\t\tisPending: filter.isPending\n\t});\n\treturn wrapper;\n}\nconst bypassFilter = (invoke) => {\n\treturn invoke();\n};\n/**\n* Create an EventFilter that debounce the events\n*/\nfunction debounceFilter(ms, options = {}) {\n\tlet timer;\n\tlet maxTimer;\n\tlet lastRejector = noop;\n\tlet lastResolve = noop;\n\tconst _pending = shallowRef(false);\n\tconst _clearTimeout = (timer) => {\n\t\tclearTimeout(timer);\n\t\tlastRejector();\n\t\tlastRejector = noop;\n\t};\n\tlet lastInvoker;\n\tconst handler = (invoke) => {\n\t\tconst duration = toValue(ms);\n\t\tconst maxDuration = toValue(options.maxWait);\n\t\tif (timer) _clearTimeout(timer);\n\t\tif (duration <= 0 || maxDuration !== void 0 && maxDuration <= 0) {\n\t\t\tif (maxTimer) {\n\t\t\t\t_clearTimeout(maxTimer);\n\t\t\t\tmaxTimer = void 0;\n\t\t\t}\n\t\t\t_pending.value = false;\n\t\t\treturn Promise.resolve(invoke());\n\t\t}\n\t\t_pending.value = true;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlastRejector = options.rejectOnCancel ? reject : resolve;\n\t\t\tlastResolve = resolve;\n\t\t\tlastInvoker = invoke;\n\t\t\tif (maxDuration && !maxTimer) maxTimer = setTimeout(() => {\n\t\t\t\tif (timer) _clearTimeout(timer);\n\t\t\t\tmaxTimer = void 0;\n\t\t\t\t_pending.value = false;\n\t\t\t\tresolve(lastInvoker());\n\t\t\t}, maxDuration);\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\tif (maxTimer) _clearTimeout(maxTimer);\n\t\t\t\tmaxTimer = void 0;\n\t\t\t\t_pending.value = false;\n\t\t\t\tresolve(invoke());\n\t\t\t}, duration);\n\t\t});\n\t};\n\treturn Object.assign(handler, {\n\t\tcancel: () => {\n\t\t\tif (timer) {\n\t\t\t\t_clearTimeout(timer);\n\t\t\t\ttimer = void 0;\n\t\t\t}\n\t\t\tif (maxTimer) {\n\t\t\t\t_clearTimeout(maxTimer);\n\t\t\t\tmaxTimer = void 0;\n\t\t\t}\n\t\t\t_pending.value = false;\n\t\t\tlastResolve = noop;\n\t\t},\n\t\tflush: () => {\n\t\t\tif (_pending.value) {\n\t\t\t\tif (timer) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\ttimer = void 0;\n\t\t\t\t}\n\t\t\t\tif (maxTimer) {\n\t\t\t\t\tclearTimeout(maxTimer);\n\t\t\t\t\tmaxTimer = void 0;\n\t\t\t\t}\n\t\t\t\t_pending.value = false;\n\t\t\t\tconst resolve = lastResolve;\n\t\t\t\tlastRejector = noop;\n\t\t\t\tlastResolve = noop;\n\t\t\t\tresolve(lastInvoker());\n\t\t\t}\n\t\t},\n\t\tisPending: shallowReadonly(_pending)\n\t});\n}\nfunction throttleFilter(...args) {\n\tlet lastExec = 0;\n\tlet timer;\n\tlet isLeading = true;\n\tlet lastRejector = noop;\n\tlet lastValue;\n\tlet ms;\n\tlet trailing;\n\tlet leading;\n\tlet rejectOnCancel;\n\tif (!isRef(args[0]) && typeof args[0] === \"object\") ({delay: ms, trailing = true, leading = true, rejectOnCancel = false} = args[0]);\n\telse [ms, trailing = true, leading = true, rejectOnCancel = false] = args;\n\tconst clear = () => {\n\t\tif (timer) {\n\t\t\tclearTimeout(timer);\n\t\t\ttimer = void 0;\n\t\t\tlastRejector();\n\t\t\tlastRejector = noop;\n\t\t}\n\t};\n\tconst filter = (_invoke) => {\n\t\tconst duration = toValue(ms);\n\t\tconst elapsed = Date.now() - lastExec;\n\t\tconst invoke = () => {\n\t\t\treturn lastValue = _invoke();\n\t\t};\n\t\tclear();\n\t\tif (duration <= 0) {\n\t\t\tlastExec = Date.now();\n\t\t\treturn invoke();\n\t\t}\n\t\tif (elapsed > duration) {\n\t\t\tlastExec = Date.now();\n\t\t\tif (leading || !isLeading) invoke();\n\t\t} else if (trailing) lastValue = new Promise((resolve, reject) => {\n\t\t\tlastRejector = rejectOnCancel ? reject : resolve;\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\tlastExec = Date.now();\n\t\t\t\tisLeading = true;\n\t\t\t\tresolve(invoke());\n\t\t\t\tclear();\n\t\t\t}, Math.max(0, duration - elapsed));\n\t\t});\n\t\tif (!leading && !timer) timer = setTimeout(() => isLeading = true, duration);\n\t\tisLeading = false;\n\t\treturn lastValue;\n\t};\n\treturn filter;\n}\n/**\n* EventFilter that gives extra controls to pause and resume the filter\n*\n* @param extendFilter Extra filter to apply when the PausableFilter is active, default to none\n* @param options Options to configure the filter\n*/\nfunction pausableFilter(extendFilter = bypassFilter, options = {}) {\n\tconst { initialState = \"active\" } = options;\n\tconst isActive = toRef(initialState === \"active\");\n\tfunction pause() {\n\t\tisActive.value = false;\n\t}\n\tfunction resume() {\n\t\tisActive.value = true;\n\t}\n\tconst eventFilter = (...args) => {\n\t\tif (isActive.value) extendFilter(...args);\n\t};\n\treturn {\n\t\tisActive: shallowReadonly(isActive),\n\t\tpause,\n\t\tresume,\n\t\teventFilter\n\t};\n}\n//#endregion\n//#region utils/general.ts\nfunction promiseTimeout(ms, throwOnTimeout = false, reason = \"Timeout\") {\n\treturn new Promise((resolve, reject) => {\n\t\tif (throwOnTimeout) setTimeout(reject, ms, reason);\n\t\telse setTimeout(resolve, ms);\n\t});\n}\nfunction identity(arg) {\n\treturn arg;\n}\n/**\n* Create singleton promise function\n*\n* @example\n* ```\n* const promise = createSingletonPromise(async () => { ... })\n*\n* await promise()\n* await promise() // all of them will be bind to a single promise instance\n* await promise() // and be resolved together\n* ```\n*/\nfunction createSingletonPromise(fn) {\n\tlet _promise;\n\tfunction wrapper() {\n\t\tif (!_promise) _promise = fn();\n\t\treturn _promise;\n\t}\n\twrapper.reset = async () => {\n\t\tconst _prev = _promise;\n\t\t_promise = void 0;\n\t\tif (_prev) await _prev;\n\t};\n\treturn wrapper;\n}\nfunction invoke(fn) {\n\treturn fn();\n}\nfunction containsProp(obj, ...props) {\n\treturn props.some((k) => k in obj);\n}\nfunction increaseWithUnit(target, delta) {\n\tvar _target$match;\n\tif (typeof target === \"number\") return target + delta;\n\tconst value = ((_target$match = target.match(/^-?\\d+\\.?\\d*/)) === null || _target$match === void 0 ? void 0 : _target$match[0]) || \"\";\n\tconst unit = target.slice(value.length);\n\tconst result = Number.parseFloat(value) + delta;\n\tif (Number.isNaN(result)) return target;\n\treturn result + unit;\n}\n/**\n* Get a px value for SSR use, do not rely on this method outside of SSR as REM unit is assumed at 16px, which might not be the case on the client\n*/\nfunction pxValue(px) {\n\treturn px.endsWith(\"rem\") ? Number.parseFloat(px) * 16 : Number.parseFloat(px);\n}\n/**\n* Create a new subset object by giving keys\n*/\nfunction objectPick(obj, keys, omitUndefined = false) {\n\treturn keys.reduce((n, k) => {\n\t\tif (k in obj) {\n\t\t\tif (!omitUndefined || obj[k] !== void 0) n[k] = obj[k];\n\t\t}\n\t\treturn n;\n\t}, {});\n}\n/**\n* Create a new subset object by omit giving keys\n*/\nfunction objectOmit(obj, keys, omitUndefined = false) {\n\treturn Object.fromEntries(Object.entries(obj).filter(([key, value]) => {\n\t\treturn (!omitUndefined || value !== void 0) && !keys.includes(key);\n\t}));\n}\nfunction objectEntries(obj) {\n\treturn Object.entries(obj);\n}\nfunction toArray(value) {\n\treturn Array.isArray(value) ? value : [value];\n}\n//#endregion\n//#region utils/port.ts\nfunction cacheStringFunction(fn) {\n\tconst cache = Object.create(null);\n\treturn ((str) => {\n\t\treturn cache[str] || (cache[str] = fn(str));\n\t});\n}\nconst hyphenateRE = /\\B([A-Z])/g;\nconst hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, \"-$1\").toLowerCase());\nconst camelizeRE = /-(\\w)/g;\nconst camelize = cacheStringFunction((str) => {\n\treturn str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : \"\");\n});\n//#endregion\n//#region utils/vue.ts\nfunction getLifeCycleTarget(target) {\n\treturn target || getCurrentInstance();\n}\n//#endregion\n//#region createSharedComposable/index.ts\n/**\n* Make a composable function usable with multiple Vue instances.\n*\n* @see https://vueuse.org/createSharedComposable\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction createSharedComposable(composable) {\n\tif (!isClient) return composable;\n\tlet subscribers = 0;\n\tlet state;\n\tlet scope;\n\tconst dispose = () => {\n\t\tsubscribers -= 1;\n\t\tif (scope && subscribers <= 0) {\n\t\t\tscope.stop();\n\t\t\tstate = void 0;\n\t\t\tscope = void 0;\n\t\t}\n\t};\n\treturn ((...args) => {\n\t\tsubscribers += 1;\n\t\tif (!scope) {\n\t\t\tscope = effectScope(true);\n\t\t\tstate = scope.run(() => composable(...args));\n\t\t}\n\t\ttryOnScopeDispose(dispose);\n\t\treturn state;\n\t});\n}\n//#endregion\n//#region extendRef/index.ts\nfunction extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) {\n\tfor (const [key, value] of Object.entries(extend)) {\n\t\tif (key === \"value\") continue;\n\t\tif (isRef(value) && unwrap) Object.defineProperty(ref, key, {\n\t\t\tget() {\n\t\t\t\treturn value.value;\n\t\t\t},\n\t\t\tset(v) {\n\t\t\t\tvalue.value = v;\n\t\t\t},\n\t\t\tenumerable\n\t\t});\n\t\telse Object.defineProperty(ref, key, {\n\t\t\tvalue,\n\t\t\tenumerable\n\t\t});\n\t}\n\treturn ref;\n}\n//#endregion\n//#region get/index.ts\nfunction get(obj, key) {\n\tif (key == null) return unref(obj);\n\treturn unref(obj)[key];\n}\n//#endregion\n//#region isDefined/index.ts\nfunction isDefined(v) {\n\treturn unref(v) != null;\n}\n//#endregion\n//#region makeDestructurable/index.ts\n/* @__NO_SIDE_EFFECTS__ */\nfunction makeDestructurable(obj, arr) {\n\tif (typeof Symbol !== \"undefined\") {\n\t\tconst clone = { ...obj };\n\t\tObject.defineProperty(clone, Symbol.iterator, {\n\t\t\tenumerable: false,\n\t\t\tvalue() {\n\t\t\t\tlet index = 0;\n\t\t\t\treturn { next: () => ({\n\t\t\t\t\tvalue: arr[index++],\n\t\t\t\t\tdone: index > arr.length\n\t\t\t\t}) };\n\t\t\t}\n\t\t});\n\t\treturn clone;\n\t} else return Object.assign([...arr], obj);\n}\n//#endregion\n//#region reactify/index.ts\n/**\n* Converts plain function into a reactive function.\n* The converted function accepts refs as it's arguments\n* and returns a ComputedRef, with proper typing.\n*\n* @param fn - Source function\n* @param options - Options\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction reactify(fn, options) {\n\tconst unrefFn = (options === null || options === void 0 ? void 0 : options.computedGetter) === false ? unref : toValue;\n\treturn function(...args) {\n\t\treturn computed(() => fn.apply(this, args.map((i) => unrefFn(i))));\n\t};\n}\n/** @deprecated use `reactify` instead */\nconst createReactiveFn = reactify;\n//#endregion\n//#region reactifyObject/index.ts\n/* @__NO_SIDE_EFFECTS__ */\nfunction reactifyObject(obj, optionsOrKeys = {}) {\n\tlet keys = [];\n\tlet options;\n\tif (Array.isArray(optionsOrKeys)) keys = optionsOrKeys;\n\telse {\n\t\toptions = optionsOrKeys;\n\t\tconst { includeOwnProperties = true } = optionsOrKeys;\n\t\tkeys.push(...Object.keys(obj));\n\t\tif (includeOwnProperties) keys.push(...Object.getOwnPropertyNames(obj));\n\t}\n\treturn Object.fromEntries(keys.map((key) => {\n\t\tconst value = obj[key];\n\t\treturn [key, typeof value === \"function\" ? reactify(value.bind(obj), options) : value];\n\t}));\n}\n//#endregion\n//#region toReactive/index.ts\n/**\n* Converts ref to reactive.\n*\n* @see https://vueuse.org/toReactive\n* @param objectRef A ref of object\n*/\nfunction toReactive(objectRef) {\n\tif (!isRef(objectRef)) return reactive(objectRef);\n\tconst proxy = new Proxy({}, {\n\t\tget(_, p, receiver) {\n\t\t\treturn unref(Reflect.get(objectRef.value, p, receiver));\n\t\t},\n\t\tset(_, p, value) {\n\t\t\tif (isRef(objectRef.value[p]) && !isRef(value)) objectRef.value[p].value = value;\n\t\t\telse objectRef.value[p] = value;\n\t\t\treturn true;\n\t\t},\n\t\tdeleteProperty(_, p) {\n\t\t\treturn Reflect.deleteProperty(objectRef.value, p);\n\t\t},\n\t\thas(_, p) {\n\t\t\treturn Reflect.has(objectRef.value, p);\n\t\t},\n\t\townKeys() {\n\t\t\treturn Object.keys(objectRef.value);\n\t\t},\n\t\tgetOwnPropertyDescriptor() {\n\t\t\treturn {\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true\n\t\t\t};\n\t\t}\n\t});\n\treturn reactive(proxy);\n}\n//#endregion\n//#region reactiveComputed/index.ts\n/**\n* Computed reactive object.\n*/\nfunction reactiveComputed(fn) {\n\treturn toReactive(computed(fn));\n}\n//#endregion\n//#region reactiveOmit/index.ts\n/**\n* Reactively omit fields from a reactive object\n*\n* @see https://vueuse.org/reactiveOmit\n*/\nfunction reactiveOmit(obj, ...keys) {\n\tconst flatKeys = keys.flat();\n\tconst predicate = flatKeys[0];\n\treturn reactiveComputed(() => typeof predicate === \"function\" ? Object.fromEntries(Object.entries(toRefs$1(obj)).filter(([k, v]) => !predicate(toValue(v), k))) : Object.fromEntries(Object.entries(toRefs$1(obj)).filter((e) => !flatKeys.includes(e[0]))));\n}\n//#endregion\n//#region reactivePick/index.ts\n/**\n* Reactively pick fields from a reactive object\n*\n* @see https://vueuse.org/reactivePick\n*/\nfunction reactivePick(obj, ...keys) {\n\tconst flatKeys = keys.flat();\n\tconst predicate = flatKeys[0];\n\treturn reactiveComputed(() => typeof predicate === \"function\" ? Object.fromEntries(Object.entries(toRefs$1(obj)).filter(([k, v]) => predicate(toValue(v), k))) : Object.fromEntries(flatKeys.map((k) => [k, toRef(obj, k)])));\n}\n//#endregion\n//#region refAutoReset/index.ts\n/**\n* Create a ref which will be reset to the default value after some time.\n*\n* @see https://vueuse.org/refAutoReset\n* @param defaultValue The value which will be set.\n* @param afterMs A zero-or-greater delay in milliseconds.\n*/\nfunction refAutoReset(defaultValue, afterMs = 1e4) {\n\treturn customRef((track, trigger) => {\n\t\tlet value = toValue(defaultValue);\n\t\tlet timer;\n\t\tconst resetAfter = () => setTimeout(() => {\n\t\t\tvalue = toValue(defaultValue);\n\t\t\ttrigger();\n\t\t}, toValue(afterMs));\n\t\ttryOnScopeDispose(() => {\n\t\t\tclearTimeout(timer);\n\t\t});\n\t\treturn {\n\t\t\tget() {\n\t\t\t\ttrack();\n\t\t\t\treturn value;\n\t\t\t},\n\t\t\tset(newValue) {\n\t\t\t\tvalue = newValue;\n\t\t\t\ttrigger();\n\t\t\t\tclearTimeout(timer);\n\t\t\t\ttimer = resetAfter();\n\t\t\t}\n\t\t};\n\t});\n}\n/** @deprecated use `refAutoReset` instead */\nconst autoResetRef = refAutoReset;\n//#endregion\n//#region useDebounceFn/index.ts\n/**\n* Debounce execution of a function.\n*\n* @see https://vueuse.org/useDebounceFn\n* @param fn A function to be executed after delay milliseconds debounced.\n* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n* @param options Options\n*\n* @return A new, debounced, function with isPending, cancel, and flush properties.\n*/\nfunction useDebounceFn(fn, ms = 200, options = {}) {\n\treturn createFilterWrapper(debounceFilter(ms, options), fn);\n}\n//#endregion\n//#region refDebounced/index.ts\n/**\n* Debounce updates of a ref.\n*\n* @return A new debounced ref.\n*/\nfunction refDebounced(value, ms = 200, options = {}) {\n\tconst debounced = ref(toValue(value));\n\tconst updater = useDebounceFn(() => {\n\t\tdebounced.value = value.value;\n\t}, ms, options);\n\twatch(value, () => updater());\n\treturn shallowReadonly(debounced);\n}\n/** @deprecated use `refDebounced` instead */\nconst debouncedRef = refDebounced;\n/** @deprecated use `refDebounced` instead */\nconst useDebounce = refDebounced;\n//#endregion\n//#region refDefault/index.ts\n/**\n* Apply default value to a ref.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction refDefault(source, defaultValue) {\n\treturn computed({\n\t\tget() {\n\t\t\tvar _source$value;\n\t\t\treturn (_source$value = source.value) !== null && _source$value !== void 0 ? _source$value : defaultValue;\n\t\t},\n\t\tset(value) {\n\t\t\tsource.value = value;\n\t\t}\n\t});\n}\n//#endregion\n//#region refManualReset/index.ts\n/**\n* Create a ref with manual reset functionality.\n*\n* @see https://vueuse.org/refManualReset\n* @param defaultValue The value which will be set.\n*/\nfunction refManualReset(defaultValue) {\n\tlet value = toValue(defaultValue);\n\tlet trigger;\n\tconst reset = () => {\n\t\tvalue = toValue(defaultValue);\n\t\ttrigger();\n\t};\n\tconst refValue = customRef((track, _trigger) => {\n\t\ttrigger = _trigger;\n\t\treturn {\n\t\t\tget() {\n\t\t\t\ttrack();\n\t\t\t\treturn value;\n\t\t\t},\n\t\t\tset(newValue) {\n\t\t\t\tvalue = newValue;\n\t\t\t\ttrigger();\n\t\t\t}\n\t\t};\n\t});\n\trefValue.reset = reset;\n\treturn refValue;\n}\n//#endregion\n//#region useThrottleFn/index.ts\n/**\n* Throttle execution of a function. Especially useful for rate limiting\n* execution of handlers on events like resize and scroll.\n*\n* @param fn A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n* to `callback` when the throttled-function is executed.\n* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n* (default value: 200)\n*\n* @param [trailing] if true, call fn again after the time is up (default value: true)\n*\n* @param [leading] if true, call fn on the leading edge of the ms timeout (default value: true)\n*\n* @param [rejectOnCancel] if true, reject the last call if it's been cancel (default value: false)\n*\n* @return A new, throttled, function.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useThrottleFn(fn, ms = 200, trailing = true, leading = true, rejectOnCancel = false) {\n\treturn createFilterWrapper(throttleFilter(ms, trailing, leading, rejectOnCancel), fn);\n}\n//#endregion\n//#region refThrottled/index.ts\n/**\n* Throttle execution of a function. Especially useful for rate limiting\n* execution of handlers on events like resize and scroll.\n*\n* @param value Ref value to be watched with throttle effect\n* @param delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n* @param trailing if true, update the value again after the delay time is up\n* @param leading if true, update the value on the leading edge of the ms timeout\n*/\nfunction refThrottled(value, delay = 200, trailing = true, leading = true) {\n\tif (delay <= 0) return value;\n\tconst throttled = ref(toValue(value));\n\tconst updater = useThrottleFn(() => {\n\t\tthrottled.value = value.value;\n\t}, delay, trailing, leading);\n\twatch(value, () => updater());\n\treturn throttled;\n}\n/** @deprecated use `refThrottled` instead */\nconst throttledRef = refThrottled;\n/** @deprecated use `refThrottled` instead */\nconst useThrottle = refThrottled;\n//#endregion\n//#region refWithControl/index.ts\n/**\n* Fine-grained controls over ref and its reactivity.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction refWithControl(initial, options = {}) {\n\tlet source = initial;\n\tlet track;\n\tlet trigger;\n\tconst ref = customRef((_track, _trigger) => {\n\t\ttrack = _track;\n\t\ttrigger = _trigger;\n\t\treturn {\n\t\t\tget() {\n\t\t\t\treturn get();\n\t\t\t},\n\t\t\tset(v) {\n\t\t\t\tset(v);\n\t\t\t}\n\t\t};\n\t});\n\tfunction get(tracking = true) {\n\t\tif (tracking) track();\n\t\treturn source;\n\t}\n\tfunction set(value, triggering = true) {\n\t\tvar _options$onBeforeChan, _options$onChanged;\n\t\tif (value === source) return;\n\t\tconst old = source;\n\t\tif (((_options$onBeforeChan = options.onBeforeChange) === null || _options$onBeforeChan === void 0 ? void 0 : _options$onBeforeChan.call(options, value, old)) === false) return;\n\t\tsource = value;\n\t\t(_options$onChanged = options.onChanged) === null || _options$onChanged === void 0 || _options$onChanged.call(options, value, old);\n\t\tif (triggering) trigger();\n\t}\n\t/**\n\t* Get the value without tracked in the reactivity system\n\t*/\n\tconst untrackedGet = () => get(false);\n\t/**\n\t* Set the value without triggering the reactivity system\n\t*/\n\tconst silentSet = (v) => set(v, false);\n\t/**\n\t* Get the value without tracked in the reactivity system.\n\t*\n\t* Alias for `untrackedGet()`\n\t*/\n\tconst peek = () => get(false);\n\t/**\n\t* Set the value without triggering the reactivity system\n\t*\n\t* Alias for `silentSet(v)`\n\t*/\n\tconst lay = (v) => set(v, false);\n\treturn extendRef(ref, {\n\t\tget,\n\t\tset,\n\t\tuntrackedGet,\n\t\tsilentSet,\n\t\tpeek,\n\t\tlay\n\t}, { enumerable: true });\n}\n/** @deprecated use `refWithControl` instead */\nconst controlledRef = refWithControl;\n//#endregion\n//#region set/index.ts\n/**\n* Shorthand for `ref.value = x`\n*/\nfunction set(...args) {\n\tif (args.length === 2) {\n\t\tconst [ref, value] = args;\n\t\tref.value = value;\n\t}\n\tif (args.length === 3) {\n\t\tconst [target, key, value] = args;\n\t\ttarget[key] = value;\n\t}\n}\n//#endregion\n//#region watchWithFilter/index.ts\nfunction watchWithFilter(source, cb, options = {}) {\n\tconst { eventFilter = bypassFilter, ...watchOptions } = options;\n\treturn watch(source, createFilterWrapper(eventFilter, cb), watchOptions);\n}\n//#endregion\n//#region watchPausable/index.ts\n/** @deprecated Use Vue's built-in `watch` instead. This function will be removed in future version. */\nfunction watchPausable(source, cb, options = {}) {\n\tconst { eventFilter: filter, initialState = \"active\", ...watchOptions } = options;\n\tconst { eventFilter, pause, resume, isActive } = pausableFilter(filter, { initialState });\n\treturn {\n\t\tstop: watchWithFilter(source, cb, {\n\t\t\t...watchOptions,\n\t\t\teventFilter\n\t\t}),\n\t\tpause,\n\t\tresume,\n\t\tisActive\n\t};\n}\n/** @deprecated Use Vue's built-in `watch` instead. This function will be removed in future version. */\nconst pausableWatch = watchPausable;\n//#endregion\n//#region syncRef/index.ts\n/**\n* Two-way refs synchronization.\n* From the set theory perspective to restrict the option's type\n* Check in the following order:\n* 1. L = R\n* 2. L ∩ R ≠ ∅\n* 3. L ⊆ R\n* 4. L ∩ R = ∅\n*/\nfunction syncRef(left, right, ...[options]) {\n\tconst { flush = \"sync\", deep = false, immediate = true, direction = \"both\", transform = {} } = options || {};\n\tconst watchers = [];\n\tconst transformLTR = \"ltr\" in transform && transform.ltr || ((v) => v);\n\tconst transformRTL = \"rtl\" in transform && transform.rtl || ((v) => v);\n\tif (direction === \"both\" || direction === \"ltr\") watchers.push(watchPausable(left, (newValue) => {\n\t\twatchers.forEach((w) => w.pause());\n\t\tright.value = transformLTR(newValue);\n\t\twatchers.forEach((w) => w.resume());\n\t}, {\n\t\tflush,\n\t\tdeep,\n\t\timmediate\n\t}));\n\tif (direction === \"both\" || direction === \"rtl\") watchers.push(watchPausable(right, (newValue) => {\n\t\twatchers.forEach((w) => w.pause());\n\t\tleft.value = transformRTL(newValue);\n\t\twatchers.forEach((w) => w.resume());\n\t}, {\n\t\tflush,\n\t\tdeep,\n\t\timmediate\n\t}));\n\tconst stop = () => {\n\t\twatchers.forEach((w) => w.stop());\n\t};\n\treturn stop;\n}\n//#endregion\n//#region syncRefs/index.ts\n/**\n* Keep target ref(s) in sync with the source ref\n*\n* @param source source ref\n* @param targets\n*/\nfunction syncRefs(source, targets, options = {}) {\n\tconst { flush = \"sync\", deep = false, immediate = true } = options;\n\tconst targetsArray = toArray(targets);\n\treturn watch(source, (newValue) => targetsArray.forEach((target) => target.value = newValue), {\n\t\tflush,\n\t\tdeep,\n\t\timmediate\n\t});\n}\n//#endregion\n//#region toRefs/index.ts\n/**\n* Extended `toRefs` that also accepts refs of an object.\n*\n* @see https://vueuse.org/toRefs\n* @param objectRef A ref or normal object or array.\n* @param options Options\n*/\nfunction toRefs(objectRef, options = {}) {\n\tif (!isRef(objectRef)) return toRefs$1(objectRef);\n\tconst result = Array.isArray(objectRef.value) ? Array.from({ length: objectRef.value.length }) : {};\n\tfor (const key in objectRef.value) result[key] = customRef(() => ({\n\t\tget() {\n\t\t\treturn objectRef.value[key];\n\t\t},\n\t\tset(v) {\n\t\t\tvar _toValue;\n\t\t\tif ((_toValue = toValue(options.replaceRef)) !== null && _toValue !== void 0 ? _toValue : true) {\n\t\t\t\tif (Array.isArray(objectRef.value)) {\n\t\t\t\t\tconst copy = [...objectRef.value];\n\t\t\t\t\tcopy[key] = v;\n\t\t\t\t\tobjectRef.value = copy;\n\t\t\t\t} else {\n\t\t\t\t\tconst newObject = {\n\t\t\t\t\t\t...objectRef.value,\n\t\t\t\t\t\t[key]: v\n\t\t\t\t\t};\n\t\t\t\t\tObject.setPrototypeOf(newObject, Object.getPrototypeOf(objectRef.value));\n\t\t\t\t\tobjectRef.value = newObject;\n\t\t\t\t}\n\t\t\t} else objectRef.value[key] = v;\n\t\t}\n\t}));\n\treturn result;\n}\n//#endregion\n//#region tryOnBeforeMount/index.ts\n/**\n* Call onBeforeMount() if it's inside a component lifecycle, if not, just call the function\n*\n* @param fn\n* @param sync if set to false, it will run in the nextTick() of Vue\n* @param target\n*/\nfunction tryOnBeforeMount(fn, sync = true, target) {\n\tif (getLifeCycleTarget(target)) onBeforeMount(fn, target);\n\telse if (sync) fn();\n\telse nextTick(fn);\n}\n//#endregion\n//#region tryOnBeforeUnmount/index.ts\n/**\n* Call onBeforeUnmount() if it's inside a component lifecycle, if not, do nothing\n*\n* @param fn\n* @param target\n*/\nfunction tryOnBeforeUnmount(fn, target) {\n\tif (getLifeCycleTarget(target)) onBeforeUnmount(fn, target);\n}\n//#endregion\n//#region tryOnMounted/index.ts\n/**\n* Call onMounted() if it's inside a component lifecycle, if not, just call the function\n*\n* @param fn\n* @param sync if set to false, it will run in the nextTick() of Vue\n* @param target\n*/\nfunction tryOnMounted(fn, sync = true, target) {\n\tif (getLifeCycleTarget(target)) onMounted(fn, target);\n\telse if (sync) fn();\n\telse nextTick(fn);\n}\n//#endregion\n//#region tryOnUnmounted/index.ts\n/**\n* Call onUnmounted() if it's inside a component lifecycle, if not, do nothing\n*\n* @param fn\n* @param target\n*/\nfunction tryOnUnmounted(fn, target) {\n\tif (getLifeCycleTarget(target)) onUnmounted(fn, target);\n}\n//#endregion\n//#region until/index.ts\nfunction createUntil(r, isNot = false) {\n\tfunction toMatch(condition, { flush = \"sync\", deep = false, timeout, throwOnTimeout } = {}) {\n\t\tlet stop = null;\n\t\tconst promises = [new Promise((resolve) => {\n\t\t\tstop = watch(r, (v) => {\n\t\t\t\tif (condition(v) !== isNot) {\n\t\t\t\t\tif (stop) stop();\n\t\t\t\t\telse nextTick(() => stop === null || stop === void 0 ? void 0 : stop());\n\t\t\t\t\tresolve(v);\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\tflush,\n\t\t\t\tdeep,\n\t\t\t\timmediate: true\n\t\t\t});\n\t\t})];\n\t\tif (timeout != null) promises.push(promiseTimeout(timeout, throwOnTimeout).then(() => toValue(r)).finally(() => stop === null || stop === void 0 ? void 0 : stop()));\n\t\treturn Promise.race(promises);\n\t}\n\tfunction toBe(value, options) {\n\t\tif (!isRef(value)) return toMatch((v) => v === value, options);\n\t\tconst { flush = \"sync\", deep = false, timeout, throwOnTimeout } = options !== null && options !== void 0 ? options : {};\n\t\tlet stop = null;\n\t\tconst promises = [new Promise((resolve) => {\n\t\t\tstop = watch([r, value], ([v1, v2]) => {\n\t\t\t\tif (isNot !== (v1 === v2)) {\n\t\t\t\t\tif (stop) stop();\n\t\t\t\t\telse nextTick(() => stop === null || stop === void 0 ? void 0 : stop());\n\t\t\t\t\tresolve(v1);\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\tflush,\n\t\t\t\tdeep,\n\t\t\t\timmediate: true\n\t\t\t});\n\t\t})];\n\t\tif (timeout != null) promises.push(promiseTimeout(timeout, throwOnTimeout).then(() => toValue(r)).finally(() => {\n\t\t\tstop === null || stop === void 0 || stop();\n\t\t\treturn toValue(r);\n\t\t}));\n\t\treturn Promise.race(promises);\n\t}\n\tfunction toBeTruthy(options) {\n\t\treturn toMatch((v) => Boolean(v), options);\n\t}\n\tfunction toBeNull(options) {\n\t\treturn toBe(null, options);\n\t}\n\tfunction toBeUndefined(options) {\n\t\treturn toBe(void 0, options);\n\t}\n\tfunction toBeNaN(options) {\n\t\treturn toMatch(Number.isNaN, options);\n\t}\n\tfunction toContains(value, options) {\n\t\treturn toMatch((v) => {\n\t\t\tconst array = Array.from(v);\n\t\t\treturn array.includes(value) || array.includes(toValue(value));\n\t\t}, options);\n\t}\n\tfunction changed(options) {\n\t\treturn changedTimes(1, options);\n\t}\n\tfunction changedTimes(n = 1, options) {\n\t\tlet count = -1;\n\t\treturn toMatch(() => {\n\t\t\tcount += 1;\n\t\t\treturn count >= n;\n\t\t}, options);\n\t}\n\tif (Array.isArray(toValue(r))) return {\n\t\ttoMatch,\n\t\ttoContains,\n\t\tchanged,\n\t\tchangedTimes,\n\t\tget not() {\n\t\t\treturn createUntil(r, !isNot);\n\t\t}\n\t};\n\telse return {\n\t\ttoMatch,\n\t\ttoBe,\n\t\ttoBeTruthy,\n\t\ttoBeNull,\n\t\ttoBeNaN,\n\t\ttoBeUndefined,\n\t\tchanged,\n\t\tchangedTimes,\n\t\tget not() {\n\t\t\treturn createUntil(r, !isNot);\n\t\t}\n\t};\n}\nfunction until(r) {\n\treturn createUntil(r);\n}\n//#endregion\n//#region useArrayDifference/index.ts\nfunction defaultComparator(value, othVal) {\n\treturn value === othVal;\n}\n/**\n* Reactive get array difference of two array\n* @see https://vueuse.org/useArrayDifference\n* @returns - the difference of two array\n* @param args\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArrayDifference(...args) {\n\tvar _args$, _args$2;\n\tconst list = args[0];\n\tconst values = args[1];\n\tlet compareFn = (_args$ = args[2]) !== null && _args$ !== void 0 ? _args$ : defaultComparator;\n\tconst { symmetric = false } = (_args$2 = args[3]) !== null && _args$2 !== void 0 ? _args$2 : {};\n\tif (typeof compareFn === \"string\") {\n\t\tconst key = compareFn;\n\t\tcompareFn = (value, othVal) => value[key] === othVal[key];\n\t}\n\tconst diff1 = computed(() => toValue(list).filter((x) => toValue(values).findIndex((y) => compareFn(x, y)) === -1));\n\tif (symmetric) {\n\t\tconst diff2 = computed(() => toValue(values).filter((x) => toValue(list).findIndex((y) => compareFn(x, y)) === -1));\n\t\treturn computed(() => symmetric ? [...toValue(diff1), ...toValue(diff2)] : toValue(diff1));\n\t} else return diff1;\n}\n//#endregion\n//#region useArrayEvery/index.ts\n/**\n* Reactive `Array.every`\n*\n* @see https://vueuse.org/useArrayEvery\n* @param list - the array was called upon.\n* @param fn - a function to test each element.\n*\n* @returns **true** if the `fn` function returns a **truthy** value for every element from the array. Otherwise, **false**.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArrayEvery(list, fn) {\n\treturn computed(() => toValue(list).every((element, index, array) => fn(toValue(element), index, array)));\n}\n//#endregion\n//#region useArrayFilter/index.ts\n/* @__NO_SIDE_EFFECTS__ */\nfunction useArrayFilter(list, fn) {\n\treturn computed(() => toValue(list).map((i) => toValue(i)).filter(fn));\n}\n//#endregion\n//#region useArrayFind/index.ts\n/**\n* Reactive `Array.find`\n*\n* @see https://vueuse.org/useArrayFind\n* @param list - the array was called upon.\n* @param fn - a function to test each element.\n*\n* @returns the first element in the array that satisfies the provided testing function. Otherwise, undefined is returned.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArrayFind(list, fn) {\n\treturn computed(() => toValue(toValue(list).find((element, index, array) => fn(toValue(element), index, array))));\n}\n//#endregion\n//#region useArrayFindIndex/index.ts\n/**\n* Reactive `Array.findIndex`\n*\n* @see https://vueuse.org/useArrayFindIndex\n* @param list - the array was called upon.\n* @param fn - a function to test each element.\n*\n* @returns the index of the first element in the array that passes the test. Otherwise, \"-1\".\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArrayFindIndex(list, fn) {\n\treturn computed(() => toValue(list).findIndex((element, index, array) => fn(toValue(element), index, array)));\n}\n//#endregion\n//#region useArrayFindLast/index.ts\nfunction findLast(arr, cb) {\n\tlet index = arr.length;\n\twhile (index-- > 0) if (cb(arr[index], index, arr)) return arr[index];\n}\n/**\n* Reactive `Array.findLast`\n*\n* @see https://vueuse.org/useArrayFindLast\n* @param list - the array was called upon.\n* @param fn - a function to test each element.\n*\n* @returns the last element in the array that satisfies the provided testing function. Otherwise, undefined is returned.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArrayFindLast(list, fn) {\n\treturn computed(() => toValue(!Array.prototype.findLast ? findLast(toValue(list), (element, index, array) => fn(toValue(element), index, array)) : toValue(list).findLast((element, index, array) => fn(toValue(element), index, array))));\n}\n//#endregion\n//#region useArrayIncludes/index.ts\nfunction isArrayIncludesOptions(obj) {\n\treturn isObject(obj) && containsProp(obj, \"formIndex\", \"comparator\");\n}\n/* @__NO_SIDE_EFFECTS__ */\nfunction useArrayIncludes(...args) {\n\tvar _comparator;\n\tconst list = args[0];\n\tconst value = args[1];\n\tlet comparator = args[2];\n\tlet formIndex = 0;\n\tif (isArrayIncludesOptions(comparator)) {\n\t\tvar _comparator$fromIndex;\n\t\tformIndex = (_comparator$fromIndex = comparator.fromIndex) !== null && _comparator$fromIndex !== void 0 ? _comparator$fromIndex : 0;\n\t\tcomparator = comparator.comparator;\n\t}\n\tif (typeof comparator === \"string\") {\n\t\tconst key = comparator;\n\t\tcomparator = (element, value) => element[key] === toValue(value);\n\t}\n\tcomparator = (_comparator = comparator) !== null && _comparator !== void 0 ? _comparator : ((element, value) => element === toValue(value));\n\treturn computed(() => toValue(list).slice(formIndex).some((element, index, array) => comparator(toValue(element), toValue(value), index, toValue(array))));\n}\n//#endregion\n//#region useArrayJoin/index.ts\n/**\n* Reactive `Array.join`\n*\n* @see https://vueuse.org/useArrayJoin\n* @param list - the array was called upon.\n* @param separator - a string to separate each pair of adjacent elements of the array. If omitted, the array elements are separated with a comma (\",\").\n*\n* @returns a string with all array elements joined. If arr.length is 0, the empty string is returned.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArrayJoin(list, separator) {\n\treturn computed(() => toValue(list).map((i) => toValue(i)).join(toValue(separator)));\n}\n//#endregion\n//#region useArrayMap/index.ts\n/**\n* Reactive `Array.map`\n*\n* @see https://vueuse.org/useArrayMap\n* @param list - the array was called upon.\n* @param fn - a function that is called for every element of the given `list`. Each time `fn` executes, the returned value is added to the new array.\n*\n* @returns a new array with each element being the result of the callback function.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArrayMap(list, fn) {\n\treturn computed(() => toValue(list).map((i) => toValue(i)).map(fn));\n}\n//#endregion\n//#region useArrayReduce/index.ts\n/* @__NO_SIDE_EFFECTS__ */\nfunction useArrayReduce(list, reducer, ...args) {\n\tconst reduceCallback = (sum, value, index) => reducer(toValue(sum), toValue(value), index);\n\treturn computed(() => {\n\t\tconst resolved = toValue(list);\n\t\treturn args.length ? resolved.reduce(reduceCallback, typeof args[0] === \"function\" ? toValue(args[0]()) : toValue(args[0])) : resolved.reduce(reduceCallback);\n\t});\n}\n//#endregion\n//#region useArraySome/index.ts\n/**\n* Reactive `Array.some`\n*\n* @see https://vueuse.org/useArraySome\n* @param list - the array was called upon.\n* @param fn - a function to test each element.\n*\n* @returns **true** if the `fn` function returns a **truthy** value for any element from the array. Otherwise, **false**.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArraySome(list, fn) {\n\treturn computed(() => toValue(list).some((element, index, array) => fn(toValue(element), index, array)));\n}\n//#endregion\n//#region useArrayUnique/index.ts\nfunction uniq(array) {\n\treturn Array.from(new Set(array));\n}\nfunction uniqueElementsBy(array, fn) {\n\treturn array.reduce((acc, v) => {\n\t\tif (!acc.some((x) => fn(v, x, array))) acc.push(v);\n\t\treturn acc;\n\t}, []);\n}\n/**\n* reactive unique array\n* @see https://vueuse.org/useArrayUnique\n* @param list - the array was called upon.\n* @param compareFn\n* @returns A computed ref that returns a unique array of items.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useArrayUnique(list, compareFn) {\n\treturn computed(() => {\n\t\tconst resolvedList = toValue(list).map((element) => toValue(element));\n\t\treturn compareFn ? uniqueElementsBy(resolvedList, compareFn) : uniq(resolvedList);\n\t});\n}\n//#endregion\n//#region useCounter/index.ts\n/**\n* Basic counter with utility functions.\n*\n* @see https://vueuse.org/useCounter\n* @param [initialValue]\n* @param options\n*/\nfunction useCounter(initialValue = 0, options = {}) {\n\tlet _initialValue = unref(initialValue);\n\tconst count = shallowRef(initialValue);\n\tconst { max = Number.POSITIVE_INFINITY, min = Number.NEGATIVE_INFINITY } = options;\n\tconst inc = (delta = 1) => count.value = Math.max(Math.min(max, count.value + delta), min);\n\tconst dec = (delta = 1) => count.value = Math.min(Math.max(min, count.value - delta), max);\n\tconst get = () => count.value;\n\tconst set = (val) => count.value = Math.max(min, Math.min(max, val));\n\tconst reset = (val = _initialValue) => {\n\t\t_initialValue = val;\n\t\treturn set(val);\n\t};\n\treturn {\n\t\tcount: shallowReadonly(count),\n\t\tinc,\n\t\tdec,\n\t\tget,\n\t\tset,\n\t\treset\n\t};\n}\n//#endregion\n//#region useDateFormat/index.ts\nconst REGEX_PARSE = /^(\\d{4})[-/]?(\\d{1,2})?[-/]?(\\d{0,2})[T\\s]*(\\d{1,2})?:?(\\d{1,2})?:?(\\d{1,2})?[.:]?(\\d+)?$/i;\nconst REGEX_FORMAT = /[YMDHhms]o|\\[([^\\]]+)\\]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a{1,2}|A{1,2}|m{1,2}|s{1,2}|Z{1,2}|z{1,4}|SSS/g;\nfunction defaultMeridiem(hours, minutes, isLowercase, hasPeriod) {\n\tlet m = hours < 12 ? \"AM\" : \"PM\";\n\tif (hasPeriod) m = m.split(\"\").reduce((acc, curr) => acc += `${curr}.`, \"\");\n\treturn isLowercase ? m.toLowerCase() : m;\n}\nfunction formatOrdinal(num) {\n\tconst suffixes = [\n\t\t\"th\",\n\t\t\"st\",\n\t\t\"nd\",\n\t\t\"rd\"\n\t];\n\tconst v = num % 100;\n\treturn num + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\n}\nfunction formatDate(date, formatStr, options = {}) {\n\tvar _options$customMeridi;\n\tconst years = date.getFullYear();\n\tconst month = date.getMonth();\n\tconst days = date.getDate();\n\tconst hours = date.getHours();\n\tconst minutes = date.getMinutes();\n\tconst seconds = date.getSeconds();\n\tconst milliseconds = date.getMilliseconds();\n\tconst day = date.getDay();\n\tconst meridiem = (_options$customMeridi = options.customMeridiem) !== null && _options$customMeridi !== void 0 ? _options$customMeridi : defaultMeridiem;\n\tconst stripTimeZone = (dateString) => {\n\t\tvar _dateString$split$;\n\t\treturn (_dateString$split$ = dateString.split(\" \")[1]) !== null && _dateString$split$ !== void 0 ? _dateString$split$ : \"\";\n\t};\n\tconst matches = {\n\t\tYo: () => formatOrdinal(years),\n\t\tYY: () => String(years).slice(-2),\n\t\tYYYY: () => years,\n\t\tM: () => month + 1,\n\t\tMo: () => formatOrdinal(month + 1),\n\t\tMM: () => `${month + 1}`.padStart(2, \"0\"),\n\t\tMMM: () => date.toLocaleDateString(toValue(options.locales), { month: \"short\" }),\n\t\tMMMM: () => date.toLocaleDateString(toValue(options.locales), { month: \"long\" }),\n\t\tD: () => String(days),\n\t\tDo: () => formatOrdinal(days),\n\t\tDD: () => `${days}`.padStart(2, \"0\"),\n\t\tH: () => String(hours),\n\t\tHo: () => formatOrdinal(hours),\n\t\tHH: () => `${hours}`.padStart(2, \"0\"),\n\t\th: () => `${hours % 12 || 12}`.padStart(1, \"0\"),\n\t\tho: () => formatOrdinal(hours % 12 || 12),\n\t\thh: () => `${hours % 12 || 12}`.padStart(2, \"0\"),\n\t\tm: () => String(minutes),\n\t\tmo: () => formatOrdinal(minutes),\n\t\tmm: () => `${minutes}`.padStart(2, \"0\"),\n\t\ts: () => String(seconds),\n\t\tso: () => formatOrdinal(seconds),\n\t\tss: () => `${seconds}`.padStart(2, \"0\"),\n\t\tSSS: () => `${milliseconds}`.padStart(3, \"0\"),\n\t\td: () => day,\n\t\tdd: () => date.toLocaleDateString(toValue(options.locales), { weekday: \"narrow\" }),\n\t\tddd: () => date.toLocaleDateString(toValue(options.locales), { weekday: \"short\" }),\n\t\tdddd: () => date.toLocaleDateString(toValue(options.locales), { weekday: \"long\" }),\n\t\tA: () => meridiem(hours, minutes),\n\t\tAA: () => meridiem(hours, minutes, false, true),\n\t\ta: () => meridiem(hours, minutes, true),\n\t\taa: () => meridiem(hours, minutes, true, true),\n\t\tz: () => stripTimeZone(date.toLocaleDateString(toValue(options.locales), { timeZoneName: \"shortOffset\" })),\n\t\tzz: () => stripTimeZone(date.toLocaleDateString(toValue(options.locales), { timeZoneName: \"shortOffset\" })),\n\t\tzzz: () => stripTimeZone(date.toLocaleDateString(toValue(options.locales), { timeZoneName: \"shortOffset\" })),\n\t\tzzzz: () => stripTimeZone(date.toLocaleDateString(toValue(options.locales), { timeZoneName: \"longOffset\" }))\n\t};\n\treturn formatStr.replace(REGEX_FORMAT, (match, $1) => {\n\t\tvar _ref, _matches$match;\n\t\treturn (_ref = $1 !== null && $1 !== void 0 ? $1 : (_matches$match = matches[match]) === null || _matches$match === void 0 ? void 0 : _matches$match.call(matches)) !== null && _ref !== void 0 ? _ref : match;\n\t});\n}\nfunction normalizeDate(date) {\n\tif (date === null) return /* @__PURE__ */ new Date(NaN);\n\tif (date === void 0) return /* @__PURE__ */ new Date();\n\tif (date instanceof Date) return new Date(date);\n\tif (typeof date === \"string\" && !/Z$/i.test(date)) {\n\t\tconst d = date.match(REGEX_PARSE);\n\t\tif (d) {\n\t\t\tconst m = d[2] - 1 || 0;\n\t\t\tconst ms = (d[7] || \"0\").substring(0, 3);\n\t\t\treturn new Date(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms);\n\t\t}\n\t}\n\treturn new Date(date);\n}\n/**\n* Get the formatted date according to the string of tokens passed in.\n*\n* @see https://vueuse.org/useDateFormat\n* @param date - The date to format, can either be a `Date` object, a timestamp, or a string\n* @param formatStr - The combination of tokens to format the date\n* @param options - UseDateFormatOptions\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useDateFormat(date, formatStr = \"HH:mm:ss\", options = {}) {\n\treturn computed(() => formatDate(normalizeDate(toValue(date)), toValue(formatStr), options));\n}\n//#endregion\n//#region useIntervalFn/index.ts\n/**\n* Wrapper for `setInterval` with controls\n*\n* @see https://vueuse.org/useIntervalFn\n* @param cb\n* @param interval\n* @param options\n*/\nfunction useIntervalFn(cb, interval = 1e3, options = {}) {\n\tconst { immediate = true, immediateCallback = false } = options;\n\tlet timer = null;\n\tconst isActive = shallowRef(false);\n\tfunction clean() {\n\t\tif (timer) {\n\t\t\tclearInterval(timer);\n\t\t\ttimer = null;\n\t\t}\n\t}\n\tfunction pause() {\n\t\tisActive.value = false;\n\t\tclean();\n\t}\n\tfunction resume() {\n\t\tconst intervalValue = toValue(interval);\n\t\tif (intervalValue <= 0) return;\n\t\tisActive.value = true;\n\t\tif (immediateCallback) cb();\n\t\tclean();\n\t\tif (isActive.value) timer = setInterval(cb, intervalValue);\n\t}\n\tif (immediate && isClient) resume();\n\tif (isRef(interval) || typeof interval === \"function\") tryOnScopeDispose(watch(interval, () => {\n\t\tif (isActive.value && isClient) resume();\n\t}));\n\ttryOnScopeDispose(pause);\n\treturn {\n\t\tisActive: shallowReadonly(isActive),\n\t\tpause,\n\t\tresume\n\t};\n}\n//#endregion\n//#region useInterval/index.ts\nfunction useInterval(interval = 1e3, options = {}) {\n\tconst { controls: exposeControls = false, immediate = true, callback } = options;\n\tconst counter = shallowRef(0);\n\tconst update = () => counter.value += 1;\n\tconst reset = () => {\n\t\tcounter.value = 0;\n\t};\n\tconst controls = useIntervalFn(callback ? () => {\n\t\tupdate();\n\t\tcallback(counter.value);\n\t} : update, interval, { immediate });\n\tif (exposeControls) return {\n\t\tcounter: shallowReadonly(counter),\n\t\treset,\n\t\t...controls\n\t};\n\telse return shallowReadonly(counter);\n}\n//#endregion\n//#region useLastChanged/index.ts\nfunction useLastChanged(source, options = {}) {\n\tvar _options$initialValue;\n\tconst ms = shallowRef((_options$initialValue = options.initialValue) !== null && _options$initialValue !== void 0 ? _options$initialValue : null);\n\twatch(source, () => ms.value = timestamp(), options);\n\treturn shallowReadonly(ms);\n}\n//#endregion\n//#region useTimeoutFn/index.ts\n/**\n* Wrapper for `setTimeout` with controls.\n*\n* @param cb\n* @param interval\n* @param options\n*/\nfunction useTimeoutFn(cb, interval, options = {}) {\n\tconst { immediate = true, immediateCallback = false } = options;\n\tconst isPending = shallowRef(false);\n\tlet timer;\n\tfunction clear() {\n\t\tif (timer) {\n\t\t\tclearTimeout(timer);\n\t\t\ttimer = void 0;\n\t\t}\n\t}\n\tfunction stop() {\n\t\tisPending.value = false;\n\t\tclear();\n\t}\n\tfunction start(...args) {\n\t\tif (immediateCallback) cb();\n\t\tclear();\n\t\tisPending.value = true;\n\t\ttimer = setTimeout(() => {\n\t\t\tisPending.value = false;\n\t\t\ttimer = void 0;\n\t\t\tcb(...args);\n\t\t}, toValue(interval));\n\t}\n\tif (immediate) {\n\t\tisPending.value = true;\n\t\tif (isClient) start();\n\t}\n\ttryOnScopeDispose(stop);\n\treturn {\n\t\tisPending: shallowReadonly(isPending),\n\t\tstart,\n\t\tstop\n\t};\n}\n//#endregion\n//#region useTimeout/index.ts\nfunction useTimeout(interval = 1e3, options = {}) {\n\tconst { controls: exposeControls = false, callback } = options;\n\tconst controls = useTimeoutFn(callback !== null && callback !== void 0 ? callback : noop, interval, options);\n\tconst ready = computed(() => !controls.isPending.value);\n\tif (exposeControls) return {\n\t\tready,\n\t\t...controls\n\t};\n\telse return ready;\n}\n//#endregion\n//#region useToNumber/index.ts\n/**\n* Reactively convert a string ref to number.\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useToNumber(value, options = {}) {\n\tconst { method = \"parseFloat\", radix, nanToZero } = options;\n\treturn computed(() => {\n\t\tlet resolved = toValue(value);\n\t\tif (typeof method === \"function\") resolved = method(resolved);\n\t\telse if (typeof resolved === \"string\") resolved = Number[method](resolved, radix);\n\t\tif (nanToZero && Number.isNaN(resolved)) resolved = 0;\n\t\treturn resolved;\n\t});\n}\n//#endregion\n//#region useToString/index.ts\n/**\n* Reactively convert a ref to string.\n*\n* @see https://vueuse.org/useToString\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useToString(value) {\n\treturn computed(() => `${toValue(value)}`);\n}\n//#endregion\n//#region useToggle/index.ts\n/**\n* A boolean ref with a toggler\n*\n* @see https://vueuse.org/useToggle\n* @param [initialValue]\n* @param options\n*\n* @__NO_SIDE_EFFECTS__\n*/\nfunction useToggle(initialValue = false, options = {}) {\n\tconst { truthyValue = true, falsyValue = false } = options;\n\tconst valueIsRef = isRef(initialValue);\n\tconst _value = shallowRef(initialValue);\n\tfunction toggle(value) {\n\t\tif (arguments.length) {\n\t\t\t_value.value = value;\n\t\t\treturn _value.value;\n\t\t} else {\n\t\t\tconst truthy = toValue(truthyValue);\n\t\t\t_value.value = _value.value === truthy ? toValue(falsyValue) : truthy;\n\t\t\treturn _value.value;\n\t\t}\n\t}\n\tif (valueIsRef) return toggle;\n\telse return [_value, toggle];\n}\n//#endregion\n//#region watchArray/index.ts\n/**\n* Watch for an array with additions and removals.\n*\n* @see https://vueuse.org/watchArray\n*/\nfunction watchArray(source, cb, options) {\n\tlet oldList = (options === null || options === void 0 ? void 0 : options.immediate) ? [] : [...typeof source === \"function\" ? source() : Array.isArray(source) ? source : toValue(source)];\n\treturn watch(source, (newList, _, onCleanup) => {\n\t\tconst oldListRemains = Array.from({ length: oldList.length });\n\t\tconst added = [];\n\t\tfor (const obj of newList) {\n\t\t\tlet found = false;\n\t\t\tfor (let i = 0; i < oldList.length; i++) if (!oldListRemains[i] && obj === oldList[i]) {\n\t\t\t\toldListRemains[i] = true;\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!found) added.push(obj);\n\t\t}\n\t\tconst removed = oldList.filter((_, i) => !oldListRemains[i]);\n\t\tcb(newList, oldList, added, removed, onCleanup);\n\t\toldList = [...newList];\n\t}, options);\n}\n//#endregion\n//#region watchAtMost/index.ts\nfunction watchAtMost(source, cb, options) {\n\tconst { count, ...watchOptions } = options;\n\tconst current = shallowRef(0);\n\tconst { stop, resume, pause } = watchWithFilter(source, (...args) => {\n\t\tcurrent.value += 1;\n\t\tif (current.value >= toValue(count)) nextTick(() => stop());\n\t\tcb(...args);\n\t}, watchOptions);\n\treturn {\n\t\tcount: current,\n\t\tstop,\n\t\tresume,\n\t\tpause\n\t};\n}\n//#endregion\n//#region watchDebounced/index.ts\nfunction watchDebounced(source, cb, options = {}) {\n\tconst { debounce = 0, maxWait = void 0, ...watchOptions } = options;\n\treturn watchWithFilter(source, cb, {\n\t\t...watchOptions,\n\t\teventFilter: debounceFilter(debounce, { maxWait })\n\t});\n}\n/** @deprecated use `watchDebounced` instead */\nconst debouncedWatch = watchDebounced;\n//#endregion\n//#region watchDeep/index.ts\n/**\n* Shorthand for watching value with {deep: true}\n*\n* @see https://vueuse.org/watchDeep\n*/\nfunction watchDeep(source, cb, options) {\n\treturn watch(source, cb, {\n\t\t...options,\n\t\tdeep: true\n\t});\n}\n//#endregion\n//#region watchIgnorable/index.ts\nfunction watchIgnorable(source, cb, options = {}) {\n\tconst { eventFilter = bypassFilter, ...watchOptions } = options;\n\tconst filteredCb = createFilterWrapper(eventFilter, cb);\n\tlet ignoreUpdates;\n\tlet ignorePrevAsyncUpdates;\n\tlet stop;\n\tif (watchOptions.flush === \"sync\") {\n\t\tlet ignore = false;\n\t\tignorePrevAsyncUpdates = () => {};\n\t\tignoreUpdates = (updater) => {\n\t\t\tignore = true;\n\t\t\tupdater();\n\t\t\tignore = false;\n\t\t};\n\t\tstop = watch(source, (...args) => {\n\t\t\tif (!ignore) filteredCb(...args);\n\t\t}, watchOptions);\n\t} else {\n\t\tconst disposables = [];\n\t\tlet ignoreCounter = 0;\n\t\tlet syncCounter = 0;\n\t\tignorePrevAsyncUpdates = () => {\n\t\t\tignoreCounter = syncCounter;\n\t\t};\n\t\tdisposables.push(watch(source, () => {\n\t\t\tsyncCounter++;\n\t\t}, {\n\t\t\t...watchOptions,\n\t\t\tflush: \"sync\"\n\t\t}));\n\t\tignoreUpdates = (updater) => {\n\t\t\tconst syncCounterPrev = syncCounter;\n\t\t\tupdater();\n\t\t\tignoreCounter += syncCounter - syncCounterPrev;\n\t\t};\n\t\tdisposables.push(watch(source, (...args) => {\n\t\t\tconst ignore = ignoreCounter > 0 && ignoreCounter === syncCounter;\n\t\t\tignoreCounter = 0;\n\t\t\tsyncCounter = 0;\n\t\t\tif (ignore) return;\n\t\t\tfilteredCb(...args);\n\t\t}, watchOptions));\n\t\tstop = () => {\n\t\t\tdisposables.forEach((fn) => fn());\n\t\t};\n\t}\n\treturn {\n\t\tstop,\n\t\tignoreUpdates,\n\t\tignorePrevAsyncUpdates\n\t};\n}\n/** @deprecated use `watchIgnorable` instead */\nconst ignorableWatch = watchIgnorable;\n//#endregion\n//#region watchImmediate/index.ts\n/**\n* Shorthand for watching value with {immediate: true}\n*\n* @see https://vueuse.org/watchImmediate\n*/\nfunction watchImmediate(source, cb, options) {\n\treturn watch(source, cb, {\n\t\t...options,\n\t\timmediate: true\n\t});\n}\n//#endregion\n//#region watchOnce/index.ts\n/**\n* Shorthand for watching value with { once: true }\n*\n* @see https://vueuse.org/watchOnce\n*/\nfunction watchOnce(source, cb, options) {\n\treturn watch(source, cb, {\n\t\t...options,\n\t\tonce: true\n\t});\n}\n//#endregion\n//#region watchThrottled/index.ts\nfunction watchThrottled(source, cb, options = {}) {\n\tconst { throttle = 0, trailing = true, leading = true, ...watchOptions } = options;\n\treturn watchWithFilter(source, cb, {\n\t\t...watchOptions,\n\t\teventFilter: throttleFilter(throttle, trailing, leading)\n\t});\n}\n/** @deprecated use `watchThrottled` instead */\nconst throttledWatch = watchThrottled;\n//#endregion\n//#region watchTriggerable/index.ts\nfunction watchTriggerable(source, cb, options = {}) {\n\tlet cleanupFn;\n\tfunction onEffect() {\n\t\tif (!cleanupFn) return;\n\t\tconst fn = cleanupFn;\n\t\tcleanupFn = void 0;\n\t\tfn();\n\t}\n\t/** Register the function `cleanupFn` */\n\tfunction onCleanup(callback) {\n\t\tcleanupFn = callback;\n\t}\n\tconst _cb = (value, oldValue) => {\n\t\tonEffect();\n\t\treturn cb(value, oldValue, onCleanup);\n\t};\n\tconst res = watchIgnorable(source, _cb, options);\n\tconst { ignoreUpdates } = res;\n\tconst trigger = () => {\n\t\tlet res;\n\t\tignoreUpdates(() => {\n\t\t\tres = _cb(getWatchSources(source), getOldValue(source));\n\t\t});\n\t\treturn res;\n\t};\n\treturn {\n\t\t...res,\n\t\ttrigger\n\t};\n}\nfunction getWatchSources(sources) {\n\tif (isReactive(sources)) return sources;\n\tif (Array.isArray(sources)) return sources.map((item) => toValue(item));\n\treturn toValue(sources);\n}\nfunction getOldValue(source) {\n\treturn Array.isArray(source) ? source.map(() => void 0) : void 0;\n}\n//#endregion\n//#region whenever/index.ts\nfunction whenever(source, cb, options) {\n\tconst stop = watch(source, (v, ov, onInvalidate) => {\n\t\tif (v) {\n\t\t\tif (options === null || options === void 0 ? void 0 : options.once) nextTick(() => stop());\n\t\t\tcb(v, ov, onInvalidate);\n\t\t}\n\t}, {\n\t\t...options,\n\t\tonce: false\n\t});\n\treturn stop;\n}\n//#endregion\nexport { assert, autoResetRef, bypassFilter, camelize, clamp, computedEager, computedWithControl, containsProp, controlledComputed, controlledRef, createDisposableDirective, createEventHook, createFilterWrapper, createGlobalState, createInjectionState, createReactiveFn, createRef, createSharedComposable, createSingletonPromise, debounceFilter, debouncedRef, debouncedWatch, eagerComputed, extendRef, formatDate, get, getLifeCycleTarget, hasOwn, hyphenate, identity, ignorableWatch, increaseWithUnit, injectLocal, invoke, isClient, isDef, isDefined, isIOS, isObject, isWorker, makeDestructurable, noop, normalizeDate, notNullish, now, objectEntries, objectOmit, objectPick, pausableFilter, pausableWatch, promiseTimeout, provideLocal, pxValue, rand, reactify, reactifyObject, reactiveComputed, reactiveOmit, reactivePick, refAutoReset, refDebounced, refDefault, refManualReset, refThrottled, refWithControl, set, syncRef, syncRefs, throttleFilter, throttledRef, throttledWatch, timestamp, toArray, toReactive, toRef, toRefs, tryOnBeforeMount, tryOnBeforeUnmount, tryOnMounted, tryOnScopeDispose, tryOnUnmounted, until, useArrayDifference, useArrayEvery, useArrayFilter, useArrayFind, useArrayFindIndex, useArrayFindLast, useArrayIncludes, useArrayJoin, useArrayMap, useArrayReduce, useArraySome, useArrayUnique, useCounter, useDateFormat, useDebounce, useDebounceFn, useInterval, useIntervalFn, useLastChanged, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useToNumber, useToString, useToggle, watchArray, watchAtMost, watchDebounced, watchDeep, watchIgnorable, watchImmediate, watchOnce, watchPausable, watchThrottled, watchTriggerable, watchWithFilter, whenever };\n"],"x_google_ignoreList":[0],"mappings":"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"}