@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.
- package/README.md +2 -4
- package/dist/{AiChatSidebar-jVlXXND3.js → AiChatSidebar-pOxCZWz9.js} +14 -14
- package/dist/{AiFeatureMenu-C1HCntyQ.js → AiFeatureMenu-Bljk6Qjv.js} +7 -7
- package/dist/{BlockIssueBadge-JhNgcUmZ.js → BlockIssueBadge-D5oGxOQP.js} +5 -5
- package/dist/{BlockPreviewCanvas-C_rA5LJN.js → BlockPreviewCanvas-DXGjUECG.js} +27 -27
- package/dist/{CloudHeaderExtras-DvYyNsPB.js → CloudHeaderExtras-DaocwNmy.js} +5 -5
- package/dist/{CloudPanels-CDPhPVdd.js → CloudPanels-CyZAnSJY.js} +7 -7
- package/dist/{CollaboratorBar-Co9UPoB0.js → CollaboratorBar-C7Zca3g1.js} +4 -4
- package/dist/{CommentsPanel-CRcVN9Ri.js → CommentsPanel-CNOb7YCm.js} +2 -2
- package/dist/{CommentsSidebar-gDU977br.js → CommentsSidebar-VmwjU9va.js} +14 -14
- package/dist/{CountdownBlock-CEzrfe5R.js → CountdownBlock-DSvbf3qU.js} +3 -3
- package/dist/{CountdownToolbar-B00zhkNJ.js → CountdownToolbar-C2kfS6Oy.js} +31 -30
- package/dist/{DesignReferenceSidebar-DedivZZl.js → DesignReferenceSidebar-QC4gEUWp.js} +11 -11
- package/dist/{IssuesPanel-C-PjdmAV.js → IssuesPanel-DL2Xr14_.js} +8 -8
- package/dist/{LoadingTrack-BlTL4zFv.js → LoadingTrack-C2jKCU2d.js} +1 -1
- package/dist/LogicTagInsertButton-D8IwH-9Z.js +1071 -0
- package/dist/{MediaPanels-BpQNY8YX.js → MediaPanels-Cc4UkfG1.js} +2 -2
- package/dist/MergeTagInput-QI-5KG2R.js +81 -0
- package/dist/{MergeTagModeToggle-DGuzSAdX.js → MergeTagModeToggle-D793Bj_E.js} +14 -55
- package/dist/{ParagraphEditor-jMKLLTa8.js → ParagraphEditor-DkkPSexG.js} +65 -66
- package/dist/{RestoreVersionDialog-DG1jUdBM.js → RestoreVersionDialog-BgueZnZr.js} +5 -5
- package/dist/{RichTextEditorContent-JrNEg0kv.js → RichTextEditorContent-BC5UTVnb.js} +11 -11
- package/dist/{SaveBlockDialog-C0KC-OKs.js → SaveBlockDialog-BuTuVlLr.js} +12 -11
- package/dist/{SavedBlocksBrowserModal-zyOiRgWZ.js → SavedBlocksBrowserModal-Srhix8BB.js} +17 -16
- package/dist/{SavedBlocksPanels-epMd799w.js → SavedBlocksPanels-B2iScCS-.js} +2 -2
- package/dist/{SavedBlocksPickBar-CJqqQ3jd.js → SavedBlocksPickBar-cI7bDQQi.js} +4 -4
- package/dist/{TemplateScoringPanel-m2FOeaai.js → TemplateScoringPanel-C2Rdlyn6.js} +16 -16
- package/dist/TemplateSettings-C_5leDdF.js +245 -0
- package/dist/{TestEmailModal-D58kYkMV.js → TestEmailModal-DJ5q_u4N.js} +10 -10
- package/dist/{TestEmailPanel-BmFVBIQt.js → TestEmailPanel-CP24UGst.js} +2 -2
- package/dist/{TitleEditor-C4BGPXnf.js → TitleEditor-QBBOXtxx.js} +15 -15
- package/dist/ToggleSwitch-JvQ_CmI1.js +102 -0
- package/dist/Toolbar-COD2TW20.js +2426 -0
- package/dist/{TplModal-BIDJw4Kj.js → TplModal-C8xGjC1l.js} +5 -5
- package/dist/{VersionHistoryMenu-dt_aZQfh.js → VersionHistoryMenu-BVQityes.js} +10 -10
- package/dist/{VersionHistoryPanels-B_5SBRrr.js → VersionHistoryPanels-BrK6na4A.js} +2 -2
- package/dist/{VersionPreviewBanner-DttvOkwd.js → VersionPreviewBanner-BaMSgA1O.js} +3 -3
- package/dist/{blockTypeIcons-CzTizYmK.js → blockTypeIcons-CdXugKyV.js} +16 -37
- package/dist/bundle-stats.json +8 -8
- package/dist/cdn/chunks/{AiChatSidebar-DeZl9Tk0.js → AiChatSidebar-CjSEoK4x.js} +8 -8
- package/dist/cdn/chunks/{AiChatSidebar-DeZl9Tk0.js.map → AiChatSidebar-CjSEoK4x.js.map} +1 -1
- package/dist/cdn/chunks/{AiFeatureMenu-Bv8jMu9p.js → AiFeatureMenu-l0K5TOSn.js} +6 -6
- package/dist/cdn/chunks/{AiFeatureMenu-Bv8jMu9p.js.map → AiFeatureMenu-l0K5TOSn.js.map} +1 -1
- package/dist/cdn/chunks/{BlockIssueBadge-B6PpoOPv.js → BlockIssueBadge-9hHpaXb9.js} +5 -5
- package/dist/cdn/chunks/{BlockIssueBadge-B6PpoOPv.js.map → BlockIssueBadge-9hHpaXb9.js.map} +1 -1
- package/dist/cdn/chunks/{BlockPreviewCanvas-DfEtDosD.js → BlockPreviewCanvas-lQrAdgG3.js} +30 -30
- package/dist/cdn/chunks/{BlockPreviewCanvas-DfEtDosD.js.map → BlockPreviewCanvas-lQrAdgG3.js.map} +1 -1
- package/dist/cdn/chunks/{CloudHeaderExtras-Hk98ub-C.js → CloudHeaderExtras-CXNe7Q-4.js} +5 -5
- package/dist/cdn/chunks/{CloudHeaderExtras-Hk98ub-C.js.map → CloudHeaderExtras-CXNe7Q-4.js.map} +1 -1
- package/dist/cdn/chunks/{CloudPanels-Ba3GLmvF.js → CloudPanels-bHhh9AUA.js} +6 -6
- package/dist/cdn/chunks/{CloudPanels-Ba3GLmvF.js.map → CloudPanels-bHhh9AUA.js.map} +1 -1
- package/dist/cdn/chunks/{CollaboratorBar-D2dCQ9gg.js → CollaboratorBar-DgqcaGGI.js} +5 -5
- package/dist/cdn/chunks/{CollaboratorBar-D2dCQ9gg.js.map → CollaboratorBar-DgqcaGGI.js.map} +1 -1
- package/dist/cdn/chunks/{CommentsPanel-CV2HveQk.js → CommentsPanel-Cy4TlTHC.js} +3 -3
- package/dist/cdn/chunks/{CommentsPanel-CV2HveQk.js.map → CommentsPanel-Cy4TlTHC.js.map} +1 -1
- package/dist/cdn/chunks/{CommentsSidebar-Dok_vaRc.js → CommentsSidebar-C7oAP3Mx.js} +5 -5
- package/dist/cdn/chunks/{CommentsSidebar-Dok_vaRc.js.map → CommentsSidebar-C7oAP3Mx.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownBlock-DGDl3ota.js → CountdownBlock-DdC8Lg5F.js} +4 -4
- package/dist/cdn/chunks/{CountdownBlock-DGDl3ota.js.map → CountdownBlock-DdC8Lg5F.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownToolbar-B9Rin64t.js → CountdownToolbar-CN9h4nlC.js} +22 -21
- package/dist/cdn/chunks/{CountdownToolbar-B9Rin64t.js.map → CountdownToolbar-CN9h4nlC.js.map} +1 -1
- package/dist/cdn/chunks/{DesignReferenceSidebar-eCuTFak2.js → DesignReferenceSidebar-Bjo0M-AY.js} +7 -7
- package/dist/cdn/chunks/{DesignReferenceSidebar-eCuTFak2.js.map → DesignReferenceSidebar-Bjo0M-AY.js.map} +1 -1
- package/dist/cdn/chunks/{IssuesPanel-CP7FEzw7.js → IssuesPanel-DdFk-Blf.js} +6 -6
- package/dist/cdn/chunks/{IssuesPanel-CP7FEzw7.js.map → IssuesPanel-DdFk-Blf.js.map} +1 -1
- package/dist/cdn/chunks/{LoadingTrack-Cm3TDKb3.js → LoadingTrack-Ba5xh5HD.js} +2 -2
- package/dist/cdn/chunks/{LoadingTrack-Cm3TDKb3.js.map → LoadingTrack-Ba5xh5HD.js.map} +1 -1
- package/dist/cdn/chunks/LogicTagInsertButton-DpyPozop.js +1035 -0
- package/dist/cdn/chunks/LogicTagInsertButton-DpyPozop.js.map +1 -0
- package/dist/cdn/chunks/{MediaPanels-TYrKKHX5.js → MediaPanels-kX9AZQ7K.js} +3 -3
- package/dist/cdn/chunks/{MediaPanels-TYrKKHX5.js.map → MediaPanels-kX9AZQ7K.js.map} +1 -1
- package/dist/cdn/chunks/MergeTagInput-ERJr7bP_.js +83 -0
- package/dist/cdn/chunks/MergeTagInput-ERJr7bP_.js.map +1 -0
- package/dist/cdn/chunks/{MergeTagModeToggle-QGTUIWWo.js → MergeTagModeToggle-n3nvSNeQ.js} +5 -5
- package/dist/cdn/chunks/{MergeTagModeToggle-QGTUIWWo.js.map → MergeTagModeToggle-n3nvSNeQ.js.map} +1 -1
- package/dist/cdn/chunks/{ParagraphEditor-D1tsPv4v.js → ParagraphEditor-DO4RzP8l.js} +40 -40
- package/dist/cdn/chunks/{ParagraphEditor-D1tsPv4v.js.map → ParagraphEditor-DO4RzP8l.js.map} +1 -1
- package/dist/cdn/chunks/{RestoreVersionDialog-BeCxNPLS.js → RestoreVersionDialog-CzZ_sFnz.js} +5 -5
- package/dist/cdn/chunks/{RestoreVersionDialog-BeCxNPLS.js.map → RestoreVersionDialog-CzZ_sFnz.js.map} +1 -1
- package/dist/cdn/chunks/{RichTextEditorContent-BBxzACFQ.js → RichTextEditorContent-Ch5zeyZ7.js} +8 -8
- package/dist/cdn/chunks/{RichTextEditorContent-BBxzACFQ.js.map → RichTextEditorContent-Ch5zeyZ7.js.map} +1 -1
- package/dist/cdn/chunks/{SaveBlockDialog-CLgh_g7H.js → SaveBlockDialog-LgxYrXyx.js} +10 -9
- package/dist/cdn/chunks/{SaveBlockDialog-CLgh_g7H.js.map → SaveBlockDialog-LgxYrXyx.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksBrowserModal-B4TcUJJe.js → SavedBlocksBrowserModal-CdeSsTpb.js} +9 -9
- package/dist/cdn/chunks/{SavedBlocksBrowserModal-B4TcUJJe.js.map → SavedBlocksBrowserModal-CdeSsTpb.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksPanels-CaBsHoRC.js → SavedBlocksPanels-B5hakNJj.js} +3 -3
- package/dist/cdn/chunks/{SavedBlocksPanels-CaBsHoRC.js.map → SavedBlocksPanels-B5hakNJj.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksPickBar-iG35XCDx.js → SavedBlocksPickBar-Cl6PLwwV.js} +5 -5
- package/dist/cdn/chunks/{SavedBlocksPickBar-iG35XCDx.js.map → SavedBlocksPickBar-Cl6PLwwV.js.map} +1 -1
- package/dist/cdn/chunks/{TemplateScoringPanel-DuQJBykq.js → TemplateScoringPanel--JxR6CsQ.js} +6 -6
- package/dist/cdn/chunks/{TemplateScoringPanel-DuQJBykq.js.map → TemplateScoringPanel--JxR6CsQ.js.map} +1 -1
- package/dist/cdn/chunks/TemplateSettings-DjXiiiNr.js +207 -0
- package/dist/cdn/chunks/TemplateSettings-DjXiiiNr.js.map +1 -0
- package/dist/cdn/chunks/{TestEmailModal-D6Woss3r.js → TestEmailModal-BAuDxJtD.js} +9 -9
- package/dist/cdn/chunks/{TestEmailModal-D6Woss3r.js.map → TestEmailModal-BAuDxJtD.js.map} +1 -1
- package/dist/cdn/chunks/{TestEmailPanel-CWQFB7J3.js → TestEmailPanel-GUGZisLp.js} +3 -3
- package/dist/cdn/chunks/{TestEmailPanel-CWQFB7J3.js.map → TestEmailPanel-GUGZisLp.js.map} +1 -1
- package/dist/cdn/chunks/{TitleEditor-CbY1tgSl.js → TitleEditor-uKu33Nwr.js} +12 -12
- package/dist/cdn/chunks/{TitleEditor-CbY1tgSl.js.map → TitleEditor-uKu33Nwr.js.map} +1 -1
- package/dist/cdn/chunks/ToggleSwitch-CDy8OfcB.js +104 -0
- package/dist/cdn/chunks/ToggleSwitch-CDy8OfcB.js.map +1 -0
- package/dist/cdn/chunks/Toolbar-dxDYwN5E.js +2385 -0
- package/dist/cdn/chunks/Toolbar-dxDYwN5E.js.map +1 -0
- package/dist/cdn/chunks/{TplModal-CGpp-d_r.js → TplModal-DuwS2ifK.js} +5 -5
- package/dist/cdn/chunks/{TplModal-CGpp-d_r.js.map → TplModal-DuwS2ifK.js.map} +1 -1
- package/dist/cdn/chunks/{VersionHistoryMenu-ByVJXDbK.js → VersionHistoryMenu-Dij1pTEb.js} +6 -6
- package/dist/cdn/chunks/{VersionHistoryMenu-ByVJXDbK.js.map → VersionHistoryMenu-Dij1pTEb.js.map} +1 -1
- package/dist/cdn/chunks/{VersionHistoryPanels-CQJ5OggF.js → VersionHistoryPanels-GeR6MStB.js} +3 -3
- package/dist/cdn/chunks/{VersionHistoryPanels-CQJ5OggF.js.map → VersionHistoryPanels-GeR6MStB.js.map} +1 -1
- package/dist/cdn/chunks/{VersionPreviewBanner-G4lLbfr8.js → VersionPreviewBanner-Df3FVlig.js} +4 -4
- package/dist/cdn/chunks/{VersionPreviewBanner-G4lLbfr8.js.map → VersionPreviewBanner-Df3FVlig.js.map} +1 -1
- package/dist/cdn/chunks/{blockTypeIcons-CQY-vxdM.js → blockTypeIcons-raBjStuv.js} +2 -2
- package/dist/cdn/chunks/{blockTypeIcons-CQY-vxdM.js.map → blockTypeIcons-raBjStuv.js.map} +1 -1
- package/dist/cdn/chunks/{cloud-BLgCKP7Z.js → cloud-eaXyxZ8l.js} +2 -2
- package/dist/cdn/chunks/{cloud-BLgCKP7Z.js.map → cloud-eaXyxZ8l.js.map} +1 -1
- package/dist/cdn/chunks/{createCloudRuntime-ClvtMBF1.js → createCloudRuntime-D5bXzcTe.js} +6 -6
- package/dist/cdn/chunks/{createCloudRuntime-ClvtMBF1.js.map → createCloudRuntime-D5bXzcTe.js.map} +1 -1
- package/dist/cdn/chunks/{dist-BW6Y49zE.js → dist-BRZhN8qJ.js} +4 -4
- package/dist/cdn/chunks/dist-BRZhN8qJ.js.map +1 -0
- package/dist/cdn/chunks/{dist-CAFTQ6Y2.js → dist-CXB2_kBa.js} +27 -22
- package/dist/cdn/chunks/dist-CXB2_kBa.js.map +1 -0
- package/dist/cdn/chunks/{draggable-kbOhCgnk.js → draggable-IB4x6w2O.js} +1477 -1470
- package/dist/cdn/chunks/draggable-IB4x6w2O.js.map +1 -0
- package/dist/cdn/chunks/{editor-modal-B6IdQWlf.js → editor-modal-C_xYN_66.js} +7 -7
- package/dist/cdn/chunks/{editor-modal-B6IdQWlf.js.map → editor-modal-C_xYN_66.js.map} +1 -1
- package/dist/cdn/chunks/en-BwfjKb4M.js +2 -0
- package/dist/cdn/chunks/{extensions-D2YIhF7u.js → extensions-Bhu8UEE5.js} +105 -45
- package/dist/cdn/chunks/extensions-Bhu8UEE5.js.map +1 -0
- package/dist/cdn/chunks/{icons-DdrAicM2.js → icons-BKkJ-5xF.js} +43 -43
- package/dist/cdn/chunks/{icons-DdrAicM2.js.map → icons-BKkJ-5xF.js.map} +1 -1
- package/dist/cdn/chunks/{keys-DXYJTLZF.js → keys-dJbD1QPs.js} +2 -2
- package/dist/cdn/chunks/{keys-DXYJTLZF.js.map → keys-dJbD1QPs.js.map} +1 -1
- package/dist/cdn/chunks/socialIcons-9VrG8X3m.js +1054 -0
- package/dist/cdn/chunks/socialIcons-9VrG8X3m.js.map +1 -0
- package/dist/cdn/chunks/{src-fn7uy1FD.js → src-CZ-W8YBa.js} +3 -3
- package/dist/cdn/chunks/{src-fn7uy1FD.js.map → src-CZ-W8YBa.js.map} +1 -1
- package/dist/cdn/chunks/templateSettingsFields-YCFVBVYh.js +36 -0
- package/dist/cdn/chunks/templateSettingsFields-YCFVBVYh.js.map +1 -0
- package/dist/cdn/chunks/{tiptap-Epe8m3Vo.js → tiptap-DhLuKyDc.js} +2776 -2773
- package/dist/cdn/chunks/tiptap-DhLuKyDc.js.map +1 -0
- package/dist/cdn/chunks/{useAliveFlag-CT9gjvO_.js → useAliveFlag-DAlQLbM2.js} +2 -2
- package/dist/cdn/chunks/{useAliveFlag-CT9gjvO_.js.map → useAliveFlag-DAlQLbM2.js.map} +1 -1
- package/dist/cdn/chunks/{useCloudI18n-OezCj0cx.js → useCloudI18n-C09JcFS0.js} +3 -3
- package/dist/cdn/chunks/{useCloudI18n-OezCj0cx.js.map → useCloudI18n-C09JcFS0.js.map} +1 -1
- package/dist/cdn/chunks/useEditorCore-BHmIp1hW.js +2592 -0
- package/dist/cdn/chunks/useEditorCore-BHmIp1hW.js.map +1 -0
- package/dist/cdn/chunks/useEditorRoot-DFx2fXJP.js +10 -0
- package/dist/cdn/chunks/{useEditorRoot-ByHPMqYT.js.map → useEditorRoot-DFx2fXJP.js.map} +1 -1
- package/dist/cdn/chunks/{useI18n-BhE7ndNr.js → useI18n-DTZ9sIcv.js} +3 -3
- package/dist/cdn/chunks/{useI18n-BhE7ndNr.js.map → useI18n-DTZ9sIcv.js.map} +1 -1
- package/dist/cdn/chunks/useLogicTag-E2V0Xdcb.js +38 -0
- package/dist/cdn/chunks/useLogicTag-E2V0Xdcb.js.map +1 -0
- package/dist/cdn/chunks/{useMergeTag-DE2mpy1w.js → useMergeTag-BE8oDoha.js} +3 -3
- package/dist/cdn/chunks/{useMergeTag-DE2mpy1w.js.map → useMergeTag-BE8oDoha.js.map} +1 -1
- package/dist/cdn/chunks/{usePopoverPosition-BPL891uG.js → usePopoverPosition-gB9q-ql7.js} +3 -3
- package/dist/cdn/chunks/{usePopoverPosition-BPL891uG.js.map → usePopoverPosition-gB9q-ql7.js.map} +1 -1
- package/dist/cdn/chunks/{useScrollToBlock-DwF4pVur.js → useScrollToBlock-CtTXwmiU.js} +3 -3
- package/dist/cdn/chunks/{useScrollToBlock-DwF4pVur.js.map → useScrollToBlock-CtTXwmiU.js.map} +1 -1
- package/dist/cdn/editor.css +1 -1
- package/dist/cdn/editor.js +809 -3337
- package/dist/cdn/editor.js.map +1 -1
- package/dist/{check-9xX6RVHz.js → check-eqb2JhqU.js} +1 -1
- package/dist/{chevron-down-J5hFJ6TL.js → chevron-down-Dkr-7Ywl.js} +1 -1
- package/dist/{chevron-right-BJuo5PQ-.js → chevron-right-Bge4XF_B.js} +1 -1
- package/dist/{chevron-up-Qfi5k52_.js → chevron-up-CQAyl0kC.js} +1 -1
- package/dist/{circle-alert-BiArYmkB.js → circle-alert-CYgTHKWr.js} +1 -1
- package/dist/{clock-BkYJZ7Y0.js → clock-BgSJZJP5.js} +1 -1
- package/dist/{cloud-DdidMW6f.js → cloud-C9xWZXhg.js} +1 -1
- package/dist/{copy-BRLUNHwF.js → copy-mw6PVnOJ.js} +1 -1
- package/dist/{createCloudRuntime-CNFXaTNQ.js → createCloudRuntime-BGd5--Bq.js} +5 -5
- package/dist/{createLucideIcon-CDDkF1Tm.js → createLucideIcon-BxY5yz5u.js} +6 -6
- package/dist/{dist-D8i1ixHK.js → dist-8VFzbeu9.js} +3 -3
- package/dist/{dist-DBirAJIs.js → dist-BDuPwOyn.js} +26 -21
- package/dist/{dist-CtF9STPS.js → dist-BJM3eFyT.js} +1 -1
- package/dist/{dist-DkcA6epL.js → dist-BdHF7nyq.js} +3 -3
- package/dist/{dist-ByT5fgKq.js → dist-Bl4rxpX9.js} +1 -1
- package/dist/{dist-BVqAYoRB.js → dist-BmsLcnrO.js} +4 -4
- package/dist/{dist-CtMXAH7a.js → dist-BxVnMgXZ.js} +1 -1
- package/dist/{dist-DC-3T0ED.js → dist-CQSVro7b.js} +1 -1
- package/dist/{dist-f7HXo6j6.js → dist-DQbOebGW.js} +1 -1
- package/dist/{dist-DL9334yz.js → dist-DerFNpDY.js} +3 -3
- package/dist/{dist-D08oVYhr.js → dist-Djmzp6wi.js} +1 -1
- package/dist/{dist-D7WY8VPq.js → dist-DyrEOKEJ.js} +1 -1
- package/dist/{dist-DzdeVn-W.js → dist-EDkj3Ub1.js} +1 -1
- package/dist/{dist-C1tsW_99.js → dist-wyXxj3R1.js} +1 -1
- package/dist/{editor-modal-uAEB6xKz.js → editor-modal-OPhP71YO.js} +20 -20
- package/dist/en-CjNopehs.js +2 -0
- package/dist/extensions-DRN-elXT.js +1645 -0
- package/dist/{eye-DwhBOaV8.js → eye-DphkRtAD.js} +1 -1
- package/dist/{image-up-CiyQNZBt.js → image-up-Qi2BXD7T.js} +1 -1
- package/dist/{info-D6A1qEiF.js → info-VSyAs02q.js} +1 -1
- package/dist/{keys-DD1rl72F.js → keys-BdoSgsz9.js} +1 -1
- package/dist/{link-tKGmYWsB.js → link-CNuozGqD.js} +1 -1
- package/dist/{list-DjZQRpeI.js → list-BA0I5Wmu.js} +1 -1
- package/dist/{loader-circle-D9ZL3Sv0.js → loader-circle-z5eeqasv.js} +1 -1
- package/dist/{message-circle-KTHxCcpB.js → message-circle-BsQ9hEup.js} +1 -1
- package/dist/package-OkXfuRoO.js +25 -0
- package/dist/{pencil-Bq-nbQ7F.js → pencil-DFVFA7Dj.js} +1 -1
- package/dist/{plus-CRMnR4IG.js → plus-D8bkVjZ7.js} +1 -1
- package/dist/{refresh-cw-D7bYS5tm.js → refresh-cw-DPB7YFuz.js} +1 -1
- package/dist/{runtime-dom.esm-bundler-PnoZU512.js → runtime-dom.esm-bundler-BGbPz4-g.js} +2 -2
- package/dist/{search-DUo0YwPz.js → search-C-dCgqIa.js} +1 -1
- package/dist/{send-DaVMQphu.js → send-Cm2fy2zm.js} +1 -1
- package/dist/{shield-check-DxaaurL9.js → shield-check-COgBYFDF.js} +1 -1
- package/dist/smartphone-v0u_MOEV.js +46 -0
- package/dist/socialIcons-DkGcpEwC.js +1130 -0
- package/dist/{sparkles-D6T6k30e.js → sparkles-Ds0RF8Iu.js} +1 -1
- package/dist/style.css +1 -1
- package/dist/templateSettingsFields-YCFVBVYh.js +34 -0
- package/dist/templatical-editor.js +895 -3498
- package/dist/{text-align-start-vreFpmCX.js → text-align-start-DiavaIm6.js} +1 -1
- package/dist/{trash-DBv8MGY6.js → trash-DnOkfu2V.js} +1 -1
- package/dist/{triangle-alert-CmNS2LLv.js → triangle-alert-DGLAyXnh.js} +1 -1
- package/dist/{upload-DDB9Fs0P.js → upload-BBDme2cy.js} +1 -1
- package/dist/{useAliveFlag-oyByIcjy.js → useAliveFlag-BkKyhkwZ.js} +1 -1
- package/dist/{useCloudI18n-C1wuXik6.js → useCloudI18n-D1iedlP3.js} +2 -2
- package/dist/{useEditorCore-jfwgLThK.js → useEditorCore-C5APBjjV.js} +1140 -2325
- package/dist/{useEditorRoot-eVv4doqZ.js → useEditorRoot-BOxn5EfP.js} +2 -2
- package/dist/{useI18n-VOtdfENx.js → useI18n-Ds_-druD.js} +2 -2
- package/dist/useLogicTag-DoHfc08B.js +36 -0
- package/dist/{useMergeTag-CQM9pFca.js → useMergeTag-DXyum3kG.js} +2 -2
- package/dist/{usePopoverPosition-gZjRywai.js → usePopoverPosition-Du-Ah8E9.js} +2 -2
- package/dist/{useScrollToBlock-C0Ehnyl4.js → useScrollToBlock-DXQYPCnJ.js} +3 -3
- package/dist/{vue.runtime.esm-bundler-DShF3P6k.js → vue.runtime.esm-bundler-CyqhBwpY.js} +1133 -1126
- package/dist/{x-B7sgO_z8.js → x-3BHV3Q6K.js} +1 -1
- package/package.json +14 -14
- package/dist/ColorPicker-BTtN94te.js +0 -501
- package/dist/FieldRow-C8nOknr_.js +0 -128
- package/dist/MergeTagInput-Cw1RoMly.js +0 -509
- package/dist/MergeTagSuggestion-BXO3UIXW.js +0 -1329
- package/dist/cdn/chunks/ColorPicker-BaonTCAQ.js +0 -502
- package/dist/cdn/chunks/ColorPicker-BaonTCAQ.js.map +0 -1
- package/dist/cdn/chunks/FieldRow-D9OJhYeb.js +0 -130
- package/dist/cdn/chunks/FieldRow-D9OJhYeb.js.map +0 -1
- package/dist/cdn/chunks/MergeTagInput-CSIThqkz.js +0 -470
- package/dist/cdn/chunks/MergeTagInput-CSIThqkz.js.map +0 -1
- package/dist/cdn/chunks/MergeTagSuggestion-CY6WK8Eb.js +0 -215
- package/dist/cdn/chunks/MergeTagSuggestion-CY6WK8Eb.js.map +0 -1
- package/dist/cdn/chunks/dist-BW6Y49zE.js.map +0 -1
- package/dist/cdn/chunks/dist-CAFTQ6Y2.js.map +0 -1
- package/dist/cdn/chunks/draggable-kbOhCgnk.js.map +0 -1
- package/dist/cdn/chunks/en-DjunooBz.js +0 -2
- package/dist/cdn/chunks/extensions-D2YIhF7u.js.map +0 -1
- package/dist/cdn/chunks/tiptap-Epe8m3Vo.js.map +0 -1
- package/dist/cdn/chunks/useEditorCore-06PtcUi1.js +0 -3698
- package/dist/cdn/chunks/useEditorCore-06PtcUi1.js.map +0 -1
- package/dist/cdn/chunks/useEditorRoot-ByHPMqYT.js +0 -10
- package/dist/en-CQWkDCpm.js +0 -2
- package/dist/extensions-CcGj7OfS.js +0 -470
|
@@ -1,470 +0,0 @@
|
|
|
1
|
-
import { E as e, F as t, K as n, N as r, Q as i, S as a, Y as o, at as s, b as c, ct as l, f as u, g as d, h as f, k as p, l as m, m as h, p as g, q as _, u as v, ut as y, y as b } from "./draggable-kbOhCgnk.js";
|
|
2
|
-
import { a as x, c as S, d as C, l as w } from "./src-Dwgq7hf4.js";
|
|
3
|
-
import { C as T } from "./useEditorCore-06PtcUi1.js";
|
|
4
|
-
import { q as E } from "./keys-DXYJTLZF.js";
|
|
5
|
-
import { t as D } from "./useI18n-BhE7ndNr.js";
|
|
6
|
-
import { n as O } from "./usePopoverPosition-BPL891uG.js";
|
|
7
|
-
import { K as k, P as A, Rt as j, n as M } from "./icons-DdrAicM2.js";
|
|
8
|
-
import { t as N } from "./_plugin-vue_export-helper-B3ysoDQm.js";
|
|
9
|
-
import { t as P } from "./useMergeTag-DE2mpy1w.js";
|
|
10
|
-
import { p as F } from "./styleConstants-C_YAPdQS.js";
|
|
11
|
-
import { n as I, r as L } from "./MergeTagSuggestion-CY6WK8Eb.js";
|
|
12
|
-
//#region src/utils/mergeTagTrigger.ts
|
|
13
|
-
function R(e, t, n, r) {
|
|
14
|
-
if (!n) return null;
|
|
15
|
-
let i = e.slice(0, t), a = i.lastIndexOf(n);
|
|
16
|
-
if (a === -1) return null;
|
|
17
|
-
let o = i.slice(a + n.length);
|
|
18
|
-
return /\s/.test(o) || r && o.includes(r) ? null : {
|
|
19
|
-
triggerStart: a,
|
|
20
|
-
caret: t,
|
|
21
|
-
query: o
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
//#endregion
|
|
25
|
-
//#region src/utils/textFieldCaret.ts
|
|
26
|
-
var z = /* @__PURE__ */ "boxSizing.width.borderTopWidth.borderRightWidth.borderBottomWidth.borderLeftWidth.borderStyle.paddingTop.paddingRight.paddingBottom.paddingLeft.fontStyle.fontVariant.fontWeight.fontStretch.fontSize.lineHeight.fontFamily.textAlign.textTransform.textIndent.letterSpacing.wordSpacing.tabSize.whiteSpace.wordWrap.wordBreak".split(".");
|
|
27
|
-
function B(e, t, n) {
|
|
28
|
-
return {
|
|
29
|
-
left: e,
|
|
30
|
-
top: t,
|
|
31
|
-
bottom: n,
|
|
32
|
-
right: e,
|
|
33
|
-
width: 0,
|
|
34
|
-
height: n - t,
|
|
35
|
-
x: e,
|
|
36
|
-
y: t,
|
|
37
|
-
toJSON: () => ({})
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
function V(e, t) {
|
|
41
|
-
let n = e.ownerDocument, r = n.defaultView;
|
|
42
|
-
if (!r) return null;
|
|
43
|
-
let i = e.tagName === "INPUT", a = r.getComputedStyle(e), o = n.createElement("div");
|
|
44
|
-
o.setAttribute("aria-hidden", "true");
|
|
45
|
-
let s = o.style;
|
|
46
|
-
s.position = "absolute", s.visibility = "hidden", s.top = "0", s.left = "0", s.overflow = "hidden", s.whiteSpace = i ? "pre" : "pre-wrap", s.wordWrap = i ? "normal" : "break-word";
|
|
47
|
-
let c = s, l = a;
|
|
48
|
-
for (let e of z) c[e] = l[e];
|
|
49
|
-
i && (s.width = "auto", s.whiteSpace = "pre");
|
|
50
|
-
let u = e.value, d = u.slice(0, t);
|
|
51
|
-
i && (d = d.replace(/\s/g, "\xA0")), o.textContent = d;
|
|
52
|
-
let f = n.createElement("span");
|
|
53
|
-
f.textContent = u.slice(t) || ".", o.appendChild(f), n.body.appendChild(o);
|
|
54
|
-
let p = f.offsetTop, m = f.offsetLeft;
|
|
55
|
-
n.body.removeChild(o);
|
|
56
|
-
let h = e.getBoundingClientRect(), g = parseFloat(a.borderTopWidth) || 0, _ = parseFloat(a.borderLeftWidth) || 0, v = parseFloat(a.lineHeight) || parseFloat(a.fontSize) || 0, y = h.left + m + _ - e.scrollLeft;
|
|
57
|
-
if (i) return B(y, h.top, h.bottom);
|
|
58
|
-
let b = h.top + p + g - e.scrollTop;
|
|
59
|
-
return B(y, b, b + v);
|
|
60
|
-
}
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region src/composables/useMergeTagAutocomplete.ts
|
|
63
|
-
var H = /* @__PURE__ */ new Set([
|
|
64
|
-
"ArrowLeft",
|
|
65
|
-
"ArrowRight",
|
|
66
|
-
"Home",
|
|
67
|
-
"End"
|
|
68
|
-
]);
|
|
69
|
-
function U(t) {
|
|
70
|
-
let { elementRef: r, modelValue: i, emit: a, mergeTags: s, syntax: c, enabled: l, onInsert: d } = t, f = w(c), m = S(c), h = u(() => l && f !== null && s.value.length > 0), g = e(E, null), v = (_(g) ? g.value : g)?.mergeTag?.suggestionEmpty ?? "No matching merge tags", y = O(), b = I(v, y), x = !1;
|
|
71
|
-
n() && o(() => {
|
|
72
|
-
x = !0, b.close();
|
|
73
|
-
});
|
|
74
|
-
function C(e) {
|
|
75
|
-
let t = e.value ?? "";
|
|
76
|
-
return R(t, e.selectionStart ?? t.length, f, m);
|
|
77
|
-
}
|
|
78
|
-
function T(e, t, n) {
|
|
79
|
-
let o = e.value ?? i(), s = o.slice(t.caret), c = m && s.startsWith(m) ? m.length : 0, l = o.slice(0, t.triggerStart), u = o.slice(t.caret + c), f = l + n.value + u, h = l.length + n.value.length;
|
|
80
|
-
d?.(), a(f), b.close(), p(() => {
|
|
81
|
-
if (x) return;
|
|
82
|
-
let e = r.value;
|
|
83
|
-
e?.focus(), e?.setSelectionRange(h, h);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
function D() {
|
|
87
|
-
if (!h.value || x) return;
|
|
88
|
-
let e = r.value;
|
|
89
|
-
if (!e) {
|
|
90
|
-
b.close();
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
let t = C(e);
|
|
94
|
-
if (!t) {
|
|
95
|
-
b.close();
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
let n = L(s.value, t.query), i = () => V(e, t.triggerStart), a = (n) => T(e, t, n);
|
|
99
|
-
b.isOpen() ? b.update({
|
|
100
|
-
items: n,
|
|
101
|
-
getRect: i,
|
|
102
|
-
onCommand: a
|
|
103
|
-
}) : b.open({
|
|
104
|
-
items: n,
|
|
105
|
-
getRect: i,
|
|
106
|
-
anchorEl: e,
|
|
107
|
-
onCommand: a
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
function k(e) {
|
|
111
|
-
return b.isOpen() ? e.key === "Escape" ? (b.close(), !0) : H.has(e.key) ? (b.close(), !1) : b.handleKeyDown(e) : !1;
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
available: h,
|
|
115
|
-
refresh: D,
|
|
116
|
-
handleKeydown: k,
|
|
117
|
-
close: () => b.close(),
|
|
118
|
-
isOpen: () => b.isOpen()
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
//#endregion
|
|
122
|
-
//#region src/composables/useMergeTagField.ts
|
|
123
|
-
function W(e) {
|
|
124
|
-
let { modelValue: t, emit: r, elementRef: a } = e, { mergeTags: s, canRequestMergeTag: c, isRequesting: l, isMergeTagValue: d, getMergeTagDisplayLabel: f, findMergeTag: m, requestMergeTag: h, syntax: g, autocomplete: _ } = P(), { canInsertLogicTag: v, isRequesting: y, requestLogicTag: b } = T(), S = i(!1), w = !1, E = !1;
|
|
125
|
-
n() && o(() => {
|
|
126
|
-
E = !0;
|
|
127
|
-
});
|
|
128
|
-
let D = U({
|
|
129
|
-
elementRef: a,
|
|
130
|
-
modelValue: t,
|
|
131
|
-
emit: r,
|
|
132
|
-
mergeTags: s,
|
|
133
|
-
syntax: g,
|
|
134
|
-
enabled: _,
|
|
135
|
-
onInsert: () => {
|
|
136
|
-
S.value = !0;
|
|
137
|
-
}
|
|
138
|
-
}), O = u(() => {
|
|
139
|
-
let e = t();
|
|
140
|
-
if (!e) return [];
|
|
141
|
-
let n = [], r = `(${g.value.source}|${g.logic.source})`, i = new RegExp(r, "g"), a = 0, o;
|
|
142
|
-
for (; (o = i.exec(e)) !== null;) {
|
|
143
|
-
o.index > a && n.push({
|
|
144
|
-
type: "text",
|
|
145
|
-
value: e.slice(a, o.index)
|
|
146
|
-
});
|
|
147
|
-
let t = o[0];
|
|
148
|
-
d(t) ? n.push({
|
|
149
|
-
type: "mergeTag",
|
|
150
|
-
value: t,
|
|
151
|
-
label: f(t)
|
|
152
|
-
}) : C(t, g) ? n.push({
|
|
153
|
-
type: "logicMergeTag",
|
|
154
|
-
value: t,
|
|
155
|
-
keyword: x(t, g)
|
|
156
|
-
}) : n.push({
|
|
157
|
-
type: "text",
|
|
158
|
-
value: t
|
|
159
|
-
}), a = o.index + t.length;
|
|
160
|
-
}
|
|
161
|
-
return a < e.length && n.push({
|
|
162
|
-
type: "text",
|
|
163
|
-
value: e.slice(a)
|
|
164
|
-
}), n;
|
|
165
|
-
}), k = u(() => O.value.some((e) => e.type === "mergeTag" || e.type === "logicMergeTag"));
|
|
166
|
-
function A() {
|
|
167
|
-
S.value = !0, p(() => {
|
|
168
|
-
a.value?.focus();
|
|
169
|
-
let e = t()?.length || 0;
|
|
170
|
-
a.value?.setSelectionRange(e, e);
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
function j() {
|
|
174
|
-
w || (S.value = !1);
|
|
175
|
-
}
|
|
176
|
-
function M(e) {
|
|
177
|
-
r(e.target.value), D.refresh();
|
|
178
|
-
}
|
|
179
|
-
function N(e) {
|
|
180
|
-
return D.handleKeydown(e) ? (e.preventDefault(), !0) : (e.key === "Escape" && j(), !1);
|
|
181
|
-
}
|
|
182
|
-
function F() {
|
|
183
|
-
D.refresh();
|
|
184
|
-
}
|
|
185
|
-
function I() {
|
|
186
|
-
D.close(), j();
|
|
187
|
-
}
|
|
188
|
-
function L() {
|
|
189
|
-
r("");
|
|
190
|
-
}
|
|
191
|
-
async function R() {
|
|
192
|
-
let e = S.value && a.value ? a.value.selectionStart ?? t().length : t().length;
|
|
193
|
-
w = !0;
|
|
194
|
-
let n;
|
|
195
|
-
try {
|
|
196
|
-
n = await h();
|
|
197
|
-
} finally {
|
|
198
|
-
w = !1;
|
|
199
|
-
}
|
|
200
|
-
if (!E && n) {
|
|
201
|
-
let i = t().slice(0, e), o = t().slice(e), s = i + n.value + o;
|
|
202
|
-
r(s), S.value = !0, p(() => {
|
|
203
|
-
if (E) return;
|
|
204
|
-
let t = e + n.value.length;
|
|
205
|
-
a.value?.focus(), a.value?.setSelectionRange(t, t);
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
async function z(e) {
|
|
210
|
-
let t = O.value, n = t[e];
|
|
211
|
-
if (n?.type !== "mergeTag") return;
|
|
212
|
-
w = !0;
|
|
213
|
-
let i;
|
|
214
|
-
try {
|
|
215
|
-
i = await h({
|
|
216
|
-
reason: "edit",
|
|
217
|
-
current: m(n.value)
|
|
218
|
-
});
|
|
219
|
-
} finally {
|
|
220
|
-
w = !1;
|
|
221
|
-
}
|
|
222
|
-
!E && i && r(t.map((t, n) => n === e ? i.value : t.value).join(""));
|
|
223
|
-
}
|
|
224
|
-
async function B() {
|
|
225
|
-
let e = a.value, n = e?.selectionStart ?? t().length, i = e?.selectionEnd ?? n;
|
|
226
|
-
w = !0;
|
|
227
|
-
let o;
|
|
228
|
-
try {
|
|
229
|
-
o = await b();
|
|
230
|
-
} finally {
|
|
231
|
-
w = !1;
|
|
232
|
-
}
|
|
233
|
-
if (E || !o) return;
|
|
234
|
-
let s = t(), c, l;
|
|
235
|
-
"before" in o ? (c = s.slice(0, n) + o.before + s.slice(n, i) + o.after + s.slice(i), l = n + o.before.length + (i - n)) : (c = s.slice(0, n) + o.value + s.slice(n), l = n + o.value.length), r(c), S.value = !0, p(() => {
|
|
236
|
-
E || (a.value?.focus(), a.value?.setSelectionRange(l, l));
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
return {
|
|
240
|
-
segments: O,
|
|
241
|
-
hasMergeTags: k,
|
|
242
|
-
canRequestMergeTag: c,
|
|
243
|
-
isRequestingMergeTag: l,
|
|
244
|
-
canInsertLogicTag: v,
|
|
245
|
-
isRequestingLogicTag: y,
|
|
246
|
-
isEditing: S,
|
|
247
|
-
startEditing: A,
|
|
248
|
-
stopEditing: j,
|
|
249
|
-
handleInput: M,
|
|
250
|
-
handleKeydown: N,
|
|
251
|
-
handleClick: F,
|
|
252
|
-
handleBlur: I,
|
|
253
|
-
clearValue: L,
|
|
254
|
-
insertMergeTag: R,
|
|
255
|
-
replaceMergeTagAt: z,
|
|
256
|
-
insertLogicTag: B,
|
|
257
|
-
autocompleteAvailable: D.available
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
//#endregion
|
|
261
|
-
//#region src/components/MergeTagSegments.vue?vue&type=script&setup=true&lang.ts
|
|
262
|
-
var G = ["aria-label"], K = [
|
|
263
|
-
"data-tooltip",
|
|
264
|
-
"aria-label",
|
|
265
|
-
"onClick"
|
|
266
|
-
], q = ["data-tooltip"], J = ["data-tooltip"], Y = {
|
|
267
|
-
key: 3,
|
|
268
|
-
class: "tpl:text-sm tpl:text-[var(--tpl-text)]"
|
|
269
|
-
}, X = ["aria-label", "title"], ee = ["aria-label", "title"], Z = /* @__PURE__ */ a({
|
|
270
|
-
__name: "MergeTagSegments",
|
|
271
|
-
props: {
|
|
272
|
-
segments: {},
|
|
273
|
-
displayClass: {},
|
|
274
|
-
pulse: { type: Boolean }
|
|
275
|
-
},
|
|
276
|
-
emits: [
|
|
277
|
-
"edit",
|
|
278
|
-
"clear",
|
|
279
|
-
"repick"
|
|
280
|
-
],
|
|
281
|
-
setup(e, { emit: n }) {
|
|
282
|
-
let i = n, { t: a, format: o } = D(), { canRepickMergeTag: u, showRawValue: f } = P();
|
|
283
|
-
function p() {
|
|
284
|
-
i("edit");
|
|
285
|
-
}
|
|
286
|
-
return (n, h) => (r(), d("div", {
|
|
287
|
-
role: "group",
|
|
288
|
-
"aria-label": s(a).mergeTag.fieldGroup,
|
|
289
|
-
class: l([e.displayClass, { "tpl-pulse-fill": e.pulse }]),
|
|
290
|
-
onClick: p
|
|
291
|
-
}, [
|
|
292
|
-
(r(!0), d(v, null, t(e.segments, (e, t) => (r(), d(v, { key: `${e.type}-${t}-${e.value}` }, [e.type === "mergeTag" && s(u)(e.value) ? (r(), d("button", {
|
|
293
|
-
key: 0,
|
|
294
|
-
type: "button",
|
|
295
|
-
class: l(["tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:gap-1 tpl:rounded tpl:border-none tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium", s(f) ? "tpl-tooltip" : ""]),
|
|
296
|
-
"data-tooltip": s(f) ? e.value : void 0,
|
|
297
|
-
"aria-label": s(o)(s(a).mergeTag.changeTag, { label: e.label }),
|
|
298
|
-
"data-testid": "merge-tag-field-chip",
|
|
299
|
-
style: {
|
|
300
|
-
"background-color": "color-mix(\n in srgb,\n var(--tpl-primary) 20%,\n transparent\n )",
|
|
301
|
-
color: "var(--tpl-primary)"
|
|
302
|
-
},
|
|
303
|
-
onClick: m((e) => i("repick", t), ["stop"])
|
|
304
|
-
}, y(e.label), 11, K)) : e.type === "mergeTag" ? (r(), d("span", {
|
|
305
|
-
key: 1,
|
|
306
|
-
class: l(["tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium", s(f) ? "tpl-tooltip" : ""]),
|
|
307
|
-
"data-tooltip": s(f) ? e.value : void 0,
|
|
308
|
-
style: {
|
|
309
|
-
"background-color": "color-mix(\n in srgb,\n var(--tpl-primary) 20%,\n transparent\n )",
|
|
310
|
-
color: "var(--tpl-primary)"
|
|
311
|
-
}
|
|
312
|
-
}, y(e.label), 11, q)) : e.type === "logicMergeTag" ? (r(), d("span", {
|
|
313
|
-
key: 2,
|
|
314
|
-
class: "tpl-tooltip tpl:inline-flex tpl:items-center tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase",
|
|
315
|
-
"data-tooltip": e.value,
|
|
316
|
-
style: {
|
|
317
|
-
"background-color": "transparent",
|
|
318
|
-
border: "1.5px solid\n color-mix(in srgb, var(--tpl-primary) 50%, transparent)",
|
|
319
|
-
color: "var(--tpl-primary)"
|
|
320
|
-
}
|
|
321
|
-
}, y(e.keyword), 9, J)) : (r(), d("span", Y, y(e.value), 1))], 64))), 128)),
|
|
322
|
-
g("button", {
|
|
323
|
-
type: "button",
|
|
324
|
-
class: "tpl:ml-auto tpl:flex tpl:size-6 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-dim)] tpl:opacity-60 tpl:transition-all tpl:hover:text-[var(--tpl-primary)] tpl:hover:opacity-100",
|
|
325
|
-
"aria-label": s(a).mergeTag.editAsText,
|
|
326
|
-
title: s(a).mergeTag.editAsText,
|
|
327
|
-
"data-testid": "merge-tag-field-edit",
|
|
328
|
-
onClick: m(p, ["stop"])
|
|
329
|
-
}, [c(s(k), {
|
|
330
|
-
size: 12,
|
|
331
|
-
"stroke-width": 2
|
|
332
|
-
})], 8, X),
|
|
333
|
-
g("button", {
|
|
334
|
-
type: "button",
|
|
335
|
-
class: "tpl:flex tpl:size-6 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-dim)] tpl:opacity-60 tpl:transition-all tpl:hover:text-[var(--tpl-danger)] tpl:hover:opacity-100",
|
|
336
|
-
"aria-label": s(a).mergeTag.remove,
|
|
337
|
-
title: s(a).mergeTag.remove,
|
|
338
|
-
"data-testid": "merge-tag-field-clear",
|
|
339
|
-
onClick: h[0] ||= m((e) => i("clear"), ["stop"])
|
|
340
|
-
}, [c(s(M), {
|
|
341
|
-
size: 12,
|
|
342
|
-
"stroke-width": 2.5
|
|
343
|
-
})], 8, ee)
|
|
344
|
-
], 10, G));
|
|
345
|
-
}
|
|
346
|
-
}), te = [
|
|
347
|
-
"aria-label",
|
|
348
|
-
"title",
|
|
349
|
-
"disabled"
|
|
350
|
-
], ne = "tpl:flex tpl:items-center tpl:justify-center tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-xs tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:duration-[120ms] tpl:hover:bg-[var(--tpl-primary-light)] tpl:hover:text-[var(--tpl-primary)] tpl:hover:border-[var(--tpl-primary)]", Q = /* @__PURE__ */ a({
|
|
351
|
-
__name: "MergeTagInsertButton",
|
|
352
|
-
props: { disabled: { type: Boolean } },
|
|
353
|
-
emits: ["insert"],
|
|
354
|
-
setup(e) {
|
|
355
|
-
let { t } = D();
|
|
356
|
-
return (n, i) => (r(), d("button", {
|
|
357
|
-
type: "button",
|
|
358
|
-
class: l([ne, "tpl:mt-1.5"]),
|
|
359
|
-
"aria-label": s(t).mergeTag.insert,
|
|
360
|
-
title: s(t).mergeTag.insert,
|
|
361
|
-
disabled: e.disabled,
|
|
362
|
-
onMousedown: i[0] ||= m(() => {}, ["prevent"]),
|
|
363
|
-
onClick: i[1] ||= (e) => n.$emit("insert")
|
|
364
|
-
}, [c(s(A), {
|
|
365
|
-
size: 12,
|
|
366
|
-
"stroke-width": 2
|
|
367
|
-
}), b(" " + y(s(t).mergeTag.insertShort), 1)], 42, te));
|
|
368
|
-
}
|
|
369
|
-
}), re = [
|
|
370
|
-
"aria-label",
|
|
371
|
-
"title",
|
|
372
|
-
"disabled"
|
|
373
|
-
], ie = "tpl:flex tpl:items-center tpl:justify-center tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-xs tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:duration-[120ms] tpl:hover:bg-[var(--tpl-primary-light)] tpl:hover:text-[var(--tpl-primary)] tpl:hover:border-[var(--tpl-primary)]", $ = /* @__PURE__ */ a({
|
|
374
|
-
__name: "LogicTagInsertButton",
|
|
375
|
-
props: { disabled: { type: Boolean } },
|
|
376
|
-
emits: ["insert"],
|
|
377
|
-
setup(e) {
|
|
378
|
-
let { t } = D();
|
|
379
|
-
return (n, i) => (r(), d("button", {
|
|
380
|
-
type: "button",
|
|
381
|
-
class: l([ie, "tpl:mt-1.5"]),
|
|
382
|
-
"aria-label": s(t).logicTag.insert,
|
|
383
|
-
title: s(t).logicTag.insert,
|
|
384
|
-
disabled: e.disabled,
|
|
385
|
-
"data-testid": "field-insert-logic-button",
|
|
386
|
-
onMousedown: i[0] ||= m(() => {}, ["prevent"]),
|
|
387
|
-
onClick: i[1] ||= (e) => n.$emit("insert")
|
|
388
|
-
}, [c(s(j), {
|
|
389
|
-
size: 12,
|
|
390
|
-
"stroke-width": 2
|
|
391
|
-
}), b(" " + y(s(t).logicTag.insertShort), 1)], 42, re));
|
|
392
|
-
}
|
|
393
|
-
}), ae = { key: 0 }, oe = {
|
|
394
|
-
key: 0,
|
|
395
|
-
class: "tpl:flex tpl:flex-wrap tpl:gap-1.5"
|
|
396
|
-
}, se = { key: 1 }, ce = [
|
|
397
|
-
"type",
|
|
398
|
-
"value",
|
|
399
|
-
"placeholder"
|
|
400
|
-
], le = {
|
|
401
|
-
key: 0,
|
|
402
|
-
class: "tpl:flex tpl:flex-wrap tpl:gap-1.5"
|
|
403
|
-
}, ue = "tpl:flex tpl:w-full tpl:min-h-10 tpl:cursor-pointer tpl:items-center tpl:flex-wrap tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:shadow-[var(--tpl-shadow-sm)] tpl:bg-[var(--tpl-bg)] tpl:border-[var(--tpl-border)] tpl:px-3.5 tpl:py-1.5 tpl:transition-all tpl:duration-[120ms] tpl:ease-[cubic-bezier(0.16,1,0.3,1)]", de = /*#__PURE__*/ N(/* @__PURE__ */ a({
|
|
404
|
-
__name: "MergeTagInput",
|
|
405
|
-
props: {
|
|
406
|
-
modelValue: {},
|
|
407
|
-
type: { default: "text" },
|
|
408
|
-
placeholder: { default: "" },
|
|
409
|
-
pulse: {
|
|
410
|
-
type: Boolean,
|
|
411
|
-
default: !1
|
|
412
|
-
}
|
|
413
|
-
},
|
|
414
|
-
emits: ["update:modelValue", "keydown"],
|
|
415
|
-
setup(e, { emit: t }) {
|
|
416
|
-
let n = e, a = t, o = i(null), { segments: u, hasMergeTags: p, canRequestMergeTag: m, isRequestingMergeTag: _, canInsertLogicTag: v, isRequestingLogicTag: y, isEditing: b, startEditing: x, handleInput: S, handleKeydown: C, handleClick: w, handleBlur: T, clearValue: E, insertMergeTag: D, insertLogicTag: O, replaceMergeTagAt: k } = W({
|
|
417
|
-
modelValue: () => n.modelValue,
|
|
418
|
-
emit: (e) => a("update:modelValue", e),
|
|
419
|
-
elementRef: o
|
|
420
|
-
});
|
|
421
|
-
function A(e) {
|
|
422
|
-
C(e) || a("keydown", e);
|
|
423
|
-
}
|
|
424
|
-
return (t, n) => s(p) && !s(b) ? (r(), d("div", ae, [c(Z, {
|
|
425
|
-
segments: s(u),
|
|
426
|
-
"display-class": ue,
|
|
427
|
-
pulse: e.pulse,
|
|
428
|
-
onEdit: s(x),
|
|
429
|
-
onClear: s(E),
|
|
430
|
-
onRepick: s(k)
|
|
431
|
-
}, null, 8, [
|
|
432
|
-
"segments",
|
|
433
|
-
"pulse",
|
|
434
|
-
"onEdit",
|
|
435
|
-
"onClear",
|
|
436
|
-
"onRepick"
|
|
437
|
-
]), s(m) || s(v) ? (r(), d("div", oe, [s(m) ? (r(), h(Q, {
|
|
438
|
-
key: 0,
|
|
439
|
-
disabled: s(_),
|
|
440
|
-
onInsert: s(D)
|
|
441
|
-
}, null, 8, ["disabled", "onInsert"])) : f("", !0), s(v) ? (r(), h($, {
|
|
442
|
-
key: 1,
|
|
443
|
-
disabled: s(y),
|
|
444
|
-
onInsert: s(O)
|
|
445
|
-
}, null, 8, ["disabled", "onInsert"])) : f("", !0)])) : f("", !0)])) : (r(), d("div", se, [g("input", {
|
|
446
|
-
ref_key: "inputRef",
|
|
447
|
-
ref: o,
|
|
448
|
-
type: e.type,
|
|
449
|
-
class: l([s(F), { "tpl-pulse-fill": e.pulse }]),
|
|
450
|
-
value: e.modelValue,
|
|
451
|
-
placeholder: e.placeholder,
|
|
452
|
-
onInput: n[0] ||= (...e) => s(S) && s(S)(...e),
|
|
453
|
-
onKeydown: A,
|
|
454
|
-
onClick: n[1] ||= (...e) => s(w) && s(w)(...e),
|
|
455
|
-
onBlur: n[2] ||= (...e) => s(T) && s(T)(...e)
|
|
456
|
-
}, null, 42, ce), s(m) || s(v) ? (r(), d("div", le, [s(m) ? (r(), h(Q, {
|
|
457
|
-
key: 0,
|
|
458
|
-
disabled: s(_),
|
|
459
|
-
onInsert: s(D)
|
|
460
|
-
}, null, 8, ["disabled", "onInsert"])) : f("", !0), s(v) ? (r(), h($, {
|
|
461
|
-
key: 1,
|
|
462
|
-
disabled: s(y),
|
|
463
|
-
onInsert: s(O)
|
|
464
|
-
}, null, 8, ["disabled", "onInsert"])) : f("", !0)])) : f("", !0)]));
|
|
465
|
-
}
|
|
466
|
-
}), [["__scopeId", "data-v-fca026e4"]]);
|
|
467
|
-
//#endregion
|
|
468
|
-
export { W as a, Z as i, $ as n, Q as r, de as t };
|
|
469
|
-
|
|
470
|
-
//# sourceMappingURL=MergeTagInput-CSIThqkz.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MergeTagInput-CSIThqkz.js","names":["$emit","$emit"],"sources":["../../../src/utils/mergeTagTrigger.ts","../../../src/utils/textFieldCaret.ts","../../../src/composables/useMergeTagAutocomplete.ts","../../../src/composables/useMergeTagField.ts","../../../src/components/MergeTagSegments.vue","../../../src/components/MergeTagSegments.vue","../../../src/components/MergeTagInsertButton.vue","../../../src/components/MergeTagInsertButton.vue","../../../src/components/LogicTagInsertButton.vue","../../../src/components/LogicTagInsertButton.vue","../../../src/components/MergeTagInput.vue","../../../src/components/MergeTagInput.vue"],"sourcesContent":["/**\n * Result of a merge-tag trigger scan — the caret sits inside an open tag.\n */\nexport interface OpenMergeTagTrigger {\n /** Index in the field value where the trigger opener starts. */\n triggerStart: number;\n /** Caret index the scan ran at (also the end of `query`). */\n caret: number;\n /** Text typed between the opener and the caret — the autocomplete filter. */\n query: string;\n}\n\n/**\n * Detects whether the caret sits inside an *open* merge-tag trigger: the user\n * has typed the syntax opener (e.g. `{{`) and is mid-typing the tag name with\n * no closing delimiter yet. Returns the opener position + query so the caller\n * can drive the autocomplete popup, or `null` when the caret is not inside an\n * open trigger.\n *\n * Mirrors `@tiptap/suggestion`'s behavior with `allowSpaces: false`: the run\n * between the opener and the caret ends at the first whitespace, and a closing\n * delimiter inside that run means the tag is already complete (`{{first_name}}`)\n * so the popup must not reappear over it.\n */\nexport function findOpenMergeTagTrigger(\n value: string,\n caret: number,\n triggerChar: string,\n closingChar: string | null,\n): OpenMergeTagTrigger | null {\n if (!triggerChar) return null;\n\n const before = value.slice(0, caret);\n const triggerStart = before.lastIndexOf(triggerChar);\n if (triggerStart === -1) return null;\n\n const query = before.slice(triggerStart + triggerChar.length);\n\n // Whitespace ends the query (allowSpaces: false parity).\n if (/\\s/.test(query)) return null;\n\n // A closing delimiter between the opener and the caret means the tag is\n // already complete — don't reopen the popup over a finished tag.\n if (closingChar && query.includes(closingChar)) return null;\n\n return { triggerStart, caret, query };\n}\n","/**\n * Viewport-space caret geometry for `<input>` / `<textarea>` elements.\n *\n * Native text controls expose no caret coordinates (unlike ProseMirror, which\n * hands the merge-tag popup a `clientRect()`). The standard workaround is a\n * hidden \"mirror\" element that clones the field's text metrics; the caret's\n * pixel position is read from a marker span placed at the caret offset. This\n * lets the input/textarea autocomplete anchor its popup at the caret exactly\n * like the rich-text editor does.\n *\n * Adapted from component/textarea-caret-position (MIT). Returns a viewport\n * `DOMRect` (same coordinate space as `Range.getBoundingClientRect`) so the\n * shared merge-tag popup controller positions it identically to the TipTap path.\n */\n\n// Computed-style properties copied onto the mirror so its text wraps and\n// measures exactly like the source field.\nconst MIRRORED_PROPERTIES = [\n \"boxSizing\",\n \"width\",\n \"borderTopWidth\",\n \"borderRightWidth\",\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderStyle\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"fontStyle\",\n \"fontVariant\",\n \"fontWeight\",\n \"fontStretch\",\n \"fontSize\",\n \"lineHeight\",\n \"fontFamily\",\n \"textAlign\",\n \"textTransform\",\n \"textIndent\",\n \"letterSpacing\",\n \"wordSpacing\",\n \"tabSize\",\n \"whiteSpace\",\n \"wordWrap\",\n \"wordBreak\",\n] as const;\n\nfunction toRect(left: number, top: number, bottom: number): DOMRect {\n const height = bottom - top;\n return {\n left,\n top,\n bottom,\n right: left,\n width: 0,\n height,\n x: left,\n y: top,\n toJSON: () => ({}),\n } as DOMRect;\n}\n\n/**\n * Returns the viewport rect of the caret at `position` in a text field, or\n * `null` when the field isn't laid out (detached / no view). The rect is a\n * zero-width vertical strip at the caret, one line tall — matching the shape\n * `Range.getBoundingClientRect()` produces for a collapsed selection.\n */\nexport function getCaretRect(\n el: HTMLInputElement | HTMLTextAreaElement,\n position: number,\n): DOMRect | null {\n const doc = el.ownerDocument;\n const win = doc.defaultView;\n if (!win) return null;\n\n const isInput = el.tagName === \"INPUT\";\n const style = win.getComputedStyle(el);\n\n const mirror = doc.createElement(\"div\");\n mirror.setAttribute(\"aria-hidden\", \"true\");\n const s = mirror.style;\n s.position = \"absolute\";\n s.visibility = \"hidden\";\n s.top = \"0\";\n s.left = \"0\";\n s.overflow = \"hidden\";\n s.whiteSpace = isInput ? \"pre\" : \"pre-wrap\";\n s.wordWrap = isInput ? \"normal\" : \"break-word\";\n const target = s as unknown as Record<string, string>;\n const source = style as unknown as Record<string, string>;\n for (const prop of MIRRORED_PROPERTIES) {\n target[prop] = source[prop];\n }\n // A single-line input never wraps; let the mirror grow with the text so the\n // marker's horizontal offset tracks the caret.\n if (isInput) {\n s.width = \"auto\";\n s.whiteSpace = \"pre\";\n }\n\n const value = el.value;\n let head = value.slice(0, position);\n if (isInput) {\n // <input> collapses whitespace runs to a single rendered space; replace\n // with non-breaking spaces so the mirror's width matches the field.\n head = head.replace(/\\s/g, \" \");\n }\n mirror.textContent = head;\n\n const marker = doc.createElement(\"span\");\n // Remaining text (or a placeholder) gives the marker the caret line's height.\n marker.textContent = value.slice(position) || \".\";\n mirror.appendChild(marker);\n\n doc.body.appendChild(mirror);\n const markerTop = marker.offsetTop;\n const markerLeft = marker.offsetLeft;\n doc.body.removeChild(mirror);\n\n const elRect = el.getBoundingClientRect();\n const borderTop = parseFloat(style.borderTopWidth) || 0;\n const borderLeft = parseFloat(style.borderLeftWidth) || 0;\n const lineHeight =\n parseFloat(style.lineHeight) || parseFloat(style.fontSize) || 0;\n\n const left = elRect.left + markerLeft + borderLeft - el.scrollLeft;\n\n // A single-line input vertically centers its text, which the block-flow\n // mirror can't replicate — anchor vertically to the field itself so the\n // popup sits directly under the input. Textareas use the measured caret line.\n if (isInput) {\n return toRect(left, elRect.top, elRect.bottom);\n }\n\n const top = elRect.top + markerTop + borderTop - el.scrollTop;\n return toRect(left, top, top + lineHeight);\n}\n","import {\n getSyntaxClosingChar,\n getSyntaxTriggerChar,\n type MergeTag,\n type SyntaxPreset,\n} from \"@templatical/types\";\nimport {\n computed,\n getCurrentScope,\n inject,\n isRef,\n nextTick,\n onScopeDispose,\n type ComputedRef,\n type Ref,\n type ShallowRef,\n} from \"vue\";\nimport type { Translations } from \"../i18n\";\nimport { TRANSLATIONS_KEY } from \"../keys\";\nimport {\n createMergeTagPopup,\n filterMergeTags,\n} from \"../extensions/MergeTagSuggestion\";\nimport {\n findOpenMergeTagTrigger,\n type OpenMergeTagTrigger,\n} from \"../utils/mergeTagTrigger\";\nimport { getCaretRect } from \"../utils/textFieldCaret\";\nimport { usePopoverRoot } from \"./usePopoverRoot\";\n\nexport interface UseMergeTagAutocompleteOptions {\n /** The `<input>` / `<textarea>` the popup anchors to. */\n elementRef: Ref<HTMLInputElement | HTMLTextAreaElement | null>;\n /** Reads the current field value. */\n modelValue: () => string;\n /** Emits a new field value. */\n emit: (value: string) => void;\n /** Available merge tags (the autocomplete filter source). */\n mergeTags: ShallowRef<MergeTag[]>;\n /** Resolved merge-tag syntax. */\n syntax: SyntaxPreset;\n /** Consumer's `mergeTags.autocomplete` flag. */\n enabled: boolean;\n /**\n * Invoked right before a picked tag is emitted, so the field can keep edit\n * mode and not flip to the chip display while the caret is still active.\n */\n onInsert?: () => void;\n}\n\nexport interface UseMergeTagAutocompleteReturn {\n /**\n * Whether autocomplete can ever fire. Mirrors the rich-text gate exactly:\n * enabled + a built-in trigger syntax + at least one tag to filter.\n */\n available: ComputedRef<boolean>;\n /** Recompute the popup after the value or caret changed. */\n refresh: () => void;\n /**\n * Field `keydown` handler. Returns `true` when the popup consumed the key\n * (the caller must then `preventDefault`); `false` to let the field handle it.\n */\n handleKeydown: (event: KeyboardEvent) => boolean;\n /** Close the popup (e.g. on blur). Idempotent. */\n close: () => void;\n /** Whether the popup is currently open. */\n isOpen: () => boolean;\n}\n\n// Horizontal caret moves take the caret out of the query run — dismiss the\n// popup (like navigating away in the rich-text editor) and let the caret move.\nconst CARET_MOVE_KEYS = new Set([\"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"]);\n\n/**\n * Type-ahead merge-tag autocomplete for a native `<input>` / `<textarea>`.\n *\n * Drives the SAME popup controller as the rich-text (`@tiptap/suggestion`)\n * path — see `createMergeTagPopup` — so the popup's rendering, positioning,\n * keyboard behavior, and ARIA are identical across both surfaces. The only\n * field-specific work is here: detecting the open trigger in the raw string\n * (`findOpenMergeTagTrigger`), measuring the caret rect without ProseMirror\n * (`getCaretRect`), and replacing the typed fragment with the picked tag.\n */\nexport function useMergeTagAutocomplete(\n options: UseMergeTagAutocompleteOptions,\n): UseMergeTagAutocompleteReturn {\n const { elementRef, modelValue, emit, mergeTags, syntax, enabled, onInsert } =\n options;\n\n const triggerChar = getSyntaxTriggerChar(syntax);\n const closingChar = getSyntaxClosingChar(syntax);\n // Reactive: `setMergeTags` can take the list from empty to populated, and a\n // boolean captured here would leave type-ahead dead for the rest of the\n // field's life.\n const available = computed(\n () => enabled && triggerChar !== null && mergeTags.value.length > 0,\n );\n\n // Resolve the empty-state label the same way the rich-text path does —\n // inject with a null default so headless callers (no translations provider)\n // don't throw, falling back to the English string.\n const injectedTranslations = inject(TRANSLATIONS_KEY, null) as\n Translations | Ref<Translations> | null;\n const resolvedTranslations = isRef(injectedTranslations)\n ? injectedTranslations.value\n : injectedTranslations;\n const emptyText =\n resolvedTranslations?.mergeTag?.suggestionEmpty ?? \"No matching merge tags\";\n\n const popoverRoot = usePopoverRoot();\n const popup = createMergeTagPopup(emptyText, popoverRoot);\n\n let disposed = false;\n if (getCurrentScope()) {\n onScopeDispose(() => {\n disposed = true;\n popup.close();\n });\n }\n\n function currentMatch(el: HTMLInputElement | HTMLTextAreaElement) {\n const value = el.value ?? \"\";\n const caret = el.selectionStart ?? value.length;\n return findOpenMergeTagTrigger(\n value,\n caret,\n triggerChar as string,\n closingChar,\n );\n }\n\n function applySelection(\n el: HTMLInputElement | HTMLTextAreaElement,\n match: OpenMergeTagTrigger,\n tag: MergeTag,\n ): void {\n const value = el.value ?? modelValue();\n // Absorb a matching closer sitting immediately after the caret so\n // `{{fir}}` → pick → `{{first_name}}`, never `{{first_name}}}}`.\n const afterCaret = value.slice(match.caret);\n const trailing =\n closingChar && afterCaret.startsWith(closingChar)\n ? closingChar.length\n : 0;\n const before = value.slice(0, match.triggerStart);\n const after = value.slice(match.caret + trailing);\n const newValue = before + tag.value + after;\n const newPos = before.length + tag.value.length;\n\n // Keep the field in edit mode BEFORE emitting: once the value gains a tag,\n // `hasMergeTags` flips true, and without this the field would swap to the\n // chip display and unmount the input mid-insert.\n onInsert?.();\n emit(newValue);\n popup.close();\n\n nextTick(() => {\n if (disposed) return;\n const node = elementRef.value;\n node?.focus();\n node?.setSelectionRange(newPos, newPos);\n });\n }\n\n function refresh(): void {\n if (!available.value || disposed) return;\n const el = elementRef.value;\n if (!el) {\n popup.close();\n return;\n }\n const match = currentMatch(el);\n if (!match) {\n popup.close();\n return;\n }\n\n const items = filterMergeTags(mergeTags.value, match.query);\n const getRect = () => getCaretRect(el, match.triggerStart);\n const onCommand = (tag: MergeTag) => applySelection(el, match, tag);\n\n if (popup.isOpen()) {\n popup.update({ items, getRect, onCommand });\n } else {\n popup.open({ items, getRect, anchorEl: el, onCommand });\n }\n }\n\n function handleKeydown(event: KeyboardEvent): boolean {\n if (!popup.isOpen()) return false;\n if (event.key === \"Escape\") {\n popup.close();\n return true;\n }\n if (CARET_MOVE_KEYS.has(event.key)) {\n popup.close();\n return false;\n }\n return popup.handleKeyDown(event);\n }\n\n return {\n available,\n refresh,\n handleKeydown,\n close: () => popup.close(),\n isOpen: () => popup.isOpen(),\n };\n}\n","import {\n getLogicMergeTagKeyword,\n isLogicMergeTagValue,\n} from \"@templatical/types\";\nimport {\n computed,\n getCurrentScope,\n nextTick,\n onScopeDispose,\n ref,\n type ComputedRef,\n type Ref,\n} from \"vue\";\nimport { useMergeTag } from \"./useMergeTag\";\nimport { useLogicTag } from \"./useLogicTag\";\nimport { useMergeTagAutocomplete } from \"./useMergeTagAutocomplete\";\n\nexport type MergeTagSegment =\n | { type: \"text\"; value: string }\n | { type: \"mergeTag\"; value: string; label: string }\n | { type: \"logicMergeTag\"; value: string; keyword: string };\n\nexport interface UseMergeTagFieldOptions {\n modelValue: () => string;\n emit: (value: string) => void;\n elementRef: Ref<HTMLInputElement | HTMLTextAreaElement | null>;\n}\n\nexport interface UseMergeTagFieldReturn {\n segments: ComputedRef<MergeTagSegment[]>;\n hasMergeTags: ComputedRef<boolean>;\n canRequestMergeTag: ComputedRef<boolean>;\n isRequestingMergeTag: Ref<boolean>;\n canInsertLogicTag: boolean;\n isRequestingLogicTag: Ref<boolean>;\n isEditing: Ref<boolean>;\n startEditing: () => void;\n stopEditing: () => void;\n handleInput: (event: Event) => void;\n /**\n * Returns whether the autocomplete popup consumed the event. A host with\n * keys of its own (the link dialog submits on Enter) acts only on `false`.\n */\n handleKeydown: (event: KeyboardEvent) => boolean;\n handleClick: () => void;\n handleBlur: () => void;\n clearValue: () => void;\n insertMergeTag: () => Promise<void>;\n /**\n * Swap the merge tag at `index` in {@link segments} for another one, chosen\n * through the same chooser insertion uses. No-op when the index isn't a\n * merge-tag segment, or when the user cancels.\n */\n replaceMergeTagAt: (index: number) => Promise<void>;\n insertLogicTag: () => Promise<void>;\n /** Whether type-ahead autocomplete is active for this field. */\n autocompleteAvailable: ComputedRef<boolean>;\n}\n\nexport function useMergeTagField(\n options: UseMergeTagFieldOptions,\n): UseMergeTagFieldReturn {\n const { modelValue, emit, elementRef } = options;\n\n const {\n mergeTags,\n canRequestMergeTag,\n isRequesting: isRequestingMergeTag,\n isMergeTagValue,\n getMergeTagDisplayLabel,\n findMergeTag,\n requestMergeTag,\n syntax,\n autocomplete,\n } = useMergeTag();\n\n const {\n canInsertLogicTag,\n isRequesting: isRequestingLogicTag,\n requestLogicTag,\n } = useLogicTag();\n\n const isEditing = ref(false);\n let insertingMergeTag = false;\n let disposed = false;\n if (getCurrentScope()) {\n onScopeDispose(() => {\n disposed = true;\n });\n }\n\n // Type-ahead autocomplete for the raw <input>/<textarea>, sharing the exact\n // popup used by the rich-text editor. `onInsert` keeps the field in edit mode\n // so the freshly inserted tag stays visible instead of flipping to chips.\n const typeahead = useMergeTagAutocomplete({\n elementRef,\n modelValue,\n emit,\n mergeTags,\n syntax,\n enabled: autocomplete,\n onInsert: () => {\n isEditing.value = true;\n },\n });\n\n const segments = computed((): MergeTagSegment[] => {\n const val = modelValue();\n if (!val) return [];\n\n const result: MergeTagSegment[] = [];\n const combinedSource = `(${syntax.value.source}|${syntax.logic.source})`;\n const regex = new RegExp(combinedSource, \"g\");\n let lastIndex = 0;\n let match;\n\n while ((match = regex.exec(val)) !== null) {\n if (match.index > lastIndex) {\n result.push({\n type: \"text\",\n value: val.slice(lastIndex, match.index),\n });\n }\n\n const matched = match[0];\n if (isMergeTagValue(matched)) {\n result.push({\n type: \"mergeTag\",\n value: matched,\n // A field value is a plain string, so there is no stored label to\n // fall back to — an undeclared token resolves to the placeholder\n // when the consumer hid raw tokens.\n label: getMergeTagDisplayLabel(matched),\n });\n } else if (isLogicMergeTagValue(matched, syntax)) {\n result.push({\n type: \"logicMergeTag\",\n value: matched,\n keyword: getLogicMergeTagKeyword(matched, syntax),\n });\n } else {\n result.push({ type: \"text\", value: matched });\n }\n\n lastIndex = match.index + matched.length;\n }\n\n if (lastIndex < val.length) {\n result.push({ type: \"text\", value: val.slice(lastIndex) });\n }\n\n return result;\n });\n\n const hasMergeTags = computed(() =>\n segments.value.some(\n (s) => s.type === \"mergeTag\" || s.type === \"logicMergeTag\",\n ),\n );\n\n function startEditing(): void {\n isEditing.value = true;\n nextTick(() => {\n elementRef.value?.focus();\n const len = modelValue()?.length || 0;\n elementRef.value?.setSelectionRange(len, len);\n });\n }\n\n function stopEditing(): void {\n if (insertingMergeTag) return;\n isEditing.value = false;\n }\n\n function handleInput(event: Event): void {\n emit((event.target as HTMLInputElement | HTMLTextAreaElement).value);\n typeahead.refresh();\n }\n\n /**\n * Field keydown: let the autocomplete popup consume navigation/selection\n * keys first (Arrow/Enter/Tab/Escape). If it doesn't, Escape falls through\n * to leaving edit mode.\n *\n * Escape is reported as NOT consumed even though it acts here: a host\n * dialog should close on the same press rather than swallow the first one.\n */\n function handleKeydown(event: KeyboardEvent): boolean {\n if (typeahead.handleKeydown(event)) {\n event.preventDefault();\n return true;\n }\n if (event.key === \"Escape\") {\n stopEditing();\n }\n return false;\n }\n\n /** A click may move the caret into or out of a trigger — re-evaluate. */\n function handleClick(): void {\n typeahead.refresh();\n }\n\n /** Blur closes the popup, then leaves edit mode. */\n function handleBlur(): void {\n typeahead.close();\n stopEditing();\n }\n\n function clearValue(): void {\n emit(\"\");\n }\n\n async function insertMergeTag(): Promise<void> {\n const cursorPos =\n isEditing.value && elementRef.value\n ? (elementRef.value.selectionStart ?? modelValue().length)\n : modelValue().length;\n\n insertingMergeTag = true;\n let mergeTag: Awaited<ReturnType<typeof requestMergeTag>>;\n try {\n mergeTag = await requestMergeTag();\n } finally {\n insertingMergeTag = false;\n }\n\n if (disposed) return;\n\n if (mergeTag) {\n const before = modelValue().slice(0, cursorPos);\n const after = modelValue().slice(cursorPos);\n const newValue = before + mergeTag.value + after;\n emit(newValue);\n\n isEditing.value = true;\n nextTick(() => {\n if (disposed) return;\n const newPos = cursorPos + mergeTag.value.length;\n elementRef.value?.focus();\n elementRef.value?.setSelectionRange(newPos, newPos);\n });\n }\n }\n\n async function replaceMergeTagAt(index: number): Promise<void> {\n // Snapshot before the await: `segments` is a computed over modelValue(),\n // and a collaborator edit or a parallel write can change it while the\n // chooser is open. Rebuilding from the snapshot keeps the swap addressed\n // to the tag the user actually clicked.\n const snapshot = segments.value;\n const target = snapshot[index];\n if (target?.type !== \"mergeTag\") return;\n\n // Same flag insertMergeTag uses: the chooser mounts outside the field, so\n // without it the blur handler leaves edit mode mid-pick.\n insertingMergeTag = true;\n let replacement: Awaited<ReturnType<typeof requestMergeTag>>;\n try {\n replacement = await requestMergeTag({\n reason: \"edit\",\n current: findMergeTag(target.value),\n });\n } finally {\n insertingMergeTag = false;\n }\n\n if (disposed || !replacement) return;\n\n emit(\n snapshot\n .map((segment, i) => (i === index ? replacement.value : segment.value))\n .join(\"\"),\n );\n }\n\n async function insertLogicTag(): Promise<void> {\n // Read the selection straight from the element (kept focused via the\n // button's mousedown.prevent). Null only in display mode → append at end.\n const el = elementRef.value;\n const start = el?.selectionStart ?? modelValue().length;\n const end = el?.selectionEnd ?? start;\n\n insertingMergeTag = true;\n let item: Awaited<ReturnType<typeof requestLogicTag>>;\n try {\n item = await requestLogicTag();\n } finally {\n insertingMergeTag = false;\n }\n\n if (disposed || !item) return;\n\n const val = modelValue();\n let newValue: string;\n let newPos: number;\n if (\"before\" in item) {\n // Pair: wrap the selection with before/after. With no selection\n // (start === end) the caret lands between them so the user types the\n // wrapped content — mirrors the rich-text behavior.\n newValue =\n val.slice(0, start) +\n item.before +\n val.slice(start, end) +\n item.after +\n val.slice(end);\n newPos = start + item.before.length + (end - start);\n } else {\n // Tag: insert at the cursor.\n newValue = val.slice(0, start) + item.value + val.slice(start);\n newPos = start + item.value.length;\n }\n emit(newValue);\n\n isEditing.value = true;\n nextTick(() => {\n if (disposed) return;\n elementRef.value?.focus();\n elementRef.value?.setSelectionRange(newPos, newPos);\n });\n }\n\n return {\n segments,\n hasMergeTags,\n canRequestMergeTag,\n isRequestingMergeTag,\n canInsertLogicTag,\n isRequestingLogicTag,\n isEditing,\n startEditing,\n stopEditing,\n handleInput,\n handleKeydown,\n handleClick,\n handleBlur,\n clearValue,\n insertMergeTag,\n replaceMergeTagAt,\n insertLogicTag,\n autocompleteAvailable: typeahead.available,\n };\n}\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport type { MergeTagSegment } from \"../composables/useMergeTagField\";\nimport { Pencil, X } from \"@lucide/vue\";\n\ndefineProps<{\n segments: MergeTagSegment[];\n displayClass: string;\n pulse?: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"edit\"): void;\n (e: \"clear\"): void;\n /** Index into `segments` of the merge tag the user wants to swap. */\n (e: \"repick\", index: number): void;\n}>();\n\nconst { t, format } = useI18n();\nconst { canRepickMergeTag, showRawValue } = useMergeTag();\n\nfunction onEdit(): void {\n emit(\"edit\");\n}\n</script>\n\n<template>\n <!--\n role=\"group\", never role=\"button\" — the field holds its own controls (a\n button per merge tag, Edit, Clear), and a button may not contain focusable\n descendants: it announces as a control inside a control and the tab order\n reads as if you stepped into the element you just landed on. The click\n handler here is a redundant mouse convenience over the Edit button, which\n is the real, keyboard-reachable control.\n -->\n <div\n role=\"group\"\n :aria-label=\"t.mergeTag.fieldGroup\"\n :class=\"[displayClass, { 'tpl-pulse-fill': pulse }]\"\n @click=\"onEdit\"\n >\n <template\n v-for=\"(seg, i) in segments\"\n :key=\"`${seg.type}-${i}-${seg.value}`\"\n >\n <button\n v-if=\"seg.type === 'mergeTag' && canRepickMergeTag(seg.value)\"\n type=\"button\"\n :class=\"[\n 'tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:gap-1 tpl:rounded tpl:border-none tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium',\n showRawValue ? 'tpl-tooltip' : '',\n ]\"\n :data-tooltip=\"showRawValue ? seg.value : undefined\"\n :aria-label=\"format(t.mergeTag.changeTag, { label: seg.label })\"\n data-testid=\"merge-tag-field-chip\"\n style=\"\n background-color: color-mix(\n in srgb,\n var(--tpl-primary) 20%,\n transparent\n );\n color: var(--tpl-primary);\n \"\n @click.stop=\"emit('repick', i)\"\n >\n {{ seg.label }}\n </button>\n <!--\n No chooser can resolve this token, so it stays a plain span and the\n click falls through to the wrapper, which opens the raw editor — the\n only way left to repair it. A disabled button would swallow the click\n instead. Keyboard users reach the same editor through the Edit button.\n -->\n <span\n v-else-if=\"seg.type === 'mergeTag'\"\n :class=\"[\n 'tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium',\n showRawValue ? 'tpl-tooltip' : '',\n ]\"\n :data-tooltip=\"showRawValue ? seg.value : undefined\"\n style=\"\n background-color: color-mix(\n in srgb,\n var(--tpl-primary) 20%,\n transparent\n );\n color: var(--tpl-primary);\n \"\n >\n {{ seg.label }}\n </span>\n <span\n v-else-if=\"seg.type === 'logicMergeTag'\"\n class=\"tpl-tooltip tpl:inline-flex tpl:items-center tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase\"\n :data-tooltip=\"seg.value\"\n style=\"\n background-color: transparent;\n border: 1.5px solid\n color-mix(in srgb, var(--tpl-primary) 50%, transparent);\n color: var(--tpl-primary);\n \"\n >\n {{ seg.keyword }}\n </span>\n <span v-else class=\"tpl:text-sm tpl:text-[var(--tpl-text)]\">{{\n seg.value\n }}</span>\n </template>\n <button\n type=\"button\"\n class=\"tpl:ml-auto tpl:flex tpl:size-6 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-dim)] tpl:opacity-60 tpl:transition-all tpl:hover:text-[var(--tpl-primary)] tpl:hover:opacity-100\"\n :aria-label=\"t.mergeTag.editAsText\"\n :title=\"t.mergeTag.editAsText\"\n data-testid=\"merge-tag-field-edit\"\n @click.stop=\"onEdit\"\n >\n <Pencil :size=\"12\" :stroke-width=\"2\" />\n </button>\n <button\n type=\"button\"\n class=\"tpl:flex tpl:size-6 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-dim)] tpl:opacity-60 tpl:transition-all tpl:hover:text-[var(--tpl-danger)] tpl:hover:opacity-100\"\n :aria-label=\"t.mergeTag.remove\"\n :title=\"t.mergeTag.remove\"\n data-testid=\"merge-tag-field-clear\"\n @click.stop=\"emit('clear')\"\n >\n <X :size=\"12\" :stroke-width=\"2.5\" />\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { useMergeTag } from \"../composables/useMergeTag\";\nimport type { MergeTagSegment } from \"../composables/useMergeTagField\";\nimport { Pencil, X } from \"@lucide/vue\";\n\ndefineProps<{\n segments: MergeTagSegment[];\n displayClass: string;\n pulse?: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"edit\"): void;\n (e: \"clear\"): void;\n /** Index into `segments` of the merge tag the user wants to swap. */\n (e: \"repick\", index: number): void;\n}>();\n\nconst { t, format } = useI18n();\nconst { canRepickMergeTag, showRawValue } = useMergeTag();\n\nfunction onEdit(): void {\n emit(\"edit\");\n}\n</script>\n\n<template>\n <!--\n role=\"group\", never role=\"button\" — the field holds its own controls (a\n button per merge tag, Edit, Clear), and a button may not contain focusable\n descendants: it announces as a control inside a control and the tab order\n reads as if you stepped into the element you just landed on. The click\n handler here is a redundant mouse convenience over the Edit button, which\n is the real, keyboard-reachable control.\n -->\n <div\n role=\"group\"\n :aria-label=\"t.mergeTag.fieldGroup\"\n :class=\"[displayClass, { 'tpl-pulse-fill': pulse }]\"\n @click=\"onEdit\"\n >\n <template\n v-for=\"(seg, i) in segments\"\n :key=\"`${seg.type}-${i}-${seg.value}`\"\n >\n <button\n v-if=\"seg.type === 'mergeTag' && canRepickMergeTag(seg.value)\"\n type=\"button\"\n :class=\"[\n 'tpl:inline-flex tpl:cursor-pointer tpl:items-center tpl:gap-1 tpl:rounded tpl:border-none tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium',\n showRawValue ? 'tpl-tooltip' : '',\n ]\"\n :data-tooltip=\"showRawValue ? seg.value : undefined\"\n :aria-label=\"format(t.mergeTag.changeTag, { label: seg.label })\"\n data-testid=\"merge-tag-field-chip\"\n style=\"\n background-color: color-mix(\n in srgb,\n var(--tpl-primary) 20%,\n transparent\n );\n color: var(--tpl-primary);\n \"\n @click.stop=\"emit('repick', i)\"\n >\n {{ seg.label }}\n </button>\n <!--\n No chooser can resolve this token, so it stays a plain span and the\n click falls through to the wrapper, which opens the raw editor — the\n only way left to repair it. A disabled button would swallow the click\n instead. Keyboard users reach the same editor through the Edit button.\n -->\n <span\n v-else-if=\"seg.type === 'mergeTag'\"\n :class=\"[\n 'tpl:inline-flex tpl:items-center tpl:gap-1 tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.9em] tpl:font-medium',\n showRawValue ? 'tpl-tooltip' : '',\n ]\"\n :data-tooltip=\"showRawValue ? seg.value : undefined\"\n style=\"\n background-color: color-mix(\n in srgb,\n var(--tpl-primary) 20%,\n transparent\n );\n color: var(--tpl-primary);\n \"\n >\n {{ seg.label }}\n </span>\n <span\n v-else-if=\"seg.type === 'logicMergeTag'\"\n class=\"tpl-tooltip tpl:inline-flex tpl:items-center tpl:rounded tpl:px-1.5 tpl:py-0.5 tpl:text-[0.8em] tpl:font-bold tpl:tracking-wide tpl:uppercase\"\n :data-tooltip=\"seg.value\"\n style=\"\n background-color: transparent;\n border: 1.5px solid\n color-mix(in srgb, var(--tpl-primary) 50%, transparent);\n color: var(--tpl-primary);\n \"\n >\n {{ seg.keyword }}\n </span>\n <span v-else class=\"tpl:text-sm tpl:text-[var(--tpl-text)]\">{{\n seg.value\n }}</span>\n </template>\n <button\n type=\"button\"\n class=\"tpl:ml-auto tpl:flex tpl:size-6 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-dim)] tpl:opacity-60 tpl:transition-all tpl:hover:text-[var(--tpl-primary)] tpl:hover:opacity-100\"\n :aria-label=\"t.mergeTag.editAsText\"\n :title=\"t.mergeTag.editAsText\"\n data-testid=\"merge-tag-field-edit\"\n @click.stop=\"onEdit\"\n >\n <Pencil :size=\"12\" :stroke-width=\"2\" />\n </button>\n <button\n type=\"button\"\n class=\"tpl:flex tpl:size-6 tpl:shrink-0 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border-none tpl:bg-transparent tpl:p-0 tpl:text-[var(--tpl-text-dim)] tpl:opacity-60 tpl:transition-all tpl:hover:text-[var(--tpl-danger)] tpl:hover:opacity-100\"\n :aria-label=\"t.mergeTag.remove\"\n :title=\"t.mergeTag.remove\"\n data-testid=\"merge-tag-field-clear\"\n @click.stop=\"emit('clear')\"\n >\n <X :size=\"12\" :stroke-width=\"2.5\" />\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { ScanLine } from \"@lucide/vue\";\n\ndefineProps<{\n disabled?: boolean;\n}>();\n\ndefineEmits<{\n (e: \"insert\"): void;\n}>();\n\nconst { t } = useI18n();\n\nconst mergeTagBtnClass =\n \"tpl:flex tpl:items-center tpl:justify-center tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-xs tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:duration-[120ms] tpl:hover:bg-[var(--tpl-primary-light)] tpl:hover:text-[var(--tpl-primary)] tpl:hover:border-[var(--tpl-primary)]\";\n</script>\n\n<template>\n <button\n type=\"button\"\n :class=\"[mergeTagBtnClass, 'tpl:mt-1.5']\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n :disabled=\"disabled\"\n @mousedown.prevent\n @click=\"$emit('insert')\"\n >\n <ScanLine :size=\"12\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { ScanLine } from \"@lucide/vue\";\n\ndefineProps<{\n disabled?: boolean;\n}>();\n\ndefineEmits<{\n (e: \"insert\"): void;\n}>();\n\nconst { t } = useI18n();\n\nconst mergeTagBtnClass =\n \"tpl:flex tpl:items-center tpl:justify-center tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-xs tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:duration-[120ms] tpl:hover:bg-[var(--tpl-primary-light)] tpl:hover:text-[var(--tpl-primary)] tpl:hover:border-[var(--tpl-primary)]\";\n</script>\n\n<template>\n <button\n type=\"button\"\n :class=\"[mergeTagBtnClass, 'tpl:mt-1.5']\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n :disabled=\"disabled\"\n @mousedown.prevent\n @click=\"$emit('insert')\"\n >\n <ScanLine :size=\"12\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { Braces } from \"@lucide/vue\";\n\ndefineProps<{\n disabled?: boolean;\n}>();\n\ndefineEmits<{\n (e: \"insert\"): void;\n}>();\n\nconst { t } = useI18n();\n\nconst logicBtnClass =\n \"tpl:flex tpl:items-center tpl:justify-center tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-xs tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:duration-[120ms] tpl:hover:bg-[var(--tpl-primary-light)] tpl:hover:text-[var(--tpl-primary)] tpl:hover:border-[var(--tpl-primary)]\";\n</script>\n\n<template>\n <button\n type=\"button\"\n :class=\"[logicBtnClass, 'tpl:mt-1.5']\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n :disabled=\"disabled\"\n data-testid=\"field-insert-logic-button\"\n @mousedown.prevent\n @click=\"$emit('insert')\"\n >\n <Braces :size=\"12\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { useI18n } from \"../composables/useI18n\";\nimport { Braces } from \"@lucide/vue\";\n\ndefineProps<{\n disabled?: boolean;\n}>();\n\ndefineEmits<{\n (e: \"insert\"): void;\n}>();\n\nconst { t } = useI18n();\n\nconst logicBtnClass =\n \"tpl:flex tpl:items-center tpl:justify-center tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-hover)] tpl:px-2 tpl:py-1 tpl:text-xs tpl:text-[var(--tpl-text-muted)] tpl:transition-all tpl:duration-[120ms] tpl:hover:bg-[var(--tpl-primary-light)] tpl:hover:text-[var(--tpl-primary)] tpl:hover:border-[var(--tpl-primary)]\";\n</script>\n\n<template>\n <button\n type=\"button\"\n :class=\"[logicBtnClass, 'tpl:mt-1.5']\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n :disabled=\"disabled\"\n data-testid=\"field-insert-logic-button\"\n @mousedown.prevent\n @click=\"$emit('insert')\"\n >\n <Braces :size=\"12\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { useMergeTagField } from \"../composables/useMergeTagField\";\nimport { inputClass } from \"../constants/styleConstants\";\nimport MergeTagSegments from \"./MergeTagSegments.vue\";\nimport MergeTagInsertButton from \"./MergeTagInsertButton.vue\";\nimport LogicTagInsertButton from \"./LogicTagInsertButton.vue\";\nimport { ref } from \"vue\";\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string;\n type?: \"text\" | \"url\";\n placeholder?: string;\n pulse?: boolean;\n }>(),\n {\n type: \"text\",\n placeholder: \"\",\n pulse: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: string): void;\n /**\n * Keydown the autocomplete popup declined. Declared (rather than left to\n * attribute fallthrough) so a host binding `@keydown` never sees the key\n * that just picked a tag — the link dialog would submit on it.\n */\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nconst {\n segments,\n hasMergeTags,\n canRequestMergeTag,\n isRequestingMergeTag,\n canInsertLogicTag,\n isRequestingLogicTag,\n isEditing,\n startEditing,\n handleInput,\n handleKeydown: handleFieldKeydown,\n handleClick,\n handleBlur,\n clearValue,\n insertMergeTag,\n insertLogicTag,\n replaceMergeTagAt,\n} = useMergeTagField({\n modelValue: () => props.modelValue,\n emit: (value) => emit(\"update:modelValue\", value),\n elementRef: inputRef,\n});\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (!handleFieldKeydown(event)) {\n emit(\"keydown\", event);\n }\n}\n\nconst displayClass =\n \"tpl:flex tpl:w-full tpl:min-h-10 tpl:cursor-pointer tpl:items-center tpl:flex-wrap tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:shadow-[var(--tpl-shadow-sm)] tpl:bg-[var(--tpl-bg)] tpl:border-[var(--tpl-border)] tpl:px-3.5 tpl:py-1.5 tpl:transition-all tpl:duration-[120ms] tpl:ease-[cubic-bezier(0.16,1,0.3,1)]\";\n</script>\n\n<template>\n <div v-if=\"hasMergeTags && !isEditing\">\n <MergeTagSegments\n :segments=\"segments\"\n :display-class=\"displayClass\"\n :pulse=\"pulse\"\n @edit=\"startEditing\"\n @clear=\"clearValue\"\n @repick=\"replaceMergeTagAt\"\n />\n <div\n v-if=\"canRequestMergeTag || canInsertLogicTag\"\n class=\"tpl:flex tpl:flex-wrap tpl:gap-1.5\"\n >\n <MergeTagInsertButton\n v-if=\"canRequestMergeTag\"\n :disabled=\"isRequestingMergeTag\"\n @insert=\"insertMergeTag\"\n />\n <LogicTagInsertButton\n v-if=\"canInsertLogicTag\"\n :disabled=\"isRequestingLogicTag\"\n @insert=\"insertLogicTag\"\n />\n </div>\n </div>\n <div v-else>\n <input\n ref=\"inputRef\"\n :type=\"type\"\n :class=\"[inputClass, { 'tpl-pulse-fill': pulse }]\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n @input=\"handleInput\"\n @keydown=\"handleKeydown\"\n @click=\"handleClick\"\n @blur=\"handleBlur\"\n />\n <div\n v-if=\"canRequestMergeTag || canInsertLogicTag\"\n class=\"tpl:flex tpl:flex-wrap tpl:gap-1.5\"\n >\n <MergeTagInsertButton\n v-if=\"canRequestMergeTag\"\n :disabled=\"isRequestingMergeTag\"\n @insert=\"insertMergeTag\"\n />\n <LogicTagInsertButton\n v-if=\"canInsertLogicTag\"\n :disabled=\"isRequestingLogicTag\"\n @insert=\"insertLogicTag\"\n />\n </div>\n </div>\n</template>\n\n<style scoped>\n.tpl-pulse-fill {\n animation: tpl-field-pulse 1s ease-out;\n}\n\n@keyframes tpl-field-pulse {\n 0% {\n box-shadow: 0 0 0 0 color-mix(in srgb, var(--tpl-warning) 30%, transparent);\n background-color: color-mix(in srgb, var(--tpl-warning) 6%, transparent);\n }\n 40% {\n box-shadow: 0 0 0 3px\n color-mix(in srgb, var(--tpl-warning) 15%, transparent);\n background-color: color-mix(in srgb, var(--tpl-warning) 5%, transparent);\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n background-color: transparent;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tpl-pulse-fill {\n animation: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useMergeTagField } from \"../composables/useMergeTagField\";\nimport { inputClass } from \"../constants/styleConstants\";\nimport MergeTagSegments from \"./MergeTagSegments.vue\";\nimport MergeTagInsertButton from \"./MergeTagInsertButton.vue\";\nimport LogicTagInsertButton from \"./LogicTagInsertButton.vue\";\nimport { ref } from \"vue\";\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string;\n type?: \"text\" | \"url\";\n placeholder?: string;\n pulse?: boolean;\n }>(),\n {\n type: \"text\",\n placeholder: \"\",\n pulse: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: string): void;\n /**\n * Keydown the autocomplete popup declined. Declared (rather than left to\n * attribute fallthrough) so a host binding `@keydown` never sees the key\n * that just picked a tag — the link dialog would submit on it.\n */\n (e: \"keydown\", event: KeyboardEvent): void;\n}>();\n\nconst inputRef = ref<HTMLInputElement | null>(null);\n\nconst {\n segments,\n hasMergeTags,\n canRequestMergeTag,\n isRequestingMergeTag,\n canInsertLogicTag,\n isRequestingLogicTag,\n isEditing,\n startEditing,\n handleInput,\n handleKeydown: handleFieldKeydown,\n handleClick,\n handleBlur,\n clearValue,\n insertMergeTag,\n insertLogicTag,\n replaceMergeTagAt,\n} = useMergeTagField({\n modelValue: () => props.modelValue,\n emit: (value) => emit(\"update:modelValue\", value),\n elementRef: inputRef,\n});\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (!handleFieldKeydown(event)) {\n emit(\"keydown\", event);\n }\n}\n\nconst displayClass =\n \"tpl:flex tpl:w-full tpl:min-h-10 tpl:cursor-pointer tpl:items-center tpl:flex-wrap tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:shadow-[var(--tpl-shadow-sm)] tpl:bg-[var(--tpl-bg)] tpl:border-[var(--tpl-border)] tpl:px-3.5 tpl:py-1.5 tpl:transition-all tpl:duration-[120ms] tpl:ease-[cubic-bezier(0.16,1,0.3,1)]\";\n</script>\n\n<template>\n <div v-if=\"hasMergeTags && !isEditing\">\n <MergeTagSegments\n :segments=\"segments\"\n :display-class=\"displayClass\"\n :pulse=\"pulse\"\n @edit=\"startEditing\"\n @clear=\"clearValue\"\n @repick=\"replaceMergeTagAt\"\n />\n <div\n v-if=\"canRequestMergeTag || canInsertLogicTag\"\n class=\"tpl:flex tpl:flex-wrap tpl:gap-1.5\"\n >\n <MergeTagInsertButton\n v-if=\"canRequestMergeTag\"\n :disabled=\"isRequestingMergeTag\"\n @insert=\"insertMergeTag\"\n />\n <LogicTagInsertButton\n v-if=\"canInsertLogicTag\"\n :disabled=\"isRequestingLogicTag\"\n @insert=\"insertLogicTag\"\n />\n </div>\n </div>\n <div v-else>\n <input\n ref=\"inputRef\"\n :type=\"type\"\n :class=\"[inputClass, { 'tpl-pulse-fill': pulse }]\"\n :value=\"modelValue\"\n :placeholder=\"placeholder\"\n @input=\"handleInput\"\n @keydown=\"handleKeydown\"\n @click=\"handleClick\"\n @blur=\"handleBlur\"\n />\n <div\n v-if=\"canRequestMergeTag || canInsertLogicTag\"\n class=\"tpl:flex tpl:flex-wrap tpl:gap-1.5\"\n >\n <MergeTagInsertButton\n v-if=\"canRequestMergeTag\"\n :disabled=\"isRequestingMergeTag\"\n @insert=\"insertMergeTag\"\n />\n <LogicTagInsertButton\n v-if=\"canInsertLogicTag\"\n :disabled=\"isRequestingLogicTag\"\n @insert=\"insertLogicTag\"\n />\n </div>\n </div>\n</template>\n\n<style scoped>\n.tpl-pulse-fill {\n animation: tpl-field-pulse 1s ease-out;\n}\n\n@keyframes tpl-field-pulse {\n 0% {\n box-shadow: 0 0 0 0 color-mix(in srgb, var(--tpl-warning) 30%, transparent);\n background-color: color-mix(in srgb, var(--tpl-warning) 6%, transparent);\n }\n 40% {\n box-shadow: 0 0 0 3px\n color-mix(in srgb, var(--tpl-warning) 15%, transparent);\n background-color: color-mix(in srgb, var(--tpl-warning) 5%, transparent);\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n background-color: transparent;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tpl-pulse-fill {\n animation: none;\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;AAwBA,SAAgB,EACd,GACA,GACA,GACA,GAC4B;CAC5B,IAAI,CAAC,GAAa,OAAO;CAEzB,IAAM,IAAS,EAAM,MAAM,GAAG,CAAK,GAC7B,IAAe,EAAO,YAAY,CAAW;CACnD,IAAI,MAAiB,IAAI,OAAO;CAEhC,IAAM,IAAQ,EAAO,MAAM,IAAe,EAAY,MAAM;CAS5D,OANI,KAAK,KAAK,CAAK,KAIf,KAAe,EAAM,SAAS,CAAW,IAAU,OAEhD;EAAE;EAAc;EAAO;CAAM;AACtC;;;AC7BA,IAAM,IAAsB,0VA4B5B;AAEA,SAAS,EAAO,GAAc,GAAa,GAAyB;CAElE,OAAO;EACL;EACA;EACA;EACA,OAAO;EACP,OAAO;EACP,QAPa,IAAS;EAQtB,GAAG;EACH,GAAG;EACH,eAAe,CAAC;CAClB;AACF;AAQA,SAAgB,EACd,GACA,GACgB;CAChB,IAAM,IAAM,EAAG,eACT,IAAM,EAAI;CAChB,IAAI,CAAC,GAAK,OAAO;CAEjB,IAAM,IAAU,EAAG,YAAY,SACzB,IAAQ,EAAI,iBAAiB,CAAE,GAE/B,IAAS,EAAI,cAAc,KAAK;CACtC,EAAO,aAAa,eAAe,MAAM;CACzC,IAAM,IAAI,EAAO;CAOjB,AANA,EAAE,WAAW,YACb,EAAE,aAAa,UACf,EAAE,MAAM,KACR,EAAE,OAAO,KACT,EAAE,WAAW,UACb,EAAE,aAAa,IAAU,QAAQ,YACjC,EAAE,WAAW,IAAU,WAAW;CAClC,IAAM,IAAS,GACT,IAAS;CACf,KAAK,IAAM,KAAQ,GACjB,EAAO,KAAQ,EAAO;CAIxB,AAAI,MACF,EAAE,QAAQ,QACV,EAAE,aAAa;CAGjB,IAAM,IAAQ,EAAG,OACb,IAAO,EAAM,MAAM,GAAG,CAAQ;CAMlC,AALI,MAGF,IAAO,EAAK,QAAQ,OAAO,MAAG,IAEhC,EAAO,cAAc;CAErB,IAAM,IAAS,EAAI,cAAc,MAAM;CAKvC,AAHA,EAAO,cAAc,EAAM,MAAM,CAAQ,KAAK,KAC9C,EAAO,YAAY,CAAM,GAEzB,EAAI,KAAK,YAAY,CAAM;CAC3B,IAAM,IAAY,EAAO,WACnB,IAAa,EAAO;CAC1B,EAAI,KAAK,YAAY,CAAM;CAE3B,IAAM,IAAS,EAAG,sBAAsB,GAClC,IAAY,WAAW,EAAM,cAAc,KAAK,GAChD,IAAa,WAAW,EAAM,eAAe,KAAK,GAClD,IACJ,WAAW,EAAM,UAAU,KAAK,WAAW,EAAM,QAAQ,KAAK,GAE1D,IAAO,EAAO,OAAO,IAAa,IAAa,EAAG;CAKxD,IAAI,GACF,OAAO,EAAO,GAAM,EAAO,KAAK,EAAO,MAAM;CAG/C,IAAM,IAAM,EAAO,MAAM,IAAY,IAAY,EAAG;CACpD,OAAO,EAAO,GAAM,GAAK,IAAM,CAAU;AAC3C;;;AClEA,IAAM,oBAAkB,IAAI,IAAI;CAAC;CAAa;CAAc;CAAQ;AAAK,CAAC;AAY1E,SAAgB,EACd,GAC+B;CAC/B,IAAM,EAAE,eAAY,eAAY,SAAM,cAAW,WAAQ,YAAS,gBAChE,GAEI,IAAc,EAAqB,CAAM,GACzC,IAAc,EAAqB,CAAM,GAIzC,IAAY,QACV,KAAW,MAAgB,QAAQ,EAAU,MAAM,SAAS,CACpE,GAKM,IAAuB,EAAO,GAAkB,IAAI,GAKpD,KAHuB,EAAM,CAAoB,IACnD,EAAqB,QACrB,EAAA,EAEoB,UAAU,mBAAmB,0BAE/C,IAAc,EAAe,GAC7B,IAAQ,EAAoB,GAAW,CAAW,GAEpD,IAAW;CACf,AAAI,EAAgB,KAClB,QAAqB;EAEnB,AADA,IAAW,IACX,EAAM,MAAM;CACd,CAAC;CAGH,SAAS,EAAa,GAA4C;EAChE,IAAM,IAAQ,EAAG,SAAS;EAE1B,OAAO,EACL,GAFY,EAAG,kBAAkB,EAAM,QAIvC,GACA,CACF;CACF;CAEA,SAAS,EACP,GACA,GACA,GACM;EACN,IAAM,IAAQ,EAAG,SAAS,EAAW,GAG/B,IAAa,EAAM,MAAM,EAAM,KAAK,GACpC,IACJ,KAAe,EAAW,WAAW,CAAW,IAC5C,EAAY,SACZ,GACA,IAAS,EAAM,MAAM,GAAG,EAAM,YAAY,GAC1C,IAAQ,EAAM,MAAM,EAAM,QAAQ,CAAQ,GAC1C,IAAW,IAAS,EAAI,QAAQ,GAChC,IAAS,EAAO,SAAS,EAAI,MAAM;EASzC,AAJA,IAAW,GACX,EAAK,CAAQ,GACb,EAAM,MAAM,GAEZ,QAAe;GACb,IAAI,GAAU;GACd,IAAM,IAAO,EAAW;GAExB,AADA,GAAM,MAAM,GACZ,GAAM,kBAAkB,GAAQ,CAAM;EACxC,CAAC;CACH;CAEA,SAAS,IAAgB;EACvB,IAAI,CAAC,EAAU,SAAS,GAAU;EAClC,IAAM,IAAK,EAAW;EACtB,IAAI,CAAC,GAAI;GACP,EAAM,MAAM;GACZ;EACF;EACA,IAAM,IAAQ,EAAa,CAAE;EAC7B,IAAI,CAAC,GAAO;GACV,EAAM,MAAM;GACZ;EACF;EAEA,IAAM,IAAQ,EAAgB,EAAU,OAAO,EAAM,KAAK,GACpD,UAAgB,EAAa,GAAI,EAAM,YAAY,GACnD,KAAa,MAAkB,EAAe,GAAI,GAAO,CAAG;EAElE,AAAI,EAAM,OAAO,IACf,EAAM,OAAO;GAAE;GAAO;GAAS;EAAU,CAAC,IAE1C,EAAM,KAAK;GAAE;GAAO;GAAS,UAAU;GAAI;EAAU,CAAC;CAE1D;CAEA,SAAS,EAAc,GAA+B;EAUpD,OATK,EAAM,OAAO,IACd,EAAM,QAAQ,YAChB,EAAM,MAAM,GACL,MAEL,EAAgB,IAAI,EAAM,GAAG,KAC/B,EAAM,MAAM,GACL,MAEF,EAAM,cAAc,CAAK,IATJ;CAU9B;CAEA,OAAO;EACL;EACA;EACA;EACA,aAAa,EAAM,MAAM;EACzB,cAAc,EAAM,OAAO;CAC7B;AACF;;;ACrJA,SAAgB,EACd,GACwB;CACxB,IAAM,EAAE,eAAY,SAAM,kBAAe,GAEnC,EACJ,cACA,uBACA,cAAc,GACd,oBACA,4BACA,iBACA,oBACA,WACA,oBACE,EAAY,GAEV,EACJ,sBACA,cAAc,GACd,uBACE,EAAY,GAEV,IAAY,EAAI,EAAK,GACvB,IAAoB,IACpB,IAAW;CACf,AAAI,EAAgB,KAClB,QAAqB;EACnB,IAAW;CACb,CAAC;CAMH,IAAM,IAAY,EAAwB;EACxC;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,gBAAgB;GACd,EAAU,QAAQ;EACpB;CACF,CAAC,GAEK,IAAW,QAAkC;EACjD,IAAM,IAAM,EAAW;EACvB,IAAI,CAAC,GAAK,OAAO,CAAC;EAElB,IAAM,IAA4B,CAAC,GAC7B,IAAiB,IAAI,EAAO,MAAM,OAAO,GAAG,EAAO,MAAM,OAAO,IAChE,IAAQ,IAAI,OAAO,GAAgB,GAAG,GACxC,IAAY,GACZ;EAEJ,QAAQ,IAAQ,EAAM,KAAK,CAAG,OAAO,OAAM;GACzC,AAAI,EAAM,QAAQ,KAChB,EAAO,KAAK;IACV,MAAM;IACN,OAAO,EAAI,MAAM,GAAW,EAAM,KAAK;GACzC,CAAC;GAGH,IAAM,IAAU,EAAM;GAoBtB,AAnBI,EAAgB,CAAO,IACzB,EAAO,KAAK;IACV,MAAM;IACN,OAAO;IAIP,OAAO,EAAwB,CAAO;GACxC,CAAC,IACQ,EAAqB,GAAS,CAAM,IAC7C,EAAO,KAAK;IACV,MAAM;IACN,OAAO;IACP,SAAS,EAAwB,GAAS,CAAM;GAClD,CAAC,IAED,EAAO,KAAK;IAAE,MAAM;IAAQ,OAAO;GAAQ,CAAC,GAG9C,IAAY,EAAM,QAAQ,EAAQ;EACpC;EAMA,OAJI,IAAY,EAAI,UAClB,EAAO,KAAK;GAAE,MAAM;GAAQ,OAAO,EAAI,MAAM,CAAS;EAAE,CAAC,GAGpD;CACT,CAAC,GAEK,IAAe,QACnB,EAAS,MAAM,MACZ,MAAM,EAAE,SAAS,cAAc,EAAE,SAAS,eAC7C,CACF;CAEA,SAAS,IAAqB;EAE5B,AADA,EAAU,QAAQ,IAClB,QAAe;GACb,EAAW,OAAO,MAAM;GACxB,IAAM,IAAM,EAAW,CAAC,EAAE,UAAU;GACpC,EAAW,OAAO,kBAAkB,GAAK,CAAG;EAC9C,CAAC;CACH;CAEA,SAAS,IAAoB;EACvB,MACJ,EAAU,QAAQ;CACpB;CAEA,SAAS,EAAY,GAAoB;EAEvC,AADA,EAAM,EAAM,OAAkD,KAAK,GACnE,EAAU,QAAQ;CACpB;CAUA,SAAS,EAAc,GAA+B;EAQpD,OAPI,EAAU,cAAc,CAAK,KAC/B,EAAM,eAAe,GACd,OAEL,EAAM,QAAQ,YAChB,EAAY,GAEP;CACT;CAGA,SAAS,IAAoB;EAC3B,EAAU,QAAQ;CACpB;CAGA,SAAS,IAAmB;EAE1B,AADA,EAAU,MAAM,GAChB,EAAY;CACd;CAEA,SAAS,IAAmB;EAC1B,EAAK,EAAE;CACT;CAEA,eAAe,IAAgC;EAC7C,IAAM,IACJ,EAAU,SAAS,EAAW,QACzB,EAAW,MAAM,kBAAkB,EAAW,CAAC,CAAC,SACjD,EAAW,CAAC,CAAC;EAEnB,IAAoB;EACpB,IAAI;EACJ,IAAI;GACF,IAAW,MAAM,EAAgB;EACnC,UAAU;GACR,IAAoB;EACtB;EAEI,UAEA,GAAU;GACZ,IAAM,IAAS,EAAW,CAAC,CAAC,MAAM,GAAG,CAAS,GACxC,IAAQ,EAAW,CAAC,CAAC,MAAM,CAAS,GACpC,IAAW,IAAS,EAAS,QAAQ;GAI3C,AAHA,EAAK,CAAQ,GAEb,EAAU,QAAQ,IAClB,QAAe;IACb,IAAI,GAAU;IACd,IAAM,IAAS,IAAY,EAAS,MAAM;IAE1C,AADA,EAAW,OAAO,MAAM,GACxB,EAAW,OAAO,kBAAkB,GAAQ,CAAM;GACpD,CAAC;EACH;CACF;CAEA,eAAe,EAAkB,GAA8B;EAK7D,IAAM,IAAW,EAAS,OACpB,IAAS,EAAS;EACxB,IAAI,GAAQ,SAAS,YAAY;EAIjC,IAAoB;EACpB,IAAI;EACJ,IAAI;GACF,IAAc,MAAM,EAAgB;IAClC,QAAQ;IACR,SAAS,EAAa,EAAO,KAAK;GACpC,CAAC;EACH,UAAU;GACR,IAAoB;EACtB;EAEI,MAAa,KAEjB,EACE,EACG,KAAK,GAAS,MAAO,MAAM,IAAQ,EAAY,QAAQ,EAAQ,KAAM,CAAC,CACtE,KAAK,EAAE,CACZ;CACF;CAEA,eAAe,IAAgC;EAG7C,IAAM,IAAK,EAAW,OAChB,IAAQ,GAAI,kBAAkB,EAAW,CAAC,CAAC,QAC3C,IAAM,GAAI,gBAAgB;EAEhC,IAAoB;EACpB,IAAI;EACJ,IAAI;GACF,IAAO,MAAM,EAAgB;EAC/B,UAAU;GACR,IAAoB;EACtB;EAEA,IAAI,KAAY,CAAC,GAAM;EAEvB,IAAM,IAAM,EAAW,GACnB,GACA;EAoBJ,AAnBI,YAAY,KAId,IACE,EAAI,MAAM,GAAG,CAAK,IAClB,EAAK,SACL,EAAI,MAAM,GAAO,CAAG,IACpB,EAAK,QACL,EAAI,MAAM,CAAG,GACf,IAAS,IAAQ,EAAK,OAAO,UAAU,IAAM,OAG7C,IAAW,EAAI,MAAM,GAAG,CAAK,IAAI,EAAK,QAAQ,EAAI,MAAM,CAAK,GAC7D,IAAS,IAAQ,EAAK,MAAM,SAE9B,EAAK,CAAQ,GAEb,EAAU,QAAQ,IAClB,QAAe;GACT,MACJ,EAAW,OAAO,MAAM,GACxB,EAAW,OAAO,kBAAkB,GAAQ,CAAM;EACpD,CAAC;CACH;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,uBAAuB,EAAU;CACnC;AACF;;;;;;;;;;;;;;;;;;;;;;;EC1UA,IAAM,IAAO,GAOP,EAAE,MAAG,cAAW,EAAQ,GACxB,EAAE,sBAAmB,oBAAiB,EAAY;EAExD,SAAS,IAAe;GACtB,EAAK,MAAM;EACb;oBAYE,EAAA,GAAA,EA6FM,OAAA;GA5FJ,MAAK;GACJ,cAAY,EAAA,CAAA,CAAC,CAAC,SAAS;GACvB,OAAK,EAAA,CAAG,EAAA,cAAY,EAAA,kBAAsB,EAAA,MAAK,CAAA,CAAA;GAC/C,SAAO;;IAER,EAAA,EAAA,GAAA,EAkEW,GAAA,MAAA,EAjEU,EAAA,WAAX,GAAK,OACJ,EAAA,GAAA,EAAA,GAAA,EAAA,KAAA,GAAA,EAAI,KAAI,GAAI,EAAC,GAAI,EAAI,QAAA,GAAA,CAGtB,EAAI,SAAI,cAAmB,EAAA,CAAA,CAAiB,CAAC,EAAI,KAAK,KAD9D,EAAA,GAAA,EAqBS,UAAA;;IAnBP,MAAK;IACJ,OAAK,EAAA,CAAA,oJAA4K,EAAA,CAAA,IAAY,gBAAA,EAAA,CAAA;IAI7L,gBAAc,EAAA,CAAA,IAAe,EAAI,QAAQ,KAAA;IACzC,cAAY,EAAA,CAAA,CAAM,CAAC,EAAA,CAAA,CAAC,CAAC,SAAS,WAAS,EAAA,OAAW,EAAI,MAAK,CAAA;IAC5D,eAAY;IACZ,OAAA;KAAA,oBAAA;KAAA,OAAA;IAAA;IAQC,SAAK,GAAA,MAAO,EAAI,UAAW,CAAC,GAAA,CAAA,MAAA,CAAA;GAE1B,GAAA,EAAA,EAAI,KAAK,GAAA,IAAA,CAAA,KASD,EAAI,SAAI,cADrB,EAAA,GAAA,EAiBO,QAAA;;IAfJ,OAAK,EAAA,CAAA,iHAAyI,EAAA,CAAA,IAAY,gBAAA,EAAA,CAAA;IAI1J,gBAAc,EAAA,CAAA,IAAe,EAAI,QAAQ,KAAA;IAC1C,OAAA;KAAA,oBAAA;KAAA,OAAA;IAAA;GASG,GAAA,EAAA,EAAI,KAAK,GAAA,IAAA,CAAA,KAGD,EAAI,SAAI,mBADrB,EAAA,GAAA,EAYO,QAAA;;IAVL,OAAM;IACL,gBAAc,EAAI;IACnB,OAAA;KAAA,oBAAA;KAAA,QAAA;KAAA,OAAA;IAAA;GAOG,GAAA,EAAA,EAAI,OAAO,GAAA,GAAA,CAAA,MAEhB,EAAA,GAAA,EAES,QAFT,GAES,EADP,EAAI,KAAK,GAAA,CAAA,EAAA,GAAA,EAAA;GAGb,EASS,UAAA;IARP,MAAK;IACL,OAAM;IACL,cAAY,EAAA,CAAA,CAAC,CAAC,SAAS;IACvB,OAAO,EAAA,CAAA,CAAC,CAAC,SAAS;IACnB,eAAY;IACX,SAAK,EAAO,GAAM,CAAA,MAAA,CAAA;GAEnB,GAAA,CAAA,EAAuC,EAAA,CAAA,GAAA;IAA9B,MAAM;IAAK,gBAAc;;GAEpC,EASS,UAAA;IARP,MAAK;IACL,OAAM;IACL,cAAY,EAAA,CAAA,CAAC,CAAC,SAAS;IACvB,OAAO,EAAA,CAAA,CAAC,CAAC,SAAS;IACnB,eAAY;IACX,SAAK,AAAA,EAAA,OAAA,GAAA,MAAO,EAAI,OAAA,GAAA,CAAA,MAAA,CAAA;GAEjB,GAAA,CAAA,EAAoC,EAAA,CAAA,GAAA;IAAhC,MAAM;IAAK,gBAAc;;;;;;;;GEjH7B,KACJ;;;;;EAHF,IAAM,EAAE,MAAM,EAAQ;oBAOpB,EAAA,GAAA,EAWS,UAAA;GAVP,MAAK;GACJ,OAAK,EAAA,CAAG,IAAgB,YAAA,CAAA;GACxB,cAAY,EAAA,CAAA,CAAC,CAAC,SAAS;GACvB,OAAO,EAAA,CAAA,CAAC,CAAC,SAAS;GAClB,UAAU,EAAA;GACV,aAAS,AAAA,EAAA,OAAA,QAAV,CAAA,GAAkB,CAAA,SAAA,CAAA;GACjB,SAAK,AAAA,EAAA,QAAA,MAAEA,EAAAA,MAAK,QAAA;EAEb,GAAA,CAAA,EAAyC,EAAA,CAAA,GAAA;GAA9B,MAAM;GAAK,gBAAc;EAAK,CAAA,GAAA,EAAA,MACzC,EAAG,EAAA,CAAA,CAAC,CAAC,SAAS,WAAW,GAAA,CAAA,CAAA,GAAA,IAAA,EAAA;;;;;;GEfvB,KACJ;;;;;EAHF,IAAM,EAAE,MAAM,EAAQ;oBAOpB,EAAA,GAAA,EAYS,UAAA;GAXP,MAAK;GACJ,OAAK,EAAA,CAAG,IAAa,YAAA,CAAA;GACrB,cAAY,EAAA,CAAA,CAAC,CAAC,SAAS;GACvB,OAAO,EAAA,CAAA,CAAC,CAAC,SAAS;GAClB,UAAU,EAAA;GACX,eAAY;GACX,aAAS,AAAA,EAAA,OAAA,QAAV,CAAA,GAAkB,CAAA,SAAA,CAAA;GACjB,SAAK,AAAA,EAAA,QAAA,MAAEC,EAAAA,MAAK,QAAA;EAEb,GAAA,CAAA,EAAuC,EAAA,CAAA,GAAA;GAA9B,MAAM;GAAK,gBAAc;EAAK,CAAA,GAAA,EAAA,MACvC,EAAG,EAAA,CAAA,CAAC,CAAC,SAAS,WAAW,GAAA,CAAA,CAAA,GAAA,IAAA,EAAA;;;;;;;;;;;;GEiCvB,KACJ;;;;;;;;;;;;;EAxDF,IAAM,IAAQ,GAcR,IAAO,GAUP,IAAW,EAA6B,IAAI,GAE5C,EACJ,aACA,iBACA,uBACA,yBACA,sBACA,yBACA,cACA,iBACA,gBACA,eAAe,GACf,gBACA,eACA,eACA,mBACA,mBACA,yBACE,EAAiB;GACnB,kBAAkB,EAAM;GACxB,OAAO,MAAU,EAAK,qBAAqB,CAAK;GAChD,YAAY;EACd,CAAC;EAED,SAAS,EAAc,GAA4B;GACjD,AAAK,EAAmB,CAAK,KAC3B,EAAK,WAAW,CAAK;EAEzB;mBAOa,EAAA,CAAA,KAAY,CAAK,EAAA,CAAA,KAA5B,EAAA,GAAA,EAwBM,OAAA,IAAA,CAvBJ,EAOE,GAAA;GANC,UAAU,EAAA,CAAA;GACV,iBAAe;GACf,OAAO,EAAA;GACP,QAAM,EAAA,CAAA;GACN,SAAO,EAAA,CAAA;GACP,UAAQ,EAAA,CAAA;;;;;;;EAGH,CAAA,GAAA,EAAA,CAAA,KAAsB,EAAA,CAAA,KAD9B,EAAA,GAAA,EAcM,OAdN,IAcM,CATI,EAAA,CAAA,KADR,EAAA,GAAA,EAIE,GAAA;;GAFC,UAAU,EAAA,CAAA;GACV,UAAQ,EAAA,CAAA;EAGH,GAAA,MAAA,GAAA,CAAA,YAAA,UAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAA,CAAA,KADR,EAAA,GAAA,EAIE,GAAA;;GAFC,UAAU,EAAA,CAAA;GACV,UAAQ,EAAA,CAAA;EAIf,GAAA,MAAA,GAAA,CAAA,YAAA,UAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,MAAA,EAAA,GAAA,EA2BM,OAAA,IAAA,CA1BJ,EAUE,SAAA;GATI,SAAA;GAAJ,KAAI;GACH,MAAM,EAAA;GACN,OAAK,EAAA,CAAG,EAAA,CAAA,GAAU,EAAA,kBAAsB,EAAA,MAAK,CAAA,CAAA;GAC7C,OAAO,EAAA;GACP,aAAa,EAAA;GACb,SAAK,AAAA,EAAA,QAAE,GAAA,MAAA,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;GACP,WAAS;GACT,SAAK,AAAA,EAAA,QAAE,GAAA,MAAA,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;GACP,QAAI,AAAA,EAAA,QAAE,GAAA,MAAA,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;EAGD,GAAA,MAAA,IAAA,EAAA,GAAA,EAAA,CAAA,KAAsB,EAAA,CAAA,KAD9B,EAAA,GAAA,EAcM,OAdN,IAcM,CATI,EAAA,CAAA,KADR,EAAA,GAAA,EAIE,GAAA;;GAFC,UAAU,EAAA,CAAA;GACV,UAAQ,EAAA,CAAA;EAGH,GAAA,MAAA,GAAA,CAAA,YAAA,UAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAA,CAAA,KADR,EAAA,GAAA,EAIE,GAAA;;GAFC,UAAU,EAAA,CAAA;GACV,UAAQ,EAAA,CAAA"}
|