@templatical/editor 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +84 -31
- package/dist/{AiChatSidebar-KeS30iRG.js → AiChatSidebar-Bq99wU01.js} +14 -14
- package/dist/{AiFeatureMenu-CCdTgCy7.js → AiFeatureMenu-F-C59LAV.js} +7 -7
- package/dist/{BlockIssueBadge-DQ6jBV1T.js → BlockIssueBadge-Dhk7Hv4m.js} +5 -5
- package/dist/{BlockPreviewCanvas-MgXVXOG_.js → BlockPreviewCanvas-CqU1kwmG.js} +3 -3
- package/dist/{CloudHeaderExtras-L_b51XVJ.js → CloudHeaderExtras-vnGV_mLD.js} +5 -5
- package/dist/{CloudPanels-XUtScYFl.js → CloudPanels-Dv-MD1Tc.js} +7 -7
- package/dist/{CollaboratorBar-Cx5klY7H.js → CollaboratorBar-DmssyJoB.js} +4 -4
- package/dist/{ColorPicker-DjfecH79.js → ColorPicker-CXPSbnRD.js} +7 -7
- package/dist/{CommentsPanel-5QxgkKF-.js → CommentsPanel-DnWdgQHg.js} +2 -2
- package/dist/{CommentsSidebar-CScszOsC.js → CommentsSidebar-ZOqmuo4D.js} +16 -16
- package/dist/{CountdownBlock-Drr1WErd.js → CountdownBlock-BgNK7fZY.js} +3 -3
- package/dist/{CountdownToolbar-CiBrLbq0.js → CountdownToolbar-SwmE7CIk.js} +19 -19
- package/dist/{DesignReferenceSidebar-B1__DJJI.js → DesignReferenceSidebar-9cLTzOqP.js} +11 -11
- package/dist/{NumberWithSuffix-C1D0WFrN.js → FieldRow-0-UbQR4a.js} +24 -17
- package/dist/{IssuesPanel-CkuV9Fjp.js → IssuesPanel-CDk7lUna.js} +8 -8
- package/dist/{LoadingTrack-Db9j_aBr.js → LoadingTrack-5KBr5cE8.js} +1 -1
- package/dist/{MergeTagModeToggle-oX-n91fH.js → MergeTagModeToggle-DtD_Xl9w.js} +6 -6
- package/dist/{MergeTagSuggestion-BUozNVtA.js → MergeTagSuggestion-DPfXtDzP.js} +4 -4
- package/dist/{ParagraphEditor-BVlMj-YW.js → ParagraphEditor-C0NbqDmV.js} +25 -25
- package/dist/{RestoreVersionDialog-CZRLWoqP.js → RestoreVersionDialog-DCX0rJiV.js} +5 -5
- package/dist/{RichTextEditorContent-BN6RBSZG.js → RichTextEditorContent-DZ6GiAUi.js} +8 -8
- package/dist/{SaveBlockDialog-KNQVLcUG.js → SaveBlockDialog-e5LtQRVk.js} +10 -10
- package/dist/{SavedBlocksBrowserModal-D7qatvfw.js → SavedBlocksBrowserModal-ZQIQoARO.js} +11 -11
- package/dist/{SavedBlocksPanels-bizAFdNK.js → SavedBlocksPanels-pGZWjSmp.js} +2 -2
- package/dist/{SavedBlocksPickBar-BXUSoa38.js → SavedBlocksPickBar-OZaOG1Si.js} +4 -4
- package/dist/{TemplateScoringPanel-Dm83xt9R.js → TemplateScoringPanel-CDwlSFEe.js} +15 -15
- package/dist/{TestEmailModal-DAdO9Gmo.js → TestEmailModal-PVa1VL2p.js} +11 -11
- package/dist/{TestEmailPanel-DORs6xk0.js → TestEmailPanel-RekBdAtO.js} +2 -2
- package/dist/{TitleEditor-B_aWxZER.js → TitleEditor-Cs2tELCL.js} +12 -12
- package/dist/{TplModal-7623HR5x.js → TplModal-Bw1i8_eE.js} +5 -5
- package/dist/{VersionHistoryMenu-D7lgozpw.js → VersionHistoryMenu-B6zAcmAC.js} +8 -8
- package/dist/{VersionHistoryPanels-Dor0p1Ur.js → VersionHistoryPanels-TqTC4ofA.js} +2 -2
- package/dist/{VersionPreviewBanner-CQt2il1L.js → VersionPreviewBanner-CQlSzQ2B.js} +3 -3
- package/dist/{blockTypeIcons-Di4AsjQx.js → blockTypeIcons-C7WedEOG.js} +2 -2
- package/dist/bundle-stats.json +6 -6
- package/dist/{cdn/chunks/ca-DY0AYOLG.js → ca-DZSrLNXK.js} +2 -2
- package/dist/cdn/chunks/{AiChatSidebar-Cwr9eqTh.js → AiChatSidebar-DmZ1Nvxo.js} +11 -11
- package/dist/cdn/chunks/{AiChatSidebar-Cwr9eqTh.js.map → AiChatSidebar-DmZ1Nvxo.js.map} +1 -1
- package/dist/cdn/chunks/{AiFeatureMenu-CT2QiHmi.js → AiFeatureMenu-D4tax9j3.js} +6 -6
- package/dist/cdn/chunks/{AiFeatureMenu-CT2QiHmi.js.map → AiFeatureMenu-D4tax9j3.js.map} +1 -1
- package/dist/cdn/chunks/{BlockIssueBadge-CXlXn9Sm.js → BlockIssueBadge-Bry71Wjz.js} +5 -5
- package/dist/cdn/chunks/{BlockIssueBadge-CXlXn9Sm.js.map → BlockIssueBadge-Bry71Wjz.js.map} +1 -1
- package/dist/cdn/chunks/{BlockPreviewCanvas-BisO3JEy.js → BlockPreviewCanvas-DDOqFJlT.js} +4 -4
- package/dist/cdn/chunks/{BlockPreviewCanvas-BisO3JEy.js.map → BlockPreviewCanvas-DDOqFJlT.js.map} +1 -1
- package/dist/cdn/chunks/{CloudHeaderExtras-MRCYqip8.js → CloudHeaderExtras-g-_SFPna.js} +5 -5
- package/dist/cdn/chunks/{CloudHeaderExtras-MRCYqip8.js.map → CloudHeaderExtras-g-_SFPna.js.map} +1 -1
- package/dist/cdn/chunks/{CloudPanels-Bb9qSwKJ.js → CloudPanels-Cnh07_2G.js} +7 -7
- package/dist/cdn/chunks/{CloudPanels-Bb9qSwKJ.js.map → CloudPanels-Cnh07_2G.js.map} +1 -1
- package/dist/cdn/chunks/{CollaboratorBar-CG13kDHu.js → CollaboratorBar-CLGB0prG.js} +5 -5
- package/dist/cdn/chunks/{CollaboratorBar-CG13kDHu.js.map → CollaboratorBar-CLGB0prG.js.map} +1 -1
- package/dist/cdn/chunks/{ColorPicker-UpN24AsB.js → ColorPicker-Ww4xHHMI.js} +7 -7
- package/dist/cdn/chunks/{ColorPicker-UpN24AsB.js.map → ColorPicker-Ww4xHHMI.js.map} +1 -1
- package/dist/cdn/chunks/{CommentsPanel-CIcIXzOB.js → CommentsPanel-DjId-XH-.js} +3 -3
- package/dist/cdn/chunks/{CommentsPanel-CIcIXzOB.js.map → CommentsPanel-DjId-XH-.js.map} +1 -1
- package/dist/cdn/chunks/{CommentsSidebar-CB5Z8xNz.js → CommentsSidebar-DXXGWSr4.js} +5 -5
- package/dist/cdn/chunks/{CommentsSidebar-CB5Z8xNz.js.map → CommentsSidebar-DXXGWSr4.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownBlock-_7TUBqJS.js → CountdownBlock-CWeJBC0L.js} +4 -4
- package/dist/cdn/chunks/{CountdownBlock-_7TUBqJS.js.map → CountdownBlock-CWeJBC0L.js.map} +1 -1
- package/dist/cdn/chunks/{CountdownToolbar-B1L0IK1T.js → CountdownToolbar-CO6xLgYc.js} +20 -20
- package/dist/cdn/chunks/{CountdownToolbar-B1L0IK1T.js.map → CountdownToolbar-CO6xLgYc.js.map} +1 -1
- package/dist/cdn/chunks/{DesignReferenceSidebar-BwsfOFsc.js → DesignReferenceSidebar-DRGqm33h.js} +7 -7
- package/dist/cdn/chunks/{DesignReferenceSidebar-BwsfOFsc.js.map → DesignReferenceSidebar-DRGqm33h.js.map} +1 -1
- package/dist/cdn/chunks/{NumberWithSuffix-CWvM_I3T.js → FieldRow-CbcpsxZ4.js} +25 -18
- package/dist/cdn/chunks/FieldRow-CbcpsxZ4.js.map +1 -0
- package/dist/cdn/chunks/{IssuesPanel-3nTCyKgK.js → IssuesPanel-iC2hgrXx.js} +6 -6
- package/dist/cdn/chunks/{IssuesPanel-3nTCyKgK.js.map → IssuesPanel-iC2hgrXx.js.map} +1 -1
- package/dist/cdn/chunks/{LoadingTrack-D_wweXVz.js → LoadingTrack-Cz1sT0wP.js} +2 -2
- package/dist/cdn/chunks/{LoadingTrack-D_wweXVz.js.map → LoadingTrack-Cz1sT0wP.js.map} +1 -1
- package/dist/cdn/chunks/{MergeTagModeToggle-BUNsRKs6.js → MergeTagModeToggle-DZtnCj0F.js} +6 -6
- package/dist/cdn/chunks/{MergeTagModeToggle-BUNsRKs6.js.map → MergeTagModeToggle-DZtnCj0F.js.map} +1 -1
- package/dist/cdn/chunks/{MergeTagSuggestion-Dt6I8bZi.js → MergeTagSuggestion-VP_nC-8W.js} +3 -3
- package/dist/cdn/chunks/{MergeTagSuggestion-Dt6I8bZi.js.map → MergeTagSuggestion-VP_nC-8W.js.map} +1 -1
- package/dist/cdn/chunks/{ParagraphEditor-BtzkHfv2.js → ParagraphEditor-BalgLjBt.js} +27 -27
- package/dist/cdn/chunks/{ParagraphEditor-BtzkHfv2.js.map → ParagraphEditor-BalgLjBt.js.map} +1 -1
- package/dist/cdn/chunks/{RestoreVersionDialog-DNoo-EBT.js → RestoreVersionDialog-DGOXQ0ou.js} +5 -5
- package/dist/cdn/chunks/{RestoreVersionDialog-DNoo-EBT.js.map → RestoreVersionDialog-DGOXQ0ou.js.map} +1 -1
- package/dist/cdn/chunks/{RichTextEditorContent-BQATmyd9.js → RichTextEditorContent-DpvOKKH-.js} +7 -7
- package/dist/cdn/chunks/{RichTextEditorContent-BQATmyd9.js.map → RichTextEditorContent-DpvOKKH-.js.map} +1 -1
- package/dist/cdn/chunks/{SaveBlockDialog-DB37Vmqt.js → SaveBlockDialog-Dod3jX9X.js} +8 -8
- package/dist/cdn/chunks/{SaveBlockDialog-DB37Vmqt.js.map → SaveBlockDialog-Dod3jX9X.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksBrowserModal-CTU2rGWQ.js → SavedBlocksBrowserModal-BysGB8zb.js} +9 -9
- package/dist/cdn/chunks/{SavedBlocksBrowserModal-CTU2rGWQ.js.map → SavedBlocksBrowserModal-BysGB8zb.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksPanels-B9h9wI6d.js → SavedBlocksPanels-DJ4fceEM.js} +3 -3
- package/dist/cdn/chunks/{SavedBlocksPanels-B9h9wI6d.js.map → SavedBlocksPanels-DJ4fceEM.js.map} +1 -1
- package/dist/cdn/chunks/{SavedBlocksPickBar-CTY5WZum.js → SavedBlocksPickBar-DGgbqAsb.js} +5 -5
- package/dist/cdn/chunks/{SavedBlocksPickBar-CTY5WZum.js.map → SavedBlocksPickBar-DGgbqAsb.js.map} +1 -1
- package/dist/cdn/chunks/{TemplateScoringPanel-DZ0cpe_D.js → TemplateScoringPanel-B0YcaJsR.js} +6 -6
- package/dist/cdn/chunks/{TemplateScoringPanel-DZ0cpe_D.js.map → TemplateScoringPanel-B0YcaJsR.js.map} +1 -1
- package/dist/cdn/chunks/{TestEmailModal-Dqx1RyDE.js → TestEmailModal-DvZFnhWa.js} +10 -10
- package/dist/cdn/chunks/{TestEmailModal-Dqx1RyDE.js.map → TestEmailModal-DvZFnhWa.js.map} +1 -1
- package/dist/cdn/chunks/{TestEmailPanel-DrcQhnON.js → TestEmailPanel-BdxpMiWc.js} +3 -3
- package/dist/cdn/chunks/{TestEmailPanel-DrcQhnON.js.map → TestEmailPanel-BdxpMiWc.js.map} +1 -1
- package/dist/cdn/chunks/{TitleEditor-CSeDvWVn.js → TitleEditor-CfHWnThg.js} +12 -12
- package/dist/cdn/chunks/{TitleEditor-CSeDvWVn.js.map → TitleEditor-CfHWnThg.js.map} +1 -1
- package/dist/cdn/chunks/{TplModal-BNBLwBxJ.js → TplModal-BMTW5bEN.js} +5 -5
- package/dist/cdn/chunks/{TplModal-BNBLwBxJ.js.map → TplModal-BMTW5bEN.js.map} +1 -1
- package/dist/cdn/chunks/{VersionHistoryMenu-cZlb0sMi.js → VersionHistoryMenu-DJGcA_RX.js} +5 -5
- package/dist/cdn/chunks/{VersionHistoryMenu-cZlb0sMi.js.map → VersionHistoryMenu-DJGcA_RX.js.map} +1 -1
- package/dist/cdn/chunks/{VersionHistoryPanels-DgrjTK3z.js → VersionHistoryPanels-2l_FLtix.js} +3 -3
- package/dist/cdn/chunks/{VersionHistoryPanels-DgrjTK3z.js.map → VersionHistoryPanels-2l_FLtix.js.map} +1 -1
- package/dist/cdn/chunks/{VersionPreviewBanner-BNq7PRun.js → VersionPreviewBanner-C8pfES5A.js} +4 -4
- package/dist/cdn/chunks/{VersionPreviewBanner-BNq7PRun.js.map → VersionPreviewBanner-C8pfES5A.js.map} +1 -1
- package/dist/cdn/chunks/{blockTypeIcons-BNGmmzB_.js → blockTypeIcons-JUwZtKaq.js} +2 -2
- package/dist/cdn/chunks/{blockTypeIcons-BNGmmzB_.js.map → blockTypeIcons-JUwZtKaq.js.map} +1 -1
- package/dist/{ca-DY0AYOLG.js → cdn/chunks/ca-DZSrLNXK.js} +4 -0
- package/dist/cdn/chunks/ca-DZSrLNXK.js.map +1 -0
- package/dist/cdn/chunks/{cloud-CRCcXTc5.js → cloud-CITqEHEc.js} +3 -3
- package/dist/cdn/chunks/{cloud-CRCcXTc5.js.map → cloud-CITqEHEc.js.map} +1 -1
- package/dist/cdn/chunks/{createCloudRuntime-B_HRgFxU.js → createCloudRuntime-jLhuyKds.js} +8 -8
- package/dist/cdn/chunks/{createCloudRuntime-B_HRgFxU.js.map → createCloudRuntime-jLhuyKds.js.map} +1 -1
- package/dist/{de-CYLWugqb.js → cdn/chunks/de-DbayqpK-.js} +4 -0
- package/dist/cdn/chunks/{de-CYLWugqb.js.map → de-DbayqpK-.js.map} +1 -1
- package/dist/cdn/chunks/{dist-eKG4m5Wx.js → dist-CgR3inPR.js} +3 -3
- package/dist/cdn/chunks/{dist-eKG4m5Wx.js.map → dist-CgR3inPR.js.map} +1 -1
- package/dist/cdn/chunks/{dist-2fOlspdg.js → dist-El3fQnfk.js} +4 -4
- package/dist/cdn/chunks/{dist-2fOlspdg.js.map → dist-El3fQnfk.js.map} +1 -1
- package/dist/cdn/chunks/{draggable-BLMjz0GK.js → draggable-D2vo-aQI.js} +1465 -1435
- package/dist/cdn/chunks/draggable-D2vo-aQI.js.map +1 -0
- package/dist/cdn/chunks/en-CwXyUb6-.js +2 -0
- package/dist/{en-C3TM249M.js → cdn/chunks/en-l0ib5X0f.js} +4 -0
- package/dist/cdn/chunks/en-l0ib5X0f.js.map +1 -0
- package/dist/cdn/chunks/{es-D1SF4nCR.js → es-CMQ-5PJP.js} +3 -1
- package/dist/cdn/chunks/es-CMQ-5PJP.js.map +1 -0
- package/dist/cdn/chunks/{extensions-Deqilwp8.js → extensions-D30V0hzj.js} +7 -7
- package/dist/cdn/chunks/{extensions-Deqilwp8.js.map → extensions-D30V0hzj.js.map} +1 -1
- package/dist/cdn/chunks/{fr-CdLhJ7kw.js → fr-DNXmZWAq.js} +3 -1
- package/dist/cdn/chunks/fr-DNXmZWAq.js.map +1 -0
- package/dist/cdn/chunks/{icons-C2kP4vOJ.js → icons-BTdLXRXn.js} +13 -13
- package/dist/cdn/chunks/icons-BTdLXRXn.js.map +1 -0
- package/dist/cdn/chunks/{keys-D7OpfE2s.js → keys-BJ770Mwm.js} +2 -2
- package/dist/cdn/chunks/{keys-D7OpfE2s.js.map → keys-BJ770Mwm.js.map} +1 -1
- package/dist/cdn/chunks/{liquid.browser-UlAOKBjI.js → liquid.browser-BPvKXNfO.js} +2 -2
- package/dist/cdn/chunks/{liquid.browser-UlAOKBjI.js.map → liquid.browser-BPvKXNfO.js.map} +1 -1
- package/dist/{nl-BvsLoyKp.js → cdn/chunks/nl-BylRRHYJ.js} +4 -0
- package/dist/cdn/chunks/nl-BylRRHYJ.js.map +1 -0
- package/dist/cdn/chunks/{preRenderCustomBlocks-CbA3RcAy.js → preRenderCustomBlocks-DyCIgmqJ.js} +2 -2
- package/dist/cdn/chunks/{preRenderCustomBlocks-CbA3RcAy.js.map → preRenderCustomBlocks-DyCIgmqJ.js.map} +1 -1
- package/dist/cdn/chunks/{pt-BR-CAGS5YXp.js → pt-BR-BVoJhpie.js} +3 -1
- package/dist/cdn/chunks/pt-BR-BVoJhpie.js.map +1 -0
- package/dist/cdn/chunks/{src-CgIXdQlX.js → src-65H3RNcb.js} +8 -8
- package/dist/cdn/chunks/{src-CgIXdQlX.js.map → src-65H3RNcb.js.map} +1 -1
- package/dist/cdn/chunks/{src-Cx70q30o.js → src-6J-yyZoD.js} +2 -2
- package/dist/cdn/chunks/{src-Cx70q30o.js.map → src-6J-yyZoD.js.map} +1 -1
- package/dist/cdn/chunks/{src-B_QJduQD.js → src-BD60gqPW.js} +72 -67
- package/dist/cdn/chunks/src-BD60gqPW.js.map +1 -0
- package/dist/cdn/chunks/{src-CnQgwcsc.js → src-CLTXM4PM.js} +166 -136
- package/dist/cdn/chunks/src-CLTXM4PM.js.map +1 -0
- package/dist/cdn/chunks/{tiptap-DOw5Yb4H.js → tiptap-Bqy-H6CT.js} +2295 -2205
- package/dist/cdn/chunks/tiptap-Bqy-H6CT.js.map +1 -0
- package/dist/cdn/chunks/{useAliveFlag-C1pwLtPO.js → useAliveFlag-DrXxPV8V.js} +2 -2
- package/dist/cdn/chunks/{useAliveFlag-C1pwLtPO.js.map → useAliveFlag-DrXxPV8V.js.map} +1 -1
- package/dist/cdn/chunks/{useCloudI18n-D4gzxtqF.js → useCloudI18n-D0AoLV0a.js} +3 -3
- package/dist/cdn/chunks/{useCloudI18n-D4gzxtqF.js.map → useCloudI18n-D0AoLV0a.js.map} +1 -1
- package/dist/cdn/chunks/{useEditorCore-Dq5gdn5i.js → useEditorCore-BQeEwEQ9.js} +356 -361
- package/dist/cdn/chunks/{useEditorCore-Dq5gdn5i.js.map → useEditorCore-BQeEwEQ9.js.map} +1 -1
- package/dist/cdn/chunks/useEditorRoot-BFGRBGts.js +10 -0
- package/dist/cdn/chunks/{useEditorRoot-BY-amddA.js.map → useEditorRoot-BFGRBGts.js.map} +1 -1
- package/dist/cdn/chunks/{useI18n-DYb1SgLB.js → useI18n-DIhawILp.js} +3 -3
- package/dist/cdn/chunks/{useI18n-DYb1SgLB.js.map → useI18n-DIhawILp.js.map} +1 -1
- package/dist/cdn/chunks/{useMergeTag-D-SE_XN8.js → useMergeTag-lWo7So18.js} +4 -4
- package/dist/cdn/chunks/{useMergeTag-D-SE_XN8.js.map → useMergeTag-lWo7So18.js.map} +1 -1
- package/dist/cdn/chunks/{usePopoverPosition-CJZ6EkS4.js → usePopoverPosition-DkiTLnBm.js} +3 -3
- package/dist/cdn/chunks/{usePopoverPosition-CJZ6EkS4.js.map → usePopoverPosition-DkiTLnBm.js.map} +1 -1
- package/dist/cdn/chunks/{useScrollToBlock-D6gyIzT1.js → useScrollToBlock-KcSAuXKz.js} +3 -3
- package/dist/cdn/chunks/{useScrollToBlock-D6gyIzT1.js.map → useScrollToBlock-KcSAuXKz.js.map} +1 -1
- package/dist/cdn/editor.css +1 -1
- package/dist/cdn/editor.js +1036 -1002
- package/dist/cdn/editor.js.map +1 -1
- package/dist/{check-Cv96tY88.js → check-CTe6VejT.js} +1 -1
- package/dist/{chevron-down-BwEyjSjd.js → chevron-down-BBThVMu-.js} +1 -1
- package/dist/{chevron-up-C6Ye-Nzc.js → chevron-up-iECwf-Bc.js} +1 -1
- package/dist/{circle-alert-BLt_gkcU.js → circle-alert-Z_eeykrO.js} +1 -1
- package/dist/{clock-D-2BI0Co.js → clock-CEj1c29j.js} +1 -1
- package/dist/{cloud-DXFUA8H_.js → cloud-DwJ8ebNl.js} +2 -2
- package/dist/{createCloudRuntime-CWPQ7puE.js → createCloudRuntime-CdXQdl34.js} +6 -6
- package/dist/{createLucideIcon-DGRWivCX.js → createLucideIcon-DphAT3tw.js} +3 -3
- package/dist/{cdn/chunks/de-CYLWugqb.js → de-DbayqpK-.js} +2 -2
- package/dist/{dist-DQ_4a0hb.js → dist-9fjN9cuD.js} +2 -2
- package/dist/{dist-WE11SQGe.js → dist-BUpBA58N.js} +2 -2
- package/dist/{dist-DAR13YWM.js → dist-BdIwIlKz.js} +2 -2
- package/dist/{dist-Btz6cFCI.js → dist-BfcqryVg.js} +4 -4
- package/dist/{dist-q3Puexqv.js → dist-CaR5TLiM.js} +2 -2
- package/dist/{dist-CkSgS-K9.js → dist-CuuPnIMy.js} +3 -3
- package/dist/dist-CzMzshfS.js +5 -0
- package/dist/{dist-B1kLn1rs.js → dist-CzVIVbSa.js} +90 -85
- package/dist/{dist-BIFUEhwQ.js → dist-D2P8U3p6.js} +2 -2
- package/dist/{dist-BtPhkQ2u.js → dist-DLaIQ5H5.js} +12 -8
- package/dist/{dist-BG2cHdqw.js → dist-DSgmnQ-f.js} +2 -2
- package/dist/dist-DTVuNn8M.js +5 -0
- package/dist/{dist-CHp21juN.js → dist-DifptC-U.js} +2 -2
- package/dist/{dist-BpHkLruF.js → dist-gWM8H2hz.js} +4 -4
- package/dist/{dist-BUh4MT4D.js → dist-nmzPlqlz.js} +266 -176
- package/dist/{cdn/chunks/en-C3TM249M.js → en-l0ib5X0f.js} +2 -2
- package/dist/{es-D1SF4nCR.js → es-CMQ-5PJP.js} +2 -0
- package/dist/{extensions-BlYe3NFn.js → extensions-Bjsdx6Vm.js} +18 -18
- package/dist/{fr-CdLhJ7kw.js → fr-DNXmZWAq.js} +2 -0
- package/dist/{image-up-KRq0lcdU.js → image-up-W1INxCu8.js} +1 -1
- package/dist/{info-DbmE2JAo.js → info-5t4WYKfh.js} +1 -1
- package/dist/{keys-CAor2T5q.js → keys-BJtoezGU.js} +1 -1
- package/dist/{liquid.browser-B-rGrnrQ.js → liquid.browser-CJgDDvQz.js} +1 -1
- package/dist/{loader-circle-dSap9DfQ.js → loader-circle-DJCZ_JMY.js} +1 -1
- package/dist/{message-circle-qSKKLbac.js → message-circle-Biu6lHh_.js} +1 -1
- package/dist/{cdn/chunks/nl-BvsLoyKp.js → nl-BylRRHYJ.js} +2 -2
- package/dist/{pencil-DMP8vL2F.js → pencil-DkPlMca7.js} +1 -1
- package/dist/{preRenderCustomBlocks-BebjKtmw.js → preRenderCustomBlocks-2KyBJocY.js} +1 -1
- package/dist/{pt-BR-CAGS5YXp.js → pt-BR-BVoJhpie.js} +2 -0
- package/dist/{refresh-cw-WXtBeMva.js → refresh-cw-DHbpkkol.js} +1 -1
- package/dist/{runtime-dom.esm-bundler-CHEsXNQz.js → runtime-dom.esm-bundler-Co_SPqAz.js} +180 -166
- package/dist/{scan-line-BTrngVuN.js → scan-line-DojwGzjU.js} +1 -1
- package/dist/{send-CLa8Cxmh.js → send-c6ppcE9I.js} +1 -1
- package/dist/{shield-check-42WZrKQu.js → shield-check-F9T4ylNK.js} +1 -1
- package/dist/{sparkles-DcOb0umz.js → sparkles-D-0OiTZD.js} +1 -1
- package/dist/style.css +1 -1
- package/dist/templatical-editor.js +1083 -1049
- package/dist/{text-align-start-zoZhXJ2T.js → text-align-start-kEEtoRrD.js} +1 -1
- package/dist/{trash-2-Capv4cSE.js → trash-2-DRQzhY9R.js} +1 -1
- package/dist/{triangle-alert-CnJUGX-6.js → triangle-alert-Bt4-GU3t.js} +1 -1
- package/dist/{upload-Bc0ZTywl.js → upload-D2wtjvH8.js} +1 -1
- package/dist/{useAliveFlag-1yBub211.js → useAliveFlag-AFbwfHlJ.js} +1 -1
- package/dist/{useCloudI18n-Dwo7usTl.js → useCloudI18n-BA69BpQ_.js} +2 -2
- package/dist/{useEditorCore-CIjO_NM9.js → useEditorCore-Du9Vx-qr.js} +873 -878
- package/dist/{useEditorRoot-CUIzpMYc.js → useEditorRoot-Cdo8Vhxa.js} +2 -2
- package/dist/{useI18n-DT_DKupw.js → useI18n-B135ASaG.js} +2 -2
- package/dist/{useMergeTag-CcHQCcPN.js → useMergeTag-Cx36rtrt.js} +5 -5
- package/dist/{usePopoverPosition-DaHz1kqb.js → usePopoverPosition-DAOHr_iM.js} +2 -2
- package/dist/{useScrollToBlock-C2-9xCr7.js → useScrollToBlock-B0Qpjfa4.js} +3 -3
- package/dist/{vue.runtime.esm-bundler-CdH_W9qX.js → vue.runtime.esm-bundler-BhOUdXMi.js} +1244 -1204
- package/dist/{x-CvPZ3OAd.js → x-YiG-TUGN.js} +1 -1
- package/package.json +25 -25
- package/dist/cdn/chunks/NumberWithSuffix-CWvM_I3T.js.map +0 -1
- package/dist/cdn/chunks/ca-DY0AYOLG.js.map +0 -1
- package/dist/cdn/chunks/draggable-BLMjz0GK.js.map +0 -1
- package/dist/cdn/chunks/en-BZlZVGwM.js +0 -2
- package/dist/cdn/chunks/en-C3TM249M.js.map +0 -1
- package/dist/cdn/chunks/es-D1SF4nCR.js.map +0 -1
- package/dist/cdn/chunks/fr-CdLhJ7kw.js.map +0 -1
- package/dist/cdn/chunks/icons-C2kP4vOJ.js.map +0 -1
- package/dist/cdn/chunks/nl-BvsLoyKp.js.map +0 -1
- package/dist/cdn/chunks/pt-BR-CAGS5YXp.js.map +0 -1
- package/dist/cdn/chunks/src-B_QJduQD.js.map +0 -1
- package/dist/cdn/chunks/src-CnQgwcsc.js.map +0 -1
- package/dist/cdn/chunks/tiptap-DOw5Yb4H.js.map +0 -1
- package/dist/cdn/chunks/useEditorRoot-BY-amddA.js +0 -10
- package/dist/dist-CCfNhI54.js +0 -5
- package/dist/dist-CMcNDUcw.js +0 -5
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { F as e, H as t, N as n, S as r, at as i, b as a, ct as o, f as s, g as c, m as l, p as u, u as d, ut as f } from "./draggable-
|
|
2
|
-
import { t as p } from "./useI18n-
|
|
1
|
+
import { F as e, H as t, N as n, S as r, at as i, b as a, ct as o, f as s, g as c, m as l, p as u, u as d, ut as f } from "./draggable-D2vo-aQI.js";
|
|
2
|
+
import { t as p } from "./useI18n-DIhawILp.js";
|
|
3
3
|
import { p as m } from "./styleConstants-C_YAPdQS.js";
|
|
4
|
-
import { t as h } from "./ColorPicker-
|
|
5
|
-
import { i as g, n as _, r as v, t as y } from "./
|
|
4
|
+
import { t as h } from "./ColorPicker-Ww4xHHMI.js";
|
|
5
|
+
import { i as g, n as _, r as v, t as y } from "./FieldRow-CbcpsxZ4.js";
|
|
6
6
|
//#region src/components/toolbar/CountdownToolbar.vue?vue&type=script&setup=true&lang.ts
|
|
7
7
|
var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid-cols-2 tpl:gap-2" }, w = ["value"], T = { value: "" }, E = ["value"], D = { class: "tpl:grid tpl:grid-cols-2 tpl:gap-3" }, O = { class: "tpl:grid tpl:grid-cols-2 tpl:gap-3" }, k = { class: "tpl:grid tpl:grid-cols-2 tpl:gap-2" }, A = [
|
|
8
8
|
"value",
|
|
@@ -60,7 +60,7 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
60
60
|
P("update", { [e]: t });
|
|
61
61
|
}
|
|
62
62
|
return (s, p) => (n(), c(d, null, [
|
|
63
|
-
a(
|
|
63
|
+
a(y, { label: i(F).countdown.targetDate }, {
|
|
64
64
|
default: t(() => [u("input", {
|
|
65
65
|
type: "datetime-local",
|
|
66
66
|
class: o(i(m)),
|
|
@@ -69,7 +69,7 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
69
69
|
}, null, 42, b)]),
|
|
70
70
|
_: 1
|
|
71
71
|
}, 8, ["label"]),
|
|
72
|
-
a(
|
|
72
|
+
a(y, { label: i(F).countdown.timezone }, {
|
|
73
73
|
default: t(() => [u("select", {
|
|
74
74
|
class: o(i(m)),
|
|
75
75
|
value: r.block.timezone,
|
|
@@ -80,7 +80,7 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
80
80
|
}, f(e), 9, S)), 64))], 42, x)]),
|
|
81
81
|
_: 1
|
|
82
82
|
}, 8, ["label"]),
|
|
83
|
-
a(
|
|
83
|
+
a(y, { label: i(F).countdown.display }, {
|
|
84
84
|
default: t(() => [u("div", C, [(n(!0), c(d, null, e(z.value, (e) => (n(), l(g, {
|
|
85
85
|
key: e.unit,
|
|
86
86
|
class: "tpl:text-[12px] tpl:text-[var(--tpl-text)]",
|
|
@@ -94,7 +94,7 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
94
94
|
]))), 128))])]),
|
|
95
95
|
_: 1
|
|
96
96
|
}, 8, ["label"]),
|
|
97
|
-
a(
|
|
97
|
+
a(y, { label: i(F).countdown.separator }, {
|
|
98
98
|
default: t(() => [a(v, {
|
|
99
99
|
options: L,
|
|
100
100
|
"model-value": r.block.separator,
|
|
@@ -102,7 +102,7 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
102
102
|
}, null, 8, ["model-value"])]),
|
|
103
103
|
_: 1
|
|
104
104
|
}, 8, ["label"]),
|
|
105
|
-
a(
|
|
105
|
+
a(y, { label: i(F).countdown.fontFamily }, {
|
|
106
106
|
default: t(() => [u("select", {
|
|
107
107
|
class: o(i(m)),
|
|
108
108
|
value: r.block.fontFamily || "",
|
|
@@ -113,8 +113,8 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
113
113
|
}, f(e.label), 9, E))), 128))], 42, w)]),
|
|
114
114
|
_: 1
|
|
115
115
|
}, 8, ["label"]),
|
|
116
|
-
u("div", D, [a(
|
|
117
|
-
default: t(() => [a(
|
|
116
|
+
u("div", D, [a(y, { label: i(F).countdown.digitFontSize }, {
|
|
117
|
+
default: t(() => [a(_, {
|
|
118
118
|
"model-value": r.block.digitFontSize,
|
|
119
119
|
min: 12,
|
|
120
120
|
max: 72,
|
|
@@ -122,8 +122,8 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
122
122
|
"onUpdate:modelValue": p[4] ||= (e) => B("digitFontSize", e)
|
|
123
123
|
}, null, 8, ["model-value"])]),
|
|
124
124
|
_: 1
|
|
125
|
-
}, 8, ["label"]), a(
|
|
126
|
-
default: t(() => [a(
|
|
125
|
+
}, 8, ["label"]), a(y, { label: i(F).countdown.labelFontSize }, {
|
|
126
|
+
default: t(() => [a(_, {
|
|
127
127
|
"model-value": r.block.labelFontSize,
|
|
128
128
|
min: 8,
|
|
129
129
|
max: 24,
|
|
@@ -132,27 +132,27 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
132
132
|
}, null, 8, ["model-value"])]),
|
|
133
133
|
_: 1
|
|
134
134
|
}, 8, ["label"])]),
|
|
135
|
-
u("div", O, [a(
|
|
135
|
+
u("div", O, [a(y, { label: i(F).countdown.digitColor }, {
|
|
136
136
|
default: t(() => [a(h, {
|
|
137
137
|
"model-value": r.block.digitColor,
|
|
138
138
|
"onUpdate:modelValue": p[6] ||= (e) => B("digitColor", e)
|
|
139
139
|
}, null, 8, ["model-value"])]),
|
|
140
140
|
_: 1
|
|
141
|
-
}, 8, ["label"]), a(
|
|
141
|
+
}, 8, ["label"]), a(y, { label: i(F).countdown.labelColor }, {
|
|
142
142
|
default: t(() => [a(h, {
|
|
143
143
|
"model-value": r.block.labelColor,
|
|
144
144
|
"onUpdate:modelValue": p[7] ||= (e) => B("labelColor", e)
|
|
145
145
|
}, null, 8, ["model-value"])]),
|
|
146
146
|
_: 1
|
|
147
147
|
}, 8, ["label"])]),
|
|
148
|
-
a(
|
|
148
|
+
a(y, { label: i(F).countdown.background }, {
|
|
149
149
|
default: t(() => [a(h, {
|
|
150
150
|
"model-value": r.block.backgroundColor,
|
|
151
151
|
"onUpdate:modelValue": p[8] ||= (e) => B("backgroundColor", e)
|
|
152
152
|
}, null, 8, ["model-value"])]),
|
|
153
153
|
_: 1
|
|
154
154
|
}, 8, ["label"]),
|
|
155
|
-
a(
|
|
155
|
+
a(y, { label: i(F).countdown.labels }, {
|
|
156
156
|
default: t(() => [u("div", k, [(n(!0), c(d, null, e(z.value, (e) => (n(), c("input", {
|
|
157
157
|
key: e.unit,
|
|
158
158
|
type: "text",
|
|
@@ -163,7 +163,7 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
163
163
|
}, null, 42, A))), 128))])]),
|
|
164
164
|
_: 1
|
|
165
165
|
}, 8, ["label"]),
|
|
166
|
-
a(
|
|
166
|
+
a(y, { label: i(F).countdown.expiry }, {
|
|
167
167
|
default: t(() => [u("input", {
|
|
168
168
|
type: "text",
|
|
169
169
|
class: o(i(m)),
|
|
@@ -173,7 +173,7 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
173
173
|
}, null, 42, j)]),
|
|
174
174
|
_: 1
|
|
175
175
|
}, 8, ["label"]),
|
|
176
|
-
a(
|
|
176
|
+
a(y, { label: i(F).countdown.expiredImageUrl }, {
|
|
177
177
|
default: t(() => [u("input", {
|
|
178
178
|
type: "url",
|
|
179
179
|
class: o(i(m)),
|
|
@@ -195,4 +195,4 @@ var b = ["value"], x = ["value"], S = ["value"], C = { class: "tpl:grid tpl:grid
|
|
|
195
195
|
//#endregion
|
|
196
196
|
export { N as default };
|
|
197
197
|
|
|
198
|
-
//# sourceMappingURL=CountdownToolbar-
|
|
198
|
+
//# sourceMappingURL=CountdownToolbar-CO6xLgYc.js.map
|
package/dist/cdn/chunks/{CountdownToolbar-B1L0IK1T.js.map → CountdownToolbar-CO6xLgYc.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CountdownToolbar-B1L0IK1T.js","names":[],"sources":["../../../src/components/toolbar/CountdownToolbar.vue","../../../src/components/toolbar/CountdownToolbar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport ColorPicker from \"../ColorPicker.vue\";\nimport SlidingPillSelect from \"../SlidingPillSelect.vue\";\nimport FieldRow from \"./FieldRow.vue\";\nimport ToggleSwitch from \"../ToggleSwitch.vue\";\nimport NumberWithSuffix from \"./NumberWithSuffix.vue\";\nimport { useI18n } from \"../../composables/useI18n\";\nimport { inputClass } from \"../../constants/styleConstants\";\nimport type { CountdownBlock } from \"@templatical/types\";\nimport { computed } from \"vue\";\n\ndefineProps<{\n block: CountdownBlock;\n fontFamilies: Array<{ value: string; label: string }>;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update\", updates: Partial<CountdownBlock>): void;\n}>();\n\nconst { t } = useI18n();\n\nconst TIMEZONES = [\n \"UTC\",\n \"America/New_York\",\n \"America/Chicago\",\n \"America/Denver\",\n \"America/Los_Angeles\",\n \"Europe/London\",\n \"Europe/Berlin\",\n \"Europe/Paris\",\n \"Europe/Moscow\",\n \"Asia/Dubai\",\n \"Asia/Kolkata\",\n \"Asia/Shanghai\",\n \"Asia/Tokyo\",\n \"Australia/Sydney\",\n \"Pacific/Auckland\",\n];\n\nconst SEPARATORS = [\n { value: \":\", label: \":\" },\n { value: \"-\", label: \"-\" },\n { value: \" \", label: \"␣\" },\n];\n\ntype UnitKey = \"Days\" | \"Hours\" | \"Minutes\" | \"Seconds\";\nconst UNITS: UnitKey[] = [\"Days\", \"Hours\", \"Minutes\", \"Seconds\"];\n\nconst unitItems = computed(() =>\n UNITS.map((unit) => ({\n unit,\n showKey: `show${unit}` as const,\n labelKey: `label${unit}` as const,\n translationKey: unit.toLowerCase() as\n \"days\" | \"hours\" | \"minutes\" | \"seconds\",\n })),\n);\n\nfunction updateField(field: keyof CountdownBlock, value: unknown): void {\n emit(\"update\", { [field]: value } as Partial<CountdownBlock>);\n}\n</script>\n\n<template>\n <FieldRow :label=\"t.countdown.targetDate\">\n <input\n type=\"datetime-local\"\n :class=\"inputClass\"\n :value=\"block.targetDate\"\n @input=\"\n updateField('targetDate', ($event.target as HTMLInputElement).value)\n \"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.timezone\">\n <select\n :class=\"inputClass\"\n :value=\"block.timezone\"\n @change=\"\n updateField('timezone', ($event.target as HTMLSelectElement).value)\n \"\n >\n <option v-for=\"tz in TIMEZONES\" :key=\"tz\" :value=\"tz\">{{ tz }}</option>\n </select>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.display\">\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-2\">\n <ToggleSwitch\n v-for=\"item in unitItems\"\n :key=\"item.unit\"\n class=\"tpl:text-[12px] tpl:text-[var(--tpl-text)]\"\n :model-value=\"block[item.showKey]\"\n :label=\"t.countdown[item.translationKey]\"\n @update:model-value=\"updateField(item.showKey, $event)\"\n />\n </div>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.separator\">\n <SlidingPillSelect\n :options=\"SEPARATORS\"\n :model-value=\"block.separator\"\n @update:model-value=\"updateField('separator', $event)\"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.fontFamily\">\n <select\n :class=\"inputClass\"\n :value=\"block.fontFamily || ''\"\n @change=\"\n updateField(\n 'fontFamily',\n ($event.target as HTMLSelectElement).value || undefined,\n )\n \"\n >\n <option value=\"\">{{ t.countdown.inheritFont }}</option>\n <option\n v-for=\"font in fontFamilies\"\n :key=\"font.value\"\n :value=\"font.value\"\n >\n {{ font.label }}\n </option>\n </select>\n </FieldRow>\n\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-3\">\n <FieldRow :label=\"t.countdown.digitFontSize\">\n <NumberWithSuffix\n :model-value=\"block.digitFontSize\"\n :min=\"12\"\n :max=\"72\"\n suffix=\"px\"\n @update:model-value=\"updateField('digitFontSize', $event)\"\n />\n </FieldRow>\n <FieldRow :label=\"t.countdown.labelFontSize\">\n <NumberWithSuffix\n :model-value=\"block.labelFontSize\"\n :min=\"8\"\n :max=\"24\"\n suffix=\"px\"\n @update:model-value=\"updateField('labelFontSize', $event)\"\n />\n </FieldRow>\n </div>\n\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-3\">\n <FieldRow :label=\"t.countdown.digitColor\">\n <ColorPicker\n :model-value=\"block.digitColor\"\n @update:model-value=\"updateField('digitColor', $event)\"\n />\n </FieldRow>\n <FieldRow :label=\"t.countdown.labelColor\">\n <ColorPicker\n :model-value=\"block.labelColor\"\n @update:model-value=\"updateField('labelColor', $event)\"\n />\n </FieldRow>\n </div>\n\n <FieldRow :label=\"t.countdown.background\">\n <ColorPicker\n :model-value=\"block.backgroundColor\"\n @update:model-value=\"updateField('backgroundColor', $event)\"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.labels\">\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-2\">\n <input\n v-for=\"item in unitItems\"\n :key=\"item.unit\"\n type=\"text\"\n :class=\"inputClass\"\n :value=\"block[item.labelKey]\"\n :placeholder=\"t.countdown[item.translationKey]\"\n @input=\"\n updateField(item.labelKey, ($event.target as HTMLInputElement).value)\n \"\n />\n </div>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.expiry\">\n <input\n type=\"text\"\n :class=\"inputClass\"\n :value=\"block.expiredMessage\"\n :placeholder=\"t.countdown.expiredMessagePlaceholder\"\n @input=\"\n updateField('expiredMessage', ($event.target as HTMLInputElement).value)\n \"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.expiredImageUrl\">\n <input\n type=\"url\"\n :class=\"inputClass\"\n :value=\"block.expiredImageUrl\"\n placeholder=\"https://...\"\n @input=\"\n updateField(\n 'expiredImageUrl',\n ($event.target as HTMLInputElement).value,\n )\n \"\n />\n </FieldRow>\n\n <ToggleSwitch\n class=\"tpl:mb-3.5 tpl:text-[12px] tpl:text-[var(--tpl-text)]\"\n :model-value=\"block.hideOnExpiry\"\n :label=\"t.countdown.hideOnExpiry\"\n @update:model-value=\"updateField('hideOnExpiry', $event)\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport ColorPicker from \"../ColorPicker.vue\";\nimport SlidingPillSelect from \"../SlidingPillSelect.vue\";\nimport FieldRow from \"./FieldRow.vue\";\nimport ToggleSwitch from \"../ToggleSwitch.vue\";\nimport NumberWithSuffix from \"./NumberWithSuffix.vue\";\nimport { useI18n } from \"../../composables/useI18n\";\nimport { inputClass } from \"../../constants/styleConstants\";\nimport type { CountdownBlock } from \"@templatical/types\";\nimport { computed } from \"vue\";\n\ndefineProps<{\n block: CountdownBlock;\n fontFamilies: Array<{ value: string; label: string }>;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update\", updates: Partial<CountdownBlock>): void;\n}>();\n\nconst { t } = useI18n();\n\nconst TIMEZONES = [\n \"UTC\",\n \"America/New_York\",\n \"America/Chicago\",\n \"America/Denver\",\n \"America/Los_Angeles\",\n \"Europe/London\",\n \"Europe/Berlin\",\n \"Europe/Paris\",\n \"Europe/Moscow\",\n \"Asia/Dubai\",\n \"Asia/Kolkata\",\n \"Asia/Shanghai\",\n \"Asia/Tokyo\",\n \"Australia/Sydney\",\n \"Pacific/Auckland\",\n];\n\nconst SEPARATORS = [\n { value: \":\", label: \":\" },\n { value: \"-\", label: \"-\" },\n { value: \" \", label: \"␣\" },\n];\n\ntype UnitKey = \"Days\" | \"Hours\" | \"Minutes\" | \"Seconds\";\nconst UNITS: UnitKey[] = [\"Days\", \"Hours\", \"Minutes\", \"Seconds\"];\n\nconst unitItems = computed(() =>\n UNITS.map((unit) => ({\n unit,\n showKey: `show${unit}` as const,\n labelKey: `label${unit}` as const,\n translationKey: unit.toLowerCase() as\n \"days\" | \"hours\" | \"minutes\" | \"seconds\",\n })),\n);\n\nfunction updateField(field: keyof CountdownBlock, value: unknown): void {\n emit(\"update\", { [field]: value } as Partial<CountdownBlock>);\n}\n</script>\n\n<template>\n <FieldRow :label=\"t.countdown.targetDate\">\n <input\n type=\"datetime-local\"\n :class=\"inputClass\"\n :value=\"block.targetDate\"\n @input=\"\n updateField('targetDate', ($event.target as HTMLInputElement).value)\n \"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.timezone\">\n <select\n :class=\"inputClass\"\n :value=\"block.timezone\"\n @change=\"\n updateField('timezone', ($event.target as HTMLSelectElement).value)\n \"\n >\n <option v-for=\"tz in TIMEZONES\" :key=\"tz\" :value=\"tz\">{{ tz }}</option>\n </select>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.display\">\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-2\">\n <ToggleSwitch\n v-for=\"item in unitItems\"\n :key=\"item.unit\"\n class=\"tpl:text-[12px] tpl:text-[var(--tpl-text)]\"\n :model-value=\"block[item.showKey]\"\n :label=\"t.countdown[item.translationKey]\"\n @update:model-value=\"updateField(item.showKey, $event)\"\n />\n </div>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.separator\">\n <SlidingPillSelect\n :options=\"SEPARATORS\"\n :model-value=\"block.separator\"\n @update:model-value=\"updateField('separator', $event)\"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.fontFamily\">\n <select\n :class=\"inputClass\"\n :value=\"block.fontFamily || ''\"\n @change=\"\n updateField(\n 'fontFamily',\n ($event.target as HTMLSelectElement).value || undefined,\n )\n \"\n >\n <option value=\"\">{{ t.countdown.inheritFont }}</option>\n <option\n v-for=\"font in fontFamilies\"\n :key=\"font.value\"\n :value=\"font.value\"\n >\n {{ font.label }}\n </option>\n </select>\n </FieldRow>\n\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-3\">\n <FieldRow :label=\"t.countdown.digitFontSize\">\n <NumberWithSuffix\n :model-value=\"block.digitFontSize\"\n :min=\"12\"\n :max=\"72\"\n suffix=\"px\"\n @update:model-value=\"updateField('digitFontSize', $event)\"\n />\n </FieldRow>\n <FieldRow :label=\"t.countdown.labelFontSize\">\n <NumberWithSuffix\n :model-value=\"block.labelFontSize\"\n :min=\"8\"\n :max=\"24\"\n suffix=\"px\"\n @update:model-value=\"updateField('labelFontSize', $event)\"\n />\n </FieldRow>\n </div>\n\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-3\">\n <FieldRow :label=\"t.countdown.digitColor\">\n <ColorPicker\n :model-value=\"block.digitColor\"\n @update:model-value=\"updateField('digitColor', $event)\"\n />\n </FieldRow>\n <FieldRow :label=\"t.countdown.labelColor\">\n <ColorPicker\n :model-value=\"block.labelColor\"\n @update:model-value=\"updateField('labelColor', $event)\"\n />\n </FieldRow>\n </div>\n\n <FieldRow :label=\"t.countdown.background\">\n <ColorPicker\n :model-value=\"block.backgroundColor\"\n @update:model-value=\"updateField('backgroundColor', $event)\"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.labels\">\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-2\">\n <input\n v-for=\"item in unitItems\"\n :key=\"item.unit\"\n type=\"text\"\n :class=\"inputClass\"\n :value=\"block[item.labelKey]\"\n :placeholder=\"t.countdown[item.translationKey]\"\n @input=\"\n updateField(item.labelKey, ($event.target as HTMLInputElement).value)\n \"\n />\n </div>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.expiry\">\n <input\n type=\"text\"\n :class=\"inputClass\"\n :value=\"block.expiredMessage\"\n :placeholder=\"t.countdown.expiredMessagePlaceholder\"\n @input=\"\n updateField('expiredMessage', ($event.target as HTMLInputElement).value)\n \"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.expiredImageUrl\">\n <input\n type=\"url\"\n :class=\"inputClass\"\n :value=\"block.expiredImageUrl\"\n placeholder=\"https://...\"\n @input=\"\n updateField(\n 'expiredImageUrl',\n ($event.target as HTMLInputElement).value,\n )\n \"\n />\n </FieldRow>\n\n <ToggleSwitch\n class=\"tpl:mb-3.5 tpl:text-[12px] tpl:text-[var(--tpl-text)]\"\n :model-value=\"block.hideOnExpiry\"\n :label=\"t.countdown.hideOnExpiry\"\n @update:model-value=\"updateField('hideOnExpiry', $event)\"\n />\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CountdownToolbar-CO6xLgYc.js","names":[],"sources":["../../../src/components/toolbar/CountdownToolbar.vue","../../../src/components/toolbar/CountdownToolbar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport ColorPicker from \"../ColorPicker.vue\";\nimport SlidingPillSelect from \"../SlidingPillSelect.vue\";\nimport FieldRow from \"./FieldRow.vue\";\nimport ToggleSwitch from \"../ToggleSwitch.vue\";\nimport NumberWithSuffix from \"./NumberWithSuffix.vue\";\nimport { useI18n } from \"../../composables/useI18n\";\nimport { inputClass } from \"../../constants/styleConstants\";\nimport type { CountdownBlock } from \"@templatical/types\";\nimport { computed } from \"vue\";\n\ndefineProps<{\n block: CountdownBlock;\n fontFamilies: Array<{ value: string; label: string }>;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update\", updates: Partial<CountdownBlock>): void;\n}>();\n\nconst { t } = useI18n();\n\nconst TIMEZONES = [\n \"UTC\",\n \"America/New_York\",\n \"America/Chicago\",\n \"America/Denver\",\n \"America/Los_Angeles\",\n \"Europe/London\",\n \"Europe/Berlin\",\n \"Europe/Paris\",\n \"Europe/Moscow\",\n \"Asia/Dubai\",\n \"Asia/Kolkata\",\n \"Asia/Shanghai\",\n \"Asia/Tokyo\",\n \"Australia/Sydney\",\n \"Pacific/Auckland\",\n];\n\nconst SEPARATORS = [\n { value: \":\", label: \":\" },\n { value: \"-\", label: \"-\" },\n { value: \" \", label: \"␣\" },\n];\n\ntype UnitKey = \"Days\" | \"Hours\" | \"Minutes\" | \"Seconds\";\nconst UNITS: UnitKey[] = [\"Days\", \"Hours\", \"Minutes\", \"Seconds\"];\n\nconst unitItems = computed(() =>\n UNITS.map((unit) => ({\n unit,\n showKey: `show${unit}` as const,\n labelKey: `label${unit}` as const,\n translationKey: unit.toLowerCase() as\n \"days\" | \"hours\" | \"minutes\" | \"seconds\",\n })),\n);\n\nfunction updateField(field: keyof CountdownBlock, value: unknown): void {\n emit(\"update\", { [field]: value } as Partial<CountdownBlock>);\n}\n</script>\n\n<template>\n <FieldRow :label=\"t.countdown.targetDate\">\n <input\n type=\"datetime-local\"\n :class=\"inputClass\"\n :value=\"block.targetDate\"\n @input=\"\n updateField('targetDate', ($event.target as HTMLInputElement).value)\n \"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.timezone\">\n <select\n :class=\"inputClass\"\n :value=\"block.timezone\"\n @change=\"\n updateField('timezone', ($event.target as HTMLSelectElement).value)\n \"\n >\n <option v-for=\"tz in TIMEZONES\" :key=\"tz\" :value=\"tz\">{{ tz }}</option>\n </select>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.display\">\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-2\">\n <ToggleSwitch\n v-for=\"item in unitItems\"\n :key=\"item.unit\"\n class=\"tpl:text-[12px] tpl:text-[var(--tpl-text)]\"\n :model-value=\"block[item.showKey]\"\n :label=\"t.countdown[item.translationKey]\"\n @update:model-value=\"updateField(item.showKey, $event)\"\n />\n </div>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.separator\">\n <SlidingPillSelect\n :options=\"SEPARATORS\"\n :model-value=\"block.separator\"\n @update:model-value=\"updateField('separator', $event)\"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.fontFamily\">\n <select\n :class=\"inputClass\"\n :value=\"block.fontFamily || ''\"\n @change=\"\n updateField(\n 'fontFamily',\n ($event.target as HTMLSelectElement).value || undefined,\n )\n \"\n >\n <option value=\"\">{{ t.countdown.inheritFont }}</option>\n <option\n v-for=\"font in fontFamilies\"\n :key=\"font.value\"\n :value=\"font.value\"\n >\n {{ font.label }}\n </option>\n </select>\n </FieldRow>\n\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-3\">\n <FieldRow :label=\"t.countdown.digitFontSize\">\n <NumberWithSuffix\n :model-value=\"block.digitFontSize\"\n :min=\"12\"\n :max=\"72\"\n suffix=\"px\"\n @update:model-value=\"updateField('digitFontSize', $event)\"\n />\n </FieldRow>\n <FieldRow :label=\"t.countdown.labelFontSize\">\n <NumberWithSuffix\n :model-value=\"block.labelFontSize\"\n :min=\"8\"\n :max=\"24\"\n suffix=\"px\"\n @update:model-value=\"updateField('labelFontSize', $event)\"\n />\n </FieldRow>\n </div>\n\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-3\">\n <FieldRow :label=\"t.countdown.digitColor\">\n <ColorPicker\n :model-value=\"block.digitColor\"\n @update:model-value=\"updateField('digitColor', $event)\"\n />\n </FieldRow>\n <FieldRow :label=\"t.countdown.labelColor\">\n <ColorPicker\n :model-value=\"block.labelColor\"\n @update:model-value=\"updateField('labelColor', $event)\"\n />\n </FieldRow>\n </div>\n\n <FieldRow :label=\"t.countdown.background\">\n <ColorPicker\n :model-value=\"block.backgroundColor\"\n @update:model-value=\"updateField('backgroundColor', $event)\"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.labels\">\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-2\">\n <input\n v-for=\"item in unitItems\"\n :key=\"item.unit\"\n type=\"text\"\n :class=\"inputClass\"\n :value=\"block[item.labelKey]\"\n :placeholder=\"t.countdown[item.translationKey]\"\n @input=\"\n updateField(item.labelKey, ($event.target as HTMLInputElement).value)\n \"\n />\n </div>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.expiry\">\n <input\n type=\"text\"\n :class=\"inputClass\"\n :value=\"block.expiredMessage\"\n :placeholder=\"t.countdown.expiredMessagePlaceholder\"\n @input=\"\n updateField('expiredMessage', ($event.target as HTMLInputElement).value)\n \"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.expiredImageUrl\">\n <input\n type=\"url\"\n :class=\"inputClass\"\n :value=\"block.expiredImageUrl\"\n placeholder=\"https://...\"\n @input=\"\n updateField(\n 'expiredImageUrl',\n ($event.target as HTMLInputElement).value,\n )\n \"\n />\n </FieldRow>\n\n <ToggleSwitch\n class=\"tpl:mb-3.5 tpl:text-[12px] tpl:text-[var(--tpl-text)]\"\n :model-value=\"block.hideOnExpiry\"\n :label=\"t.countdown.hideOnExpiry\"\n @update:model-value=\"updateField('hideOnExpiry', $event)\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport ColorPicker from \"../ColorPicker.vue\";\nimport SlidingPillSelect from \"../SlidingPillSelect.vue\";\nimport FieldRow from \"./FieldRow.vue\";\nimport ToggleSwitch from \"../ToggleSwitch.vue\";\nimport NumberWithSuffix from \"./NumberWithSuffix.vue\";\nimport { useI18n } from \"../../composables/useI18n\";\nimport { inputClass } from \"../../constants/styleConstants\";\nimport type { CountdownBlock } from \"@templatical/types\";\nimport { computed } from \"vue\";\n\ndefineProps<{\n block: CountdownBlock;\n fontFamilies: Array<{ value: string; label: string }>;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update\", updates: Partial<CountdownBlock>): void;\n}>();\n\nconst { t } = useI18n();\n\nconst TIMEZONES = [\n \"UTC\",\n \"America/New_York\",\n \"America/Chicago\",\n \"America/Denver\",\n \"America/Los_Angeles\",\n \"Europe/London\",\n \"Europe/Berlin\",\n \"Europe/Paris\",\n \"Europe/Moscow\",\n \"Asia/Dubai\",\n \"Asia/Kolkata\",\n \"Asia/Shanghai\",\n \"Asia/Tokyo\",\n \"Australia/Sydney\",\n \"Pacific/Auckland\",\n];\n\nconst SEPARATORS = [\n { value: \":\", label: \":\" },\n { value: \"-\", label: \"-\" },\n { value: \" \", label: \"␣\" },\n];\n\ntype UnitKey = \"Days\" | \"Hours\" | \"Minutes\" | \"Seconds\";\nconst UNITS: UnitKey[] = [\"Days\", \"Hours\", \"Minutes\", \"Seconds\"];\n\nconst unitItems = computed(() =>\n UNITS.map((unit) => ({\n unit,\n showKey: `show${unit}` as const,\n labelKey: `label${unit}` as const,\n translationKey: unit.toLowerCase() as\n \"days\" | \"hours\" | \"minutes\" | \"seconds\",\n })),\n);\n\nfunction updateField(field: keyof CountdownBlock, value: unknown): void {\n emit(\"update\", { [field]: value } as Partial<CountdownBlock>);\n}\n</script>\n\n<template>\n <FieldRow :label=\"t.countdown.targetDate\">\n <input\n type=\"datetime-local\"\n :class=\"inputClass\"\n :value=\"block.targetDate\"\n @input=\"\n updateField('targetDate', ($event.target as HTMLInputElement).value)\n \"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.timezone\">\n <select\n :class=\"inputClass\"\n :value=\"block.timezone\"\n @change=\"\n updateField('timezone', ($event.target as HTMLSelectElement).value)\n \"\n >\n <option v-for=\"tz in TIMEZONES\" :key=\"tz\" :value=\"tz\">{{ tz }}</option>\n </select>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.display\">\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-2\">\n <ToggleSwitch\n v-for=\"item in unitItems\"\n :key=\"item.unit\"\n class=\"tpl:text-[12px] tpl:text-[var(--tpl-text)]\"\n :model-value=\"block[item.showKey]\"\n :label=\"t.countdown[item.translationKey]\"\n @update:model-value=\"updateField(item.showKey, $event)\"\n />\n </div>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.separator\">\n <SlidingPillSelect\n :options=\"SEPARATORS\"\n :model-value=\"block.separator\"\n @update:model-value=\"updateField('separator', $event)\"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.fontFamily\">\n <select\n :class=\"inputClass\"\n :value=\"block.fontFamily || ''\"\n @change=\"\n updateField(\n 'fontFamily',\n ($event.target as HTMLSelectElement).value || undefined,\n )\n \"\n >\n <option value=\"\">{{ t.countdown.inheritFont }}</option>\n <option\n v-for=\"font in fontFamilies\"\n :key=\"font.value\"\n :value=\"font.value\"\n >\n {{ font.label }}\n </option>\n </select>\n </FieldRow>\n\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-3\">\n <FieldRow :label=\"t.countdown.digitFontSize\">\n <NumberWithSuffix\n :model-value=\"block.digitFontSize\"\n :min=\"12\"\n :max=\"72\"\n suffix=\"px\"\n @update:model-value=\"updateField('digitFontSize', $event)\"\n />\n </FieldRow>\n <FieldRow :label=\"t.countdown.labelFontSize\">\n <NumberWithSuffix\n :model-value=\"block.labelFontSize\"\n :min=\"8\"\n :max=\"24\"\n suffix=\"px\"\n @update:model-value=\"updateField('labelFontSize', $event)\"\n />\n </FieldRow>\n </div>\n\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-3\">\n <FieldRow :label=\"t.countdown.digitColor\">\n <ColorPicker\n :model-value=\"block.digitColor\"\n @update:model-value=\"updateField('digitColor', $event)\"\n />\n </FieldRow>\n <FieldRow :label=\"t.countdown.labelColor\">\n <ColorPicker\n :model-value=\"block.labelColor\"\n @update:model-value=\"updateField('labelColor', $event)\"\n />\n </FieldRow>\n </div>\n\n <FieldRow :label=\"t.countdown.background\">\n <ColorPicker\n :model-value=\"block.backgroundColor\"\n @update:model-value=\"updateField('backgroundColor', $event)\"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.labels\">\n <div class=\"tpl:grid tpl:grid-cols-2 tpl:gap-2\">\n <input\n v-for=\"item in unitItems\"\n :key=\"item.unit\"\n type=\"text\"\n :class=\"inputClass\"\n :value=\"block[item.labelKey]\"\n :placeholder=\"t.countdown[item.translationKey]\"\n @input=\"\n updateField(item.labelKey, ($event.target as HTMLInputElement).value)\n \"\n />\n </div>\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.expiry\">\n <input\n type=\"text\"\n :class=\"inputClass\"\n :value=\"block.expiredMessage\"\n :placeholder=\"t.countdown.expiredMessagePlaceholder\"\n @input=\"\n updateField('expiredMessage', ($event.target as HTMLInputElement).value)\n \"\n />\n </FieldRow>\n\n <FieldRow :label=\"t.countdown.expiredImageUrl\">\n <input\n type=\"url\"\n :class=\"inputClass\"\n :value=\"block.expiredImageUrl\"\n placeholder=\"https://...\"\n @input=\"\n updateField(\n 'expiredImageUrl',\n ($event.target as HTMLInputElement).value,\n )\n \"\n />\n </FieldRow>\n\n <ToggleSwitch\n class=\"tpl:mb-3.5 tpl:text-[12px] tpl:text-[var(--tpl-text)]\"\n :model-value=\"block.hideOnExpiry\"\n :label=\"t.countdown.hideOnExpiry\"\n @update:model-value=\"updateField('hideOnExpiry', $event)\"\n />\n</template>\n"],"mappings":"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"}
|
package/dist/cdn/chunks/{DesignReferenceSidebar-BwsfOFsc.js → DesignReferenceSidebar-DRGqm33h.js}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { A as e, B as t, H as n, N as r, Q as i, S as a, U as ee, at as o, b as s, ct as te, f as ne, g as c, h as l, lt as u, m as re, n as ie, o as ae, p as d, ut as f, y as p } from "./draggable-
|
|
2
|
-
import { W as m, h as oe, i as se } from "./keys-
|
|
1
|
+
import { A as e, B as t, H as n, N as r, Q as i, S as a, U as ee, at as o, b as s, ct as te, f as ne, g as c, h as l, lt as u, m as re, n as ie, o as ae, p as d, ut as f, y as p } from "./draggable-D2vo-aQI.js";
|
|
2
|
+
import { W as m, h as oe, i as se } from "./keys-BJ770Mwm.js";
|
|
3
3
|
import "./timeouts-DHPZQ0G3.js";
|
|
4
|
-
import { Mt as ce, St as le, n as h, pt as g, s as ue, xt as _ } from "./icons-
|
|
5
|
-
import { t as de } from "./LoadingTrack-
|
|
4
|
+
import { Mt as ce, St as le, n as h, pt as g, s as ue, xt as _ } from "./icons-BTdLXRXn.js";
|
|
5
|
+
import { t as de } from "./LoadingTrack-Cz1sT0wP.js";
|
|
6
6
|
import { t as v } from "./_plugin-vue_export-helper-B3ysoDQm.js";
|
|
7
|
-
import { n as fe } from "./useCloudI18n-
|
|
8
|
-
import { g as pe } from "./cloud-
|
|
7
|
+
import { n as fe } from "./useCloudI18n-D0AoLV0a.js";
|
|
8
|
+
import { g as pe } from "./cloud-CITqEHEc.js";
|
|
9
9
|
//#region src/cloud/components/DesignReferenceSidebar.vue?vue&type=script&setup=true&lang.ts
|
|
10
10
|
var me = {
|
|
11
11
|
key: 0,
|
|
@@ -220,4 +220,4 @@ var me = {
|
|
|
220
220
|
//#endregion
|
|
221
221
|
export { L as default };
|
|
222
222
|
|
|
223
|
-
//# sourceMappingURL=DesignReferenceSidebar-
|
|
223
|
+
//# sourceMappingURL=DesignReferenceSidebar-DRGqm33h.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DesignReferenceSidebar-BwsfOFsc.js","names":[],"sources":["../../../src/cloud/components/DesignReferenceSidebar.vue","../../../src/cloud/components/DesignReferenceSidebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { MAX_UPLOAD_SIZE_BYTES } from \"../../constants/timeouts\";\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport { useDesignReference } from \"@templatical/core/cloud\";\nimport { EDITOR_KEY, AUTH_MANAGER_KEY, requireInject } from \"../../keys\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport {\n CircleAlert,\n FileImage,\n FileText,\n ImageUp,\n Upload,\n X,\n} from \"@lucide/vue\";\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n hasExistingBlocks: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"apply\", content: TemplateContent): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"DesignReferenceSidebar\");\nconst authManager = requireInject(AUTH_MANAGER_KEY, \"DesignReferenceSidebar\");\n\nconst designReference = useDesignReference({\n authManager,\n getTemplateId: () => editor.state.template?.id ?? null,\n onApply: (content) => emit(\"apply\", content),\n});\n\nconst fileInput = ref<HTMLInputElement | null>(null);\n\ntype SourceTab = \"image\" | \"pdf\";\n\nconst activeTab = ref<SourceTab>(\"image\");\nconst selectedFile = ref<File | null>(null);\nconst prompt = ref(\"\");\nconst filePreviewUrl = ref<string | null>(null);\nconst showConfirmation = ref(false);\nconst isDragging = ref(false);\n\nconst canGenerate = computed(() => {\n if (designReference.isGenerating.value) {\n return false;\n }\n\n return selectedFile.value !== null;\n});\n\nfunction selectTab(tab: SourceTab): void {\n activeTab.value = tab;\n clearFile();\n}\n\nfunction handleFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) {\n setFile(file);\n }\n // Reset input so same file can be selected again\n input.value = \"\";\n}\n\nfunction setFile(file: File): void {\n // Validate file size (10MB)\n if (file.size > MAX_UPLOAD_SIZE_BYTES) {\n designReference.error.value = cloudT.designReference.fileTooLarge;\n return;\n }\n\n // Validate file type\n if (activeTab.value === \"image\") {\n const validTypes = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/webp\"];\n if (!validTypes.includes(file.type)) {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n } else if (activeTab.value === \"pdf\") {\n if (file.type !== \"application/pdf\") {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n }\n\n selectedFile.value = file;\n designReference.error.value = null;\n\n // Create preview URL for images\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n }\n if (file.type.startsWith(\"image/\")) {\n filePreviewUrl.value = URL.createObjectURL(file);\n } else {\n filePreviewUrl.value = null;\n }\n}\n\nfunction clearFile(): void {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n selectedFile.value = null;\n}\n\nfunction handleDragOver(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = true;\n}\n\nfunction handleDragLeave(): void {\n isDragging.value = false;\n}\n\nfunction handleDrop(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = false;\n\n const file = event.dataTransfer?.files?.[0];\n if (file) {\n setFile(file);\n }\n}\n\nfunction handleGenerate(): void {\n if (!canGenerate.value) {\n return;\n }\n\n // Show confirmation if there are existing blocks\n if (props.hasExistingBlocks && !showConfirmation.value) {\n showConfirmation.value = true;\n return;\n }\n\n showConfirmation.value = false;\n\n const input: {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n } = {};\n\n if (prompt.value.trim()) {\n input.prompt = prompt.value.trim();\n }\n\n if (activeTab.value === \"image\" && selectedFile.value) {\n input.imageUpload = selectedFile.value;\n } else if (activeTab.value === \"pdf\" && selectedFile.value) {\n input.pdfUpload = selectedFile.value;\n }\n\n designReference.generate(input);\n}\n\nfunction cancelConfirmation(): void {\n showConfirmation.value = false;\n}\n\n// Reset state when panel closes\nwatch(\n () => props.visible,\n (isVisible) => {\n if (!isVisible) {\n showConfirmation.value = false;\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n});\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-design-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-design-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ImageUp :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.designReference.title }}</span>\n </div>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"designReference.isGenerating.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <div\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3\"\n >\n <LoadingTrack />\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.designReference.generating }}\n </p>\n </div>\n </div>\n\n <!-- Input form -->\n <div v-else class=\"tpl:flex tpl:flex-col tpl:gap-4\">\n <!-- Source tabs -->\n <div\n class=\"tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]\"\n >\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all\"\n :style=\"{\n backgroundColor:\n activeTab === 'image' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'image'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'image' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('image')\"\n >\n <FileImage :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadImage }}\n </button>\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all\"\n :style=\"{\n backgroundColor:\n activeTab === 'pdf' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'pdf'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'pdf' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('pdf')\"\n >\n <FileText :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadPdf }}\n </button>\n </div>\n\n <!-- File upload area (image or pdf) -->\n <div>\n <!-- Preview -->\n <div v-if=\"selectedFile\" class=\"tpl:flex tpl:flex-col tpl:gap-2\">\n <div\n class=\"tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]\"\n >\n <!-- Image preview -->\n <img\n v-if=\"filePreviewUrl\"\n :src=\"filePreviewUrl\"\n :alt=\"selectedFile.name\"\n class=\"tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain\"\n />\n <!-- PDF preview (icon-based) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2\"\n >\n <FileText\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\">\n {{ selectedFile.name }}\n </span>\n </div>\n <!-- Remove button -->\n <button\n class=\"tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]\"\n @click=\"clearFile\"\n >\n <X :size=\"12\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Drop zone -->\n <div\n v-else\n class=\"tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors\"\n :style=\"{\n borderColor: isDragging\n ? 'var(--tpl-primary)'\n : 'var(--tpl-border-light)',\n backgroundColor: isDragging\n ? 'var(--tpl-primary-light)'\n : 'var(--tpl-bg)',\n }\"\n @click=\"fileInput?.click()\"\n @dragover=\"handleDragOver\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop\"\n >\n <Upload\n :size=\"24\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span\n class=\"tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.dropHint }}\n </span>\n <span\n class=\"tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n activeTab === \"image\"\n ? cloudT.designReference.acceptedImages\n : cloudT.designReference.acceptedPdf\n }}\n </span>\n </div>\n <input\n ref=\"fileInput\"\n type=\"file\"\n class=\"tpl:hidden\"\n :accept=\"\n activeTab === 'image'\n ? 'image/png,image/jpeg,image/webp'\n : 'application/pdf'\n \"\n @change=\"handleFileSelect\"\n />\n </div>\n\n <!-- Prompt textarea -->\n <div class=\"tpl:flex tpl:flex-col tpl:gap-1.5\">\n <label\n class=\"tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.promptLabel }}\n </label>\n <textarea\n v-model=\"prompt\"\n class=\"tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]\"\n :class=\"['tpl-design-prompt-input']\"\n :placeholder=\"cloudT.designReference.promptPlaceholder\"\n rows=\"3\"\n />\n </div>\n\n <!-- Confirmation overlay -->\n <div\n v-if=\"showConfirmation\"\n class=\"tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]\"\n >\n <p class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\">\n {{ cloudT.designReference.replaceWarning }}\n </p>\n <div class=\"tpl:flex tpl:gap-2\">\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]\"\n style=\"background-color: transparent\"\n @click=\"cancelConfirmation\"\n >\n {{ cloudT.designReference.replaceCancel }}\n </button>\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-on-primary)]\"\n @click=\"handleGenerate\"\n >\n {{ cloudT.designReference.replaceConfirm }}\n </button>\n </div>\n </div>\n\n <!-- Error message -->\n <div\n v-if=\"designReference.error.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.designReference.error }}</span>\n </div>\n\n <!-- Generate button -->\n <button\n v-if=\"!showConfirmation\"\n class=\"tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-on-primary)]\"\n :disabled=\"!canGenerate\"\n @click=\"handleGenerate\"\n >\n <ImageUp :size=\"16\" :stroke-width=\"2\" />\n {{ cloudT.designReference.generate }}\n </button>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-design-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-prompt-input:focus {\n border-color: var(--tpl-primary);\n box-shadow: var(--tpl-ring);\n}\n\n.tpl-design-dropzone:hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { MAX_UPLOAD_SIZE_BYTES } from \"../../constants/timeouts\";\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport { useDesignReference } from \"@templatical/core/cloud\";\nimport { EDITOR_KEY, AUTH_MANAGER_KEY, requireInject } from \"../../keys\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport {\n CircleAlert,\n FileImage,\n FileText,\n ImageUp,\n Upload,\n X,\n} from \"@lucide/vue\";\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n hasExistingBlocks: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"apply\", content: TemplateContent): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"DesignReferenceSidebar\");\nconst authManager = requireInject(AUTH_MANAGER_KEY, \"DesignReferenceSidebar\");\n\nconst designReference = useDesignReference({\n authManager,\n getTemplateId: () => editor.state.template?.id ?? null,\n onApply: (content) => emit(\"apply\", content),\n});\n\nconst fileInput = ref<HTMLInputElement | null>(null);\n\ntype SourceTab = \"image\" | \"pdf\";\n\nconst activeTab = ref<SourceTab>(\"image\");\nconst selectedFile = ref<File | null>(null);\nconst prompt = ref(\"\");\nconst filePreviewUrl = ref<string | null>(null);\nconst showConfirmation = ref(false);\nconst isDragging = ref(false);\n\nconst canGenerate = computed(() => {\n if (designReference.isGenerating.value) {\n return false;\n }\n\n return selectedFile.value !== null;\n});\n\nfunction selectTab(tab: SourceTab): void {\n activeTab.value = tab;\n clearFile();\n}\n\nfunction handleFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) {\n setFile(file);\n }\n // Reset input so same file can be selected again\n input.value = \"\";\n}\n\nfunction setFile(file: File): void {\n // Validate file size (10MB)\n if (file.size > MAX_UPLOAD_SIZE_BYTES) {\n designReference.error.value = cloudT.designReference.fileTooLarge;\n return;\n }\n\n // Validate file type\n if (activeTab.value === \"image\") {\n const validTypes = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/webp\"];\n if (!validTypes.includes(file.type)) {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n } else if (activeTab.value === \"pdf\") {\n if (file.type !== \"application/pdf\") {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n }\n\n selectedFile.value = file;\n designReference.error.value = null;\n\n // Create preview URL for images\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n }\n if (file.type.startsWith(\"image/\")) {\n filePreviewUrl.value = URL.createObjectURL(file);\n } else {\n filePreviewUrl.value = null;\n }\n}\n\nfunction clearFile(): void {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n selectedFile.value = null;\n}\n\nfunction handleDragOver(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = true;\n}\n\nfunction handleDragLeave(): void {\n isDragging.value = false;\n}\n\nfunction handleDrop(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = false;\n\n const file = event.dataTransfer?.files?.[0];\n if (file) {\n setFile(file);\n }\n}\n\nfunction handleGenerate(): void {\n if (!canGenerate.value) {\n return;\n }\n\n // Show confirmation if there are existing blocks\n if (props.hasExistingBlocks && !showConfirmation.value) {\n showConfirmation.value = true;\n return;\n }\n\n showConfirmation.value = false;\n\n const input: {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n } = {};\n\n if (prompt.value.trim()) {\n input.prompt = prompt.value.trim();\n }\n\n if (activeTab.value === \"image\" && selectedFile.value) {\n input.imageUpload = selectedFile.value;\n } else if (activeTab.value === \"pdf\" && selectedFile.value) {\n input.pdfUpload = selectedFile.value;\n }\n\n designReference.generate(input);\n}\n\nfunction cancelConfirmation(): void {\n showConfirmation.value = false;\n}\n\n// Reset state when panel closes\nwatch(\n () => props.visible,\n (isVisible) => {\n if (!isVisible) {\n showConfirmation.value = false;\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n});\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-design-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-design-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ImageUp :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.designReference.title }}</span>\n </div>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"designReference.isGenerating.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <div\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3\"\n >\n <LoadingTrack />\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.designReference.generating }}\n </p>\n </div>\n </div>\n\n <!-- Input form -->\n <div v-else class=\"tpl:flex tpl:flex-col tpl:gap-4\">\n <!-- Source tabs -->\n <div\n class=\"tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]\"\n >\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all\"\n :style=\"{\n backgroundColor:\n activeTab === 'image' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'image'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'image' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('image')\"\n >\n <FileImage :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadImage }}\n </button>\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all\"\n :style=\"{\n backgroundColor:\n activeTab === 'pdf' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'pdf'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'pdf' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('pdf')\"\n >\n <FileText :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadPdf }}\n </button>\n </div>\n\n <!-- File upload area (image or pdf) -->\n <div>\n <!-- Preview -->\n <div v-if=\"selectedFile\" class=\"tpl:flex tpl:flex-col tpl:gap-2\">\n <div\n class=\"tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]\"\n >\n <!-- Image preview -->\n <img\n v-if=\"filePreviewUrl\"\n :src=\"filePreviewUrl\"\n :alt=\"selectedFile.name\"\n class=\"tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain\"\n />\n <!-- PDF preview (icon-based) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2\"\n >\n <FileText\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\">\n {{ selectedFile.name }}\n </span>\n </div>\n <!-- Remove button -->\n <button\n class=\"tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]\"\n @click=\"clearFile\"\n >\n <X :size=\"12\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Drop zone -->\n <div\n v-else\n class=\"tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors\"\n :style=\"{\n borderColor: isDragging\n ? 'var(--tpl-primary)'\n : 'var(--tpl-border-light)',\n backgroundColor: isDragging\n ? 'var(--tpl-primary-light)'\n : 'var(--tpl-bg)',\n }\"\n @click=\"fileInput?.click()\"\n @dragover=\"handleDragOver\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop\"\n >\n <Upload\n :size=\"24\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span\n class=\"tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.dropHint }}\n </span>\n <span\n class=\"tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n activeTab === \"image\"\n ? cloudT.designReference.acceptedImages\n : cloudT.designReference.acceptedPdf\n }}\n </span>\n </div>\n <input\n ref=\"fileInput\"\n type=\"file\"\n class=\"tpl:hidden\"\n :accept=\"\n activeTab === 'image'\n ? 'image/png,image/jpeg,image/webp'\n : 'application/pdf'\n \"\n @change=\"handleFileSelect\"\n />\n </div>\n\n <!-- Prompt textarea -->\n <div class=\"tpl:flex tpl:flex-col tpl:gap-1.5\">\n <label\n class=\"tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.promptLabel }}\n </label>\n <textarea\n v-model=\"prompt\"\n class=\"tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]\"\n :class=\"['tpl-design-prompt-input']\"\n :placeholder=\"cloudT.designReference.promptPlaceholder\"\n rows=\"3\"\n />\n </div>\n\n <!-- Confirmation overlay -->\n <div\n v-if=\"showConfirmation\"\n class=\"tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]\"\n >\n <p class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\">\n {{ cloudT.designReference.replaceWarning }}\n </p>\n <div class=\"tpl:flex tpl:gap-2\">\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]\"\n style=\"background-color: transparent\"\n @click=\"cancelConfirmation\"\n >\n {{ cloudT.designReference.replaceCancel }}\n </button>\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-on-primary)]\"\n @click=\"handleGenerate\"\n >\n {{ cloudT.designReference.replaceConfirm }}\n </button>\n </div>\n </div>\n\n <!-- Error message -->\n <div\n v-if=\"designReference.error.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.designReference.error }}</span>\n </div>\n\n <!-- Generate button -->\n <button\n v-if=\"!showConfirmation\"\n class=\"tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-on-primary)]\"\n :disabled=\"!canGenerate\"\n @click=\"handleGenerate\"\n >\n <ImageUp :size=\"16\" :stroke-width=\"2\" />\n {{ cloudT.designReference.generate }}\n </button>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-design-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-prompt-input:focus {\n border-color: var(--tpl-primary);\n box-shadow: var(--tpl-ring);\n}\n\n.tpl-design-dropzone:hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DesignReferenceSidebar-DRGqm33h.js","names":[],"sources":["../../../src/cloud/components/DesignReferenceSidebar.vue","../../../src/cloud/components/DesignReferenceSidebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { MAX_UPLOAD_SIZE_BYTES } from \"../../constants/timeouts\";\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport { useDesignReference } from \"@templatical/core/cloud\";\nimport { EDITOR_KEY, AUTH_MANAGER_KEY, requireInject } from \"../../keys\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport {\n CircleAlert,\n FileImage,\n FileText,\n ImageUp,\n Upload,\n X,\n} from \"@lucide/vue\";\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n hasExistingBlocks: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"apply\", content: TemplateContent): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"DesignReferenceSidebar\");\nconst authManager = requireInject(AUTH_MANAGER_KEY, \"DesignReferenceSidebar\");\n\nconst designReference = useDesignReference({\n authManager,\n getTemplateId: () => editor.state.template?.id ?? null,\n onApply: (content) => emit(\"apply\", content),\n});\n\nconst fileInput = ref<HTMLInputElement | null>(null);\n\ntype SourceTab = \"image\" | \"pdf\";\n\nconst activeTab = ref<SourceTab>(\"image\");\nconst selectedFile = ref<File | null>(null);\nconst prompt = ref(\"\");\nconst filePreviewUrl = ref<string | null>(null);\nconst showConfirmation = ref(false);\nconst isDragging = ref(false);\n\nconst canGenerate = computed(() => {\n if (designReference.isGenerating.value) {\n return false;\n }\n\n return selectedFile.value !== null;\n});\n\nfunction selectTab(tab: SourceTab): void {\n activeTab.value = tab;\n clearFile();\n}\n\nfunction handleFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) {\n setFile(file);\n }\n // Reset input so same file can be selected again\n input.value = \"\";\n}\n\nfunction setFile(file: File): void {\n // Validate file size (10MB)\n if (file.size > MAX_UPLOAD_SIZE_BYTES) {\n designReference.error.value = cloudT.designReference.fileTooLarge;\n return;\n }\n\n // Validate file type\n if (activeTab.value === \"image\") {\n const validTypes = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/webp\"];\n if (!validTypes.includes(file.type)) {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n } else if (activeTab.value === \"pdf\") {\n if (file.type !== \"application/pdf\") {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n }\n\n selectedFile.value = file;\n designReference.error.value = null;\n\n // Create preview URL for images\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n }\n if (file.type.startsWith(\"image/\")) {\n filePreviewUrl.value = URL.createObjectURL(file);\n } else {\n filePreviewUrl.value = null;\n }\n}\n\nfunction clearFile(): void {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n selectedFile.value = null;\n}\n\nfunction handleDragOver(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = true;\n}\n\nfunction handleDragLeave(): void {\n isDragging.value = false;\n}\n\nfunction handleDrop(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = false;\n\n const file = event.dataTransfer?.files?.[0];\n if (file) {\n setFile(file);\n }\n}\n\nfunction handleGenerate(): void {\n if (!canGenerate.value) {\n return;\n }\n\n // Show confirmation if there are existing blocks\n if (props.hasExistingBlocks && !showConfirmation.value) {\n showConfirmation.value = true;\n return;\n }\n\n showConfirmation.value = false;\n\n const input: {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n } = {};\n\n if (prompt.value.trim()) {\n input.prompt = prompt.value.trim();\n }\n\n if (activeTab.value === \"image\" && selectedFile.value) {\n input.imageUpload = selectedFile.value;\n } else if (activeTab.value === \"pdf\" && selectedFile.value) {\n input.pdfUpload = selectedFile.value;\n }\n\n designReference.generate(input);\n}\n\nfunction cancelConfirmation(): void {\n showConfirmation.value = false;\n}\n\n// Reset state when panel closes\nwatch(\n () => props.visible,\n (isVisible) => {\n if (!isVisible) {\n showConfirmation.value = false;\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n});\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-design-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-design-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ImageUp :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.designReference.title }}</span>\n </div>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"designReference.isGenerating.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <div\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3\"\n >\n <LoadingTrack />\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.designReference.generating }}\n </p>\n </div>\n </div>\n\n <!-- Input form -->\n <div v-else class=\"tpl:flex tpl:flex-col tpl:gap-4\">\n <!-- Source tabs -->\n <div\n class=\"tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]\"\n >\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all\"\n :style=\"{\n backgroundColor:\n activeTab === 'image' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'image'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'image' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('image')\"\n >\n <FileImage :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadImage }}\n </button>\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all\"\n :style=\"{\n backgroundColor:\n activeTab === 'pdf' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'pdf'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'pdf' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('pdf')\"\n >\n <FileText :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadPdf }}\n </button>\n </div>\n\n <!-- File upload area (image or pdf) -->\n <div>\n <!-- Preview -->\n <div v-if=\"selectedFile\" class=\"tpl:flex tpl:flex-col tpl:gap-2\">\n <div\n class=\"tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]\"\n >\n <!-- Image preview -->\n <img\n v-if=\"filePreviewUrl\"\n :src=\"filePreviewUrl\"\n :alt=\"selectedFile.name\"\n class=\"tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain\"\n />\n <!-- PDF preview (icon-based) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2\"\n >\n <FileText\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\">\n {{ selectedFile.name }}\n </span>\n </div>\n <!-- Remove button -->\n <button\n class=\"tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]\"\n @click=\"clearFile\"\n >\n <X :size=\"12\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Drop zone -->\n <div\n v-else\n class=\"tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors\"\n :style=\"{\n borderColor: isDragging\n ? 'var(--tpl-primary)'\n : 'var(--tpl-border-light)',\n backgroundColor: isDragging\n ? 'var(--tpl-primary-light)'\n : 'var(--tpl-bg)',\n }\"\n @click=\"fileInput?.click()\"\n @dragover=\"handleDragOver\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop\"\n >\n <Upload\n :size=\"24\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span\n class=\"tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.dropHint }}\n </span>\n <span\n class=\"tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n activeTab === \"image\"\n ? cloudT.designReference.acceptedImages\n : cloudT.designReference.acceptedPdf\n }}\n </span>\n </div>\n <input\n ref=\"fileInput\"\n type=\"file\"\n class=\"tpl:hidden\"\n :accept=\"\n activeTab === 'image'\n ? 'image/png,image/jpeg,image/webp'\n : 'application/pdf'\n \"\n @change=\"handleFileSelect\"\n />\n </div>\n\n <!-- Prompt textarea -->\n <div class=\"tpl:flex tpl:flex-col tpl:gap-1.5\">\n <label\n class=\"tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.promptLabel }}\n </label>\n <textarea\n v-model=\"prompt\"\n class=\"tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]\"\n :class=\"['tpl-design-prompt-input']\"\n :placeholder=\"cloudT.designReference.promptPlaceholder\"\n rows=\"3\"\n />\n </div>\n\n <!-- Confirmation overlay -->\n <div\n v-if=\"showConfirmation\"\n class=\"tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]\"\n >\n <p class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\">\n {{ cloudT.designReference.replaceWarning }}\n </p>\n <div class=\"tpl:flex tpl:gap-2\">\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]\"\n style=\"background-color: transparent\"\n @click=\"cancelConfirmation\"\n >\n {{ cloudT.designReference.replaceCancel }}\n </button>\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-on-primary)]\"\n @click=\"handleGenerate\"\n >\n {{ cloudT.designReference.replaceConfirm }}\n </button>\n </div>\n </div>\n\n <!-- Error message -->\n <div\n v-if=\"designReference.error.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.designReference.error }}</span>\n </div>\n\n <!-- Generate button -->\n <button\n v-if=\"!showConfirmation\"\n class=\"tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-on-primary)]\"\n :disabled=\"!canGenerate\"\n @click=\"handleGenerate\"\n >\n <ImageUp :size=\"16\" :stroke-width=\"2\" />\n {{ cloudT.designReference.generate }}\n </button>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-design-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-prompt-input:focus {\n border-color: var(--tpl-primary);\n box-shadow: var(--tpl-ring);\n}\n\n.tpl-design-dropzone:hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { MAX_UPLOAD_SIZE_BYTES } from \"../../constants/timeouts\";\nimport LoadingTrack from \"../../components/LoadingTrack.vue\";\nimport { useDesignReference } from \"@templatical/core/cloud\";\nimport { EDITOR_KEY, AUTH_MANAGER_KEY, requireInject } from \"../../keys\";\nimport { useCloudI18nStrict } from \"../../composables/useCloudI18n\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport {\n CircleAlert,\n FileImage,\n FileText,\n ImageUp,\n Upload,\n X,\n} from \"@lucide/vue\";\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\n\nconst props = defineProps<{\n visible: boolean;\n hasExistingBlocks: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"close\"): void;\n (e: \"apply\", content: TemplateContent): void;\n}>();\n\nconst { t: cloudT } = useCloudI18nStrict();\nconst editor = requireInject(EDITOR_KEY, \"DesignReferenceSidebar\");\nconst authManager = requireInject(AUTH_MANAGER_KEY, \"DesignReferenceSidebar\");\n\nconst designReference = useDesignReference({\n authManager,\n getTemplateId: () => editor.state.template?.id ?? null,\n onApply: (content) => emit(\"apply\", content),\n});\n\nconst fileInput = ref<HTMLInputElement | null>(null);\n\ntype SourceTab = \"image\" | \"pdf\";\n\nconst activeTab = ref<SourceTab>(\"image\");\nconst selectedFile = ref<File | null>(null);\nconst prompt = ref(\"\");\nconst filePreviewUrl = ref<string | null>(null);\nconst showConfirmation = ref(false);\nconst isDragging = ref(false);\n\nconst canGenerate = computed(() => {\n if (designReference.isGenerating.value) {\n return false;\n }\n\n return selectedFile.value !== null;\n});\n\nfunction selectTab(tab: SourceTab): void {\n activeTab.value = tab;\n clearFile();\n}\n\nfunction handleFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) {\n setFile(file);\n }\n // Reset input so same file can be selected again\n input.value = \"\";\n}\n\nfunction setFile(file: File): void {\n // Validate file size (10MB)\n if (file.size > MAX_UPLOAD_SIZE_BYTES) {\n designReference.error.value = cloudT.designReference.fileTooLarge;\n return;\n }\n\n // Validate file type\n if (activeTab.value === \"image\") {\n const validTypes = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/webp\"];\n if (!validTypes.includes(file.type)) {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n } else if (activeTab.value === \"pdf\") {\n if (file.type !== \"application/pdf\") {\n designReference.error.value = cloudT.designReference.invalidFileType;\n return;\n }\n }\n\n selectedFile.value = file;\n designReference.error.value = null;\n\n // Create preview URL for images\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n }\n if (file.type.startsWith(\"image/\")) {\n filePreviewUrl.value = URL.createObjectURL(file);\n } else {\n filePreviewUrl.value = null;\n }\n}\n\nfunction clearFile(): void {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n selectedFile.value = null;\n}\n\nfunction handleDragOver(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = true;\n}\n\nfunction handleDragLeave(): void {\n isDragging.value = false;\n}\n\nfunction handleDrop(event: DragEvent): void {\n event.preventDefault();\n isDragging.value = false;\n\n const file = event.dataTransfer?.files?.[0];\n if (file) {\n setFile(file);\n }\n}\n\nfunction handleGenerate(): void {\n if (!canGenerate.value) {\n return;\n }\n\n // Show confirmation if there are existing blocks\n if (props.hasExistingBlocks && !showConfirmation.value) {\n showConfirmation.value = true;\n return;\n }\n\n showConfirmation.value = false;\n\n const input: {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n } = {};\n\n if (prompt.value.trim()) {\n input.prompt = prompt.value.trim();\n }\n\n if (activeTab.value === \"image\" && selectedFile.value) {\n input.imageUpload = selectedFile.value;\n } else if (activeTab.value === \"pdf\" && selectedFile.value) {\n input.pdfUpload = selectedFile.value;\n }\n\n designReference.generate(input);\n}\n\nfunction cancelConfirmation(): void {\n showConfirmation.value = false;\n}\n\n// Reset state when panel closes\nwatch(\n () => props.visible,\n (isVisible) => {\n if (!isVisible) {\n showConfirmation.value = false;\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (filePreviewUrl.value) {\n URL.revokeObjectURL(filePreviewUrl.value);\n filePreviewUrl.value = null;\n }\n});\n</script>\n\n<template>\n <Transition\n enter-active-class=\"tpl-design-slide-enter-active\"\n enter-from-class=\"tpl:translate-x-full\"\n enter-to-class=\"tpl:translate-x-0\"\n leave-active-class=\"tpl-design-slide-leave-active\"\n leave-from-class=\"tpl:translate-x-0\"\n leave-to-class=\"tpl:translate-x-full\"\n >\n <div\n v-if=\"visible\"\n class=\"tpl-design-sidebar tpl:absolute tpl:top-14 tpl:right-0 tpl:bottom-0 tpl:z-panel tpl:flex tpl:w-[360px] tpl:flex-col tpl:border-l tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)]\"\n >\n <!-- Header -->\n <div\n class=\"tpl:flex tpl:items-center tpl:justify-between tpl:border-b tpl:border-[var(--tpl-border)] tpl:px-4 tpl:py-3\"\n >\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-sm tpl:font-medium tpl:text-[var(--tpl-primary)]\"\n >\n <ImageUp :size=\"13\" :stroke-width=\"2\" />\n <span>{{ cloudT.designReference.title }}</span>\n </div>\n <button\n class=\"tpl:rounded-md tpl:p-0.5 tpl:transition-colors tpl:text-[var(--tpl-text-muted)]\"\n @click=\"emit('close')\"\n >\n <X :size=\"14\" :stroke-width=\"2\" />\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"tpl:flex-1 tpl:overflow-y-auto tpl:p-4\">\n <!-- Loading state -->\n <div\n v-if=\"designReference.isGenerating.value\"\n class=\"tpl:flex tpl:h-full tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-3 tpl:text-center\"\n >\n <div\n class=\"tpl:flex tpl:w-full tpl:flex-col tpl:items-center tpl:gap-3\"\n >\n <LoadingTrack />\n <p class=\"tpl:text-sm tpl:text-[var(--tpl-text-muted)]\">\n {{ cloudT.designReference.generating }}\n </p>\n </div>\n </div>\n\n <!-- Input form -->\n <div v-else class=\"tpl:flex tpl:flex-col tpl:gap-4\">\n <!-- Source tabs -->\n <div\n class=\"tpl:flex tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1 tpl:bg-[var(--tpl-bg-hover)]\"\n >\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all\"\n :style=\"{\n backgroundColor:\n activeTab === 'image' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'image'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'image' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('image')\"\n >\n <FileImage :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadImage }}\n </button>\n <button\n class=\"tpl:flex tpl:flex-1 tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-2 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all\"\n :style=\"{\n backgroundColor:\n activeTab === 'pdf' ? 'var(--tpl-bg)' : 'transparent',\n color:\n activeTab === 'pdf'\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n boxShadow: activeTab === 'pdf' ? 'var(--tpl-shadow)' : 'none',\n }\"\n @click=\"selectTab('pdf')\"\n >\n <FileText :size=\"12\" :stroke-width=\"2\" />\n {{ cloudT.designReference.uploadPdf }}\n </button>\n </div>\n\n <!-- File upload area (image or pdf) -->\n <div>\n <!-- Preview -->\n <div v-if=\"selectedFile\" class=\"tpl:flex tpl:flex-col tpl:gap-2\">\n <div\n class=\"tpl:relative tpl:overflow-hidden tpl:rounded-[var(--tpl-radius)] tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)]\"\n >\n <!-- Image preview -->\n <img\n v-if=\"filePreviewUrl\"\n :src=\"filePreviewUrl\"\n :alt=\"selectedFile.name\"\n class=\"tpl:h-auto tpl:max-h-48 tpl:w-full tpl:object-contain\"\n />\n <!-- PDF preview (icon-based) -->\n <div\n v-else\n class=\"tpl:flex tpl:h-32 tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2\"\n >\n <FileText\n :size=\"32\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span class=\"tpl:text-xs tpl:text-[var(--tpl-text-muted)]\">\n {{ selectedFile.name }}\n </span>\n </div>\n <!-- Remove button -->\n <button\n class=\"tpl:absolute tpl:top-2 tpl:right-2 tpl:rounded-full tpl:p-1 tpl:transition-colors tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-muted)] tpl:shadow-[var(--tpl-shadow)]\"\n @click=\"clearFile\"\n >\n <X :size=\"12\" :stroke-width=\"2\" />\n </button>\n </div>\n </div>\n\n <!-- Drop zone -->\n <div\n v-else\n class=\"tpl-design-dropzone tpl:flex tpl:cursor-pointer tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:border-2 tpl:border-dashed tpl:px-4 tpl:py-8 tpl:transition-colors\"\n :style=\"{\n borderColor: isDragging\n ? 'var(--tpl-primary)'\n : 'var(--tpl-border-light)',\n backgroundColor: isDragging\n ? 'var(--tpl-primary-light)'\n : 'var(--tpl-bg)',\n }\"\n @click=\"fileInput?.click()\"\n @dragover=\"handleDragOver\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop\"\n >\n <Upload\n :size=\"24\"\n :stroke-width=\"1.5\"\n class=\"tpl:text-[var(--tpl-text-dim)]\"\n />\n <span\n class=\"tpl:text-center tpl:text-xs tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.dropHint }}\n </span>\n <span\n class=\"tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{\n activeTab === \"image\"\n ? cloudT.designReference.acceptedImages\n : cloudT.designReference.acceptedPdf\n }}\n </span>\n </div>\n <input\n ref=\"fileInput\"\n type=\"file\"\n class=\"tpl:hidden\"\n :accept=\"\n activeTab === 'image'\n ? 'image/png,image/jpeg,image/webp'\n : 'application/pdf'\n \"\n @change=\"handleFileSelect\"\n />\n </div>\n\n <!-- Prompt textarea -->\n <div class=\"tpl:flex tpl:flex-col tpl:gap-1.5\">\n <label\n class=\"tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text-muted)]\"\n >\n {{ cloudT.designReference.promptLabel }}\n </label>\n <textarea\n v-model=\"prompt\"\n class=\"tpl:min-h-[72px] tpl:w-full tpl:resize-none tpl:rounded-[var(--tpl-radius-sm)] tpl:border tpl:px-3 tpl:py-2 tpl:font-sans tpl:text-sm tpl:outline-none tpl:transition-colors tpl:border-[var(--tpl-border)] tpl:text-[var(--tpl-text)] tpl:bg-[var(--tpl-bg)]\"\n :class=\"['tpl-design-prompt-input']\"\n :placeholder=\"cloudT.designReference.promptPlaceholder\"\n rows=\"3\"\n />\n </div>\n\n <!-- Confirmation overlay -->\n <div\n v-if=\"showConfirmation\"\n class=\"tpl:flex tpl:flex-col tpl:gap-2 tpl:rounded-[var(--tpl-radius)] tpl:px-3 tpl:py-3 tpl:bg-[var(--tpl-warning-light)] tpl:border tpl:border-[var(--tpl-warning)]\"\n >\n <p class=\"tpl:text-xs tpl:leading-snug tpl:text-[var(--tpl-text)]\">\n {{ cloudT.designReference.replaceWarning }}\n </p>\n <div class=\"tpl:flex tpl:gap-2\">\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]\"\n style=\"background-color: transparent\"\n @click=\"cancelConfirmation\"\n >\n {{ cloudT.designReference.replaceCancel }}\n </button>\n <button\n class=\"tpl:flex-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:transition-all tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-on-primary)]\"\n @click=\"handleGenerate\"\n >\n {{ cloudT.designReference.replaceConfirm }}\n </button>\n </div>\n </div>\n\n <!-- Error message -->\n <div\n v-if=\"designReference.error.value\"\n class=\"tpl:flex tpl:items-start tpl:gap-2 tpl:rounded-lg tpl:px-3 tpl:py-2 tpl:text-xs tpl:bg-[var(--tpl-danger-light)] tpl:text-[var(--tpl-danger)]\"\n >\n <CircleAlert\n :size=\"14\"\n :stroke-width=\"2\"\n class=\"tpl:mt-0.5 tpl:shrink-0\"\n />\n <span>{{ cloudT.designReference.error }}</span>\n </div>\n\n <!-- Generate button -->\n <button\n v-if=\"!showConfirmation\"\n class=\"tpl:flex tpl:w-full tpl:items-center tpl:justify-center tpl:gap-2 tpl:rounded-[var(--tpl-radius-sm)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:hover:opacity-90 tpl:disabled:cursor-not-allowed tpl:disabled:opacity-50 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-on-primary)]\"\n :disabled=\"!canGenerate\"\n @click=\"handleGenerate\"\n >\n <ImageUp :size=\"16\" :stroke-width=\"2\" />\n {{ cloudT.designReference.generate }}\n </button>\n\n <!-- AI disclaimer -->\n <p\n class=\"tpl:m-0 tpl:pt-1 tpl:text-center tpl:text-[11px] tpl:text-[var(--tpl-text-dim)]\"\n >\n {{ cloudT.aiMenu.disclaimer }}\n </p>\n </div>\n </div>\n </div>\n </Transition>\n</template>\n\n<style scoped>\n.tpl-design-slide-enter-active {\n transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-slide-leave-active {\n transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.tpl-design-prompt-input:focus {\n border-color: var(--tpl-primary);\n box-shadow: var(--tpl-ring);\n}\n\n.tpl-design-dropzone:hover {\n border-color: var(--tpl-primary) !important;\n background-color: var(--tpl-primary-light) !important;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBA,IAAM,IAAQ,GAKR,IAAO,GAKP,EAAE,GAAG,MAAW,GAAmB,GACnC,KAAS,EAAc,IAAY,wBAAwB,GAC3D,KAAc,EAAc,IAAkB,wBAAwB,GAEtE,IAAkB,GAAmB;GACzC;GACA,qBAAqB,GAAO,MAAM,UAAU,MAAM;GAClD,UAAU,MAAY,EAAK,SAAS,CAAO;EAC7C,CAAC,GAEK,IAAY,EAA6B,IAAI,GAI7C,IAAY,EAAe,OAAO,GAClC,IAAe,EAAiB,IAAI,GACpC,IAAS,EAAI,EAAE,GACf,IAAiB,EAAmB,IAAI,GACxC,IAAmB,EAAI,EAAK,GAC5B,IAAa,EAAI,EAAK,GAEtB,IAAc,SAClB,CAAI,EAAgB,aAAa,SAI1B,EAAa,UAAU,IAC/B;EAED,SAAS,EAAU,GAAsB;GAEvC,AADA,EAAU,QAAQ,GAClB,EAAU;EACZ;EAEA,SAAS,GAAiB,GAAoB;GAC5C,IAAM,IAAQ,EAAM,QACd,IAAO,EAAM,QAAQ;GAK3B,AAJI,KACF,EAAQ,CAAI,GAGd,EAAM,QAAQ;EAChB;EAEA,SAAS,EAAQ,GAAkB;GAEjC,IAAI,EAAK,OAAA,UAA8B;IACrC,EAAgB,MAAM,QAAQ,EAAO,gBAAgB;IACrD;GACF;GAGA,IAAI,EAAU,UAAU,SAElB;QAAA,CAAC;KADe;KAAa;KAAc;KAAa;IACvD,CAAA,CAAW,SAAS,EAAK,IAAI,GAAG;KACnC,EAAgB,MAAM,QAAQ,EAAO,gBAAgB;KACrD;IACF;UACK,IAAI,EAAU,UAAU,SACzB,EAAK,SAAS,mBAAmB;IACnC,EAAgB,MAAM,QAAQ,EAAO,gBAAgB;IACrD;GACF;GAUF,AAPA,EAAa,QAAQ,GACrB,EAAgB,MAAM,QAAQ,MAG1B,EAAe,SACjB,IAAI,gBAAgB,EAAe,KAAK,GAEtC,EAAK,KAAK,WAAW,QAAQ,IAC/B,EAAe,QAAQ,IAAI,gBAAgB,CAAI,IAE/C,EAAe,QAAQ;EAE3B;EAEA,SAAS,IAAkB;GAKzB,AAJA,AAEE,EAAe,WADf,IAAI,gBAAgB,EAAe,KAAK,GACjB,OAEzB,EAAa,QAAQ;EACvB;EAEA,SAAS,EAAe,GAAwB;GAE9C,AADA,EAAM,eAAe,GACrB,EAAW,QAAQ;EACrB;EAEA,SAAS,KAAwB;GAC/B,EAAW,QAAQ;EACrB;EAEA,SAAS,GAAW,GAAwB;GAE1C,AADA,EAAM,eAAe,GACrB,EAAW,QAAQ;GAEnB,IAAM,IAAO,EAAM,cAAc,QAAQ;GACzC,AAAI,KACF,EAAQ,CAAI;EAEhB;EAEA,SAAS,IAAuB;GAC9B,IAAI,CAAC,EAAY,OACf;GAIF,IAAI,EAAM,qBAAqB,CAAC,EAAiB,OAAO;IACtD,EAAiB,QAAQ;IACzB;GACF;GAEA,EAAiB,QAAQ;GAEzB,IAAM,IAIF,CAAC;GAYL,AAVI,EAAO,MAAM,KAAK,MACpB,EAAM,SAAS,EAAO,MAAM,KAAK,IAG/B,EAAU,UAAU,WAAW,EAAa,QAC9C,EAAM,cAAc,EAAa,QACxB,EAAU,UAAU,SAAS,EAAa,UACnD,EAAM,YAAY,EAAa,QAGjC,EAAgB,SAAS,CAAK;EAChC;EAEA,SAAS,KAA2B;GAClC,EAAiB,QAAQ;EAC3B;SAGA,QACQ,EAAM,UACX,MAAc;GACb,AAAK,MACH,EAAiB,QAAQ;EAE7B,CACF,GAEA,QAAsB;GACpB,AAEE,EAAe,WADf,IAAI,gBAAgB,EAAe,KAAK,GACjB;EAE3B,CAAC,cAIC,EAAA,GAAA,GAyPa,IAAA;GAxPX,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;GACf,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;;GAEf,SAAA,QAgPM,CA/OE,EAAA,WADR,EAAA,GAAA,EAgPM,OAhPN,IAgPM,CA3OJ,EAeM,OAfN,IAeM,CAZJ,EAKM,OALN,IAKM,CAFJ,EAAwC,EAAA,CAAA,GAAA;IAA9B,MAAM;IAAK,gBAAc;GACnC,CAAA,GAAA,EAA+C,QAAA,MAAA,EAAtC,EAAA,CAAA,CAAM,CAAC,gBAAgB,KAAK,GAAA,CAAA,CAAA,CAAA,GAEvC,EAKS,UAAA;IAJP,OAAM;IACL,SAAK,AAAA,EAAA,QAAA,MAAE,EAAI,OAAA;GAEZ,GAAA,CAAA,EAAkC,EAAA,CAAA,GAAA;IAA9B,MAAM;IAAK,gBAAc;GAKjC,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,EAwNM,OAxNN,IAwNM,CArNI,EAAA,CAAA,CAAe,CAAC,aAAa,SADrC,EAAA,GAAA,EAYM,OAZN,GAYM,CARJ,EAOM,OAPN,GAOM,CAJJ,EAAgB,EAAA,GAChB,EAEI,KAFJ,GAEI,EADC,EAAA,CAAA,CAAM,CAAC,gBAAgB,UAAU,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,MAM1C,EAAA,GAAA,EAsMM,OAtMN,GAsMM;IApMJ,EAmCM,OAnCN,GAmCM,CAhCJ,EAeS,UAAA;KAdP,OAAM;KACL,OAAK,EAAA;MAAuD,iBAAA,EAAA,UAAS,UAAA,kBAAA;MAAyF,OAAA,EAAA,UAAS,UAAA,uBAAA;MAAkI,WAAA,EAAA,UAAS,UAAA,sBAAA;;KASlT,SAAK,AAAA,EAAA,QAAA,MAAE,EAAS,OAAA;IAEjB,GAAA,CAAA,EAA0C,EAAA,EAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;IAAK,CAAA,GAAA,EAAA,MAC1C,EAAG,EAAA,CAAA,CAAM,CAAC,gBAAgB,WAAW,GAAA,CAAA,CAAA,GAAA,CAAA,GAEvC,EAeS,UAAA;KAdP,OAAM;KACL,OAAK,EAAA;MAAuD,iBAAA,EAAA,UAAS,QAAA,kBAAA;MAAuF,OAAA,EAAA,UAAS,QAAA,uBAAA;MAAgI,WAAA,EAAA,UAAS,QAAA,sBAAA;;KAS9S,SAAK,AAAA,EAAA,QAAA,MAAE,EAAS,KAAA;IAEjB,GAAA,CAAA,EAAyC,EAAA,CAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;IAAK,CAAA,GAAA,EAAA,MACzC,EAAG,EAAA,CAAA,CAAM,CAAC,gBAAgB,SAAS,GAAA,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA;IAKvC,EAqFM,OAAA,MAAA,CAnFO,EAAA,SAAX,EAAA,GAAA,EAiCM,OAjCN,GAiCM,CAhCJ,EA+BM,OA/BN,GA+BM,CA1BI,EAAA,SADR,EAAA,GAAA,EAKE,OAAA;;KAHC,KAAK,EAAA;KACL,KAAK,EAAA,MAAa;KACnB,OAAM;IAGR,GAAA,MAAA,GAAA,CAAA,MAAA,EAAA,GAAA,EAYM,OAZN,GAYM,CARJ,EAIE,EAAA,CAAA,GAAA;KAHC,MAAM;KACN,gBAAc;KACf,OAAM;IAER,CAAA,GAAA,EAEO,QAFP,GAEO,EADF,EAAA,MAAa,IAAI,GAAA,CAAA,CAAA,CAAA,IAIxB,EAKS,UAAA;KAJP,OAAM;KACL,SAAO;IAER,GAAA,CAAA,EAAkC,EAAA,CAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;IAMnC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,MAAA,EAAA,GAAA,EAmCM,OAAA;;KAjCJ,OAAM;KACL,OAAK,EAAA;MAAiC,aAAA,EAAA,QAAA,uBAAA;MAAoI,iBAAA,EAAA,QAAA,6BAAA;;KAQ1K,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,OAAW,MAAK;KACvB,YAAU;KACV,aAAW;KACX,QAAM;;KAEP,EAIE,EAAA,EAAA,GAAA;MAHC,MAAM;MACN,gBAAc;MACf,OAAM;;KAER,EAIO,QAJP,GAIO,EADF,EAAA,CAAA,CAAM,CAAC,gBAAgB,QAAQ,GAAA,CAAA;KAEpC,EAQO,QARP,GAQO,EAJH,EAAA,UAAS,UAAmC,EAAA,CAAA,CAAM,CAAC,gBAAgB,iBAAqC,EAAA,CAAA,CAAM,CAAC,gBAAgB,WAAW,GAAA,CAAA;IAMhJ,GAAA,EAAA,IAAA,EAUE,SAAA;KATI,SAAA;KAAJ,KAAI;KACJ,MAAK;KACL,OAAM;KACL,QAAyB,EAAA,UAAS,UAAA,oCAAA;KAKlC,UAAQ;;IAKb,EAaM,OAbN,GAaM,CAZJ,EAIQ,SAJR,GAIQ,EADH,EAAA,CAAA,CAAM,CAAC,gBAAgB,WAAW,GAAA,CAAA,GAEvC,GAAA,EAME,YAAA;KALS,uBAAA,AAAA,EAAA,QAAA,MAAA,EAAM,QAAA;KACf,OAAK,GAAA,CAAC,iQACE,CAAA,yBAAA,CAA2B,CAAA;KAClC,aAAa,EAAA,CAAA,CAAM,CAAC,gBAAgB;KACrC,MAAK;IAJI,GAAA,MAAA,GAAA,CAAA,GAAA,CAAA,CAAA,IAAA,EAAA,KAAM,CAAA,CAAA,CAAA,CAAA;IAUX,EAAA,SADR,EAAA,GAAA,EAsBM,OAtBN,GAsBM,CAlBJ,EAEI,KAFJ,GAEI,EADC,EAAA,CAAA,CAAM,CAAC,gBAAgB,cAAc,GAAA,CAAA,GAE1C,EAcM,OAdN,IAcM,CAbJ,EAMS,UAAA;KALP,OAAM;KACN,OAAA,EAAA,oBAAA,cAAA;KACC,SAAO;IAEL,GAAA,EAAA,EAAA,CAAA,CAAM,CAAC,gBAAgB,aAAa,GAAA,CAAA,GAEzC,EAKS,UAAA;KAJP,OAAM;KACL,SAAO;IAEL,GAAA,EAAA,EAAA,CAAA,CAAM,CAAC,gBAAgB,cAAc,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;IAOtC,EAAA,CAAA,CAAe,CAAC,MAAM,SAD9B,EAAA,GAAA,EAUM,OAVN,IAUM,CANJ,EAIE,EAAA,EAAA,GAAA;KAHC,MAAM;KACN,gBAAc;KACf,OAAM;IAER,CAAA,GAAA,EAA+C,QAAA,MAAA,EAAtC,EAAA,CAAA,CAAM,CAAC,gBAAgB,KAAK,GAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;IAK9B,EAAA,QAM2B,EAAA,IAAA,EAAA,KAPpC,EAAA,GAAA,EAQS,UAAA;;KANP,OAAM;KACL,UAAQ,CAAG,EAAA;KACX,SAAO;IAER,GAAA,CAAA,EAAwC,EAAA,CAAA,GAAA;KAA9B,MAAM;KAAK,gBAAc;IAAK,CAAA,GAAA,EAAA,MACxC,EAAG,EAAA,CAAA,CAAM,CAAC,gBAAgB,QAAQ,GAAA,CAAA,CAAA,GAAA,GAAA,EAAA;IAIpC,EAII,KAJJ,IAII,EADC,EAAA,CAAA,CAAM,CAAC,OAAO,UAAU,GAAA,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as e, I as t, N as n, R as r, S as i, at as a, ct as o, f as s, g as c, h as l, lt as u, m as d, p as f, u as p, ut as m, y as h } from "./draggable-
|
|
1
|
+
import { F as e, I as t, N as n, R as r, S as i, at as a, ct as o, f as s, g as c, h as l, lt as u, m as d, p as f, u as p, ut as m, y as h } from "./draggable-D2vo-aQI.js";
|
|
2
2
|
import { g, h as _, m as v } from "./styleConstants-C_YAPdQS.js";
|
|
3
3
|
//#region src/components/ToggleSwitch.vue?vue&type=script&setup=true&lang.ts
|
|
4
4
|
var y = { key: 0 }, b = {
|
|
@@ -83,41 +83,48 @@ var y = { key: 0 }, b = {
|
|
|
83
83
|
"stroke-width": 2
|
|
84
84
|
})) : (n(), c("span", w, m(e.label), 1))], 12, C))), 128))], 4));
|
|
85
85
|
}
|
|
86
|
-
}), E = { class: "tpl:
|
|
87
|
-
|
|
88
|
-
props: { label: {} },
|
|
89
|
-
setup(e) {
|
|
90
|
-
return (r, i) => (n(), c("div", E, [e.label ? (n(), c("label", {
|
|
91
|
-
key: 0,
|
|
92
|
-
class: o(a(g))
|
|
93
|
-
}, m(e.label), 3)) : l("", !0), t(r.$slots, "default")]));
|
|
94
|
-
}
|
|
95
|
-
}), O = { class: "tpl:flex tpl:items-stretch" }, k = [
|
|
86
|
+
}), E = { class: "tpl:flex tpl:items-stretch" }, D = [
|
|
87
|
+
"data-testid",
|
|
96
88
|
"value",
|
|
97
89
|
"min",
|
|
98
90
|
"max"
|
|
99
|
-
],
|
|
91
|
+
], O = /* @__PURE__ */ i({
|
|
100
92
|
__name: "NumberWithSuffix",
|
|
101
93
|
props: {
|
|
102
94
|
modelValue: {},
|
|
103
95
|
min: {},
|
|
104
96
|
max: {},
|
|
105
|
-
suffix: {}
|
|
97
|
+
suffix: {},
|
|
98
|
+
testid: {}
|
|
106
99
|
},
|
|
107
100
|
emits: ["update:modelValue"],
|
|
108
101
|
setup(e, { emit: t }) {
|
|
109
102
|
let r = t;
|
|
110
|
-
|
|
103
|
+
function i(e) {
|
|
104
|
+
let t = e.target;
|
|
105
|
+
t.validity?.badInput || r("update:modelValue", Number(t.value));
|
|
106
|
+
}
|
|
107
|
+
return (t, r) => (n(), c("div", E, [f("input", {
|
|
111
108
|
type: "number",
|
|
109
|
+
"data-testid": e.testid,
|
|
112
110
|
class: o(a(v)),
|
|
113
111
|
value: e.modelValue,
|
|
114
112
|
min: e.min,
|
|
115
113
|
max: e.max,
|
|
116
|
-
onInput: i
|
|
117
|
-
}, null, 42,
|
|
114
|
+
onInput: i
|
|
115
|
+
}, null, 42, D), f("span", { class: o(a(_)) }, m(e.suffix), 3)]));
|
|
116
|
+
}
|
|
117
|
+
}), k = { class: "tpl:mb-3.5" }, A = /* @__PURE__ */ i({
|
|
118
|
+
__name: "FieldRow",
|
|
119
|
+
props: { label: {} },
|
|
120
|
+
setup(e) {
|
|
121
|
+
return (r, i) => (n(), c("div", k, [e.label ? (n(), c("label", {
|
|
122
|
+
key: 0,
|
|
123
|
+
class: o(a(g))
|
|
124
|
+
}, m(e.label), 3)) : l("", !0), t(r.$slots, "default")]));
|
|
118
125
|
}
|
|
119
126
|
});
|
|
120
127
|
//#endregion
|
|
121
|
-
export { S as i,
|
|
128
|
+
export { S as i, O as n, T as r, A as t };
|
|
122
129
|
|
|
123
|
-
//# sourceMappingURL=
|
|
130
|
+
//# sourceMappingURL=FieldRow-CbcpsxZ4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldRow-CbcpsxZ4.js","names":["$slots"],"sources":["../../../src/components/ToggleSwitch.vue","../../../src/components/ToggleSwitch.vue","../../../src/components/SlidingPillSelect.vue","../../../src/components/SlidingPillSelect.vue","../../../src/components/toolbar/NumberWithSuffix.vue","../../../src/components/toolbar/NumberWithSuffix.vue","../../../src/components/toolbar/FieldRow.vue","../../../src/components/toolbar/FieldRow.vue"],"sourcesContent":["<script setup lang=\"ts\">\ndefineProps<{\n modelValue: boolean;\n label?: string;\n disabled?: boolean;\n required?: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: boolean): void;\n}>();\n</script>\n\n<template>\n <label\n :class=\"[\n 'tpl:flex tpl:items-center tpl:justify-between tpl:gap-2',\n disabled ? 'tpl:cursor-not-allowed' : 'tpl:cursor-pointer',\n ]\"\n >\n <span v-if=\"$slots.default || label || required\">\n <slot>{{ label }}</slot>\n <span v-if=\"required\" class=\"tpl:text-[var(--tpl-danger)]\"> *</span>\n </span>\n <button\n type=\"button\"\n role=\"switch\"\n :aria-checked=\"modelValue\"\n :aria-label=\"label\"\n :disabled=\"disabled\"\n :class=\"[\n 'tpl:relative tpl:inline-flex tpl:h-5 tpl:w-9 tpl:shrink-0 tpl:rounded-full tpl:border-2 tpl:border-transparent tpl:transition-colors tpl:duration-200',\n modelValue\n ? 'tpl:bg-[var(--tpl-primary)]'\n : 'tpl:bg-[var(--tpl-border)]',\n disabled\n ? 'tpl:cursor-not-allowed tpl:opacity-60'\n : 'tpl:cursor-pointer',\n ]\"\n @click=\"!disabled && emit('update:modelValue', !modelValue)\"\n >\n <span\n class=\"tpl:pointer-events-none tpl:inline-block tpl:size-4 tpl:rounded-full tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow)] tpl:transition-transform tpl:duration-200\"\n :class=\"modelValue ? 'tpl:translate-x-4' : 'tpl:translate-x-0'\"\n />\n </button>\n </label>\n</template>\n","<script setup lang=\"ts\">\ndefineProps<{\n modelValue: boolean;\n label?: string;\n disabled?: boolean;\n required?: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: boolean): void;\n}>();\n</script>\n\n<template>\n <label\n :class=\"[\n 'tpl:flex tpl:items-center tpl:justify-between tpl:gap-2',\n disabled ? 'tpl:cursor-not-allowed' : 'tpl:cursor-pointer',\n ]\"\n >\n <span v-if=\"$slots.default || label || required\">\n <slot>{{ label }}</slot>\n <span v-if=\"required\" class=\"tpl:text-[var(--tpl-danger)]\"> *</span>\n </span>\n <button\n type=\"button\"\n role=\"switch\"\n :aria-checked=\"modelValue\"\n :aria-label=\"label\"\n :disabled=\"disabled\"\n :class=\"[\n 'tpl:relative tpl:inline-flex tpl:h-5 tpl:w-9 tpl:shrink-0 tpl:rounded-full tpl:border-2 tpl:border-transparent tpl:transition-colors tpl:duration-200',\n modelValue\n ? 'tpl:bg-[var(--tpl-primary)]'\n : 'tpl:bg-[var(--tpl-border)]',\n disabled\n ? 'tpl:cursor-not-allowed tpl:opacity-60'\n : 'tpl:cursor-pointer',\n ]\"\n @click=\"!disabled && emit('update:modelValue', !modelValue)\"\n >\n <span\n class=\"tpl:pointer-events-none tpl:inline-block tpl:size-4 tpl:rounded-full tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow)] tpl:transition-transform tpl:duration-200\"\n :class=\"modelValue ? 'tpl:translate-x-4' : 'tpl:translate-x-0'\"\n />\n </button>\n </label>\n</template>\n","<script setup lang=\"ts\">\nimport type { Component } from \"vue\";\nimport { computed } from \"vue\";\n\nexport interface PillOption {\n value: string;\n label: string;\n icon?: Component;\n}\n\nconst props = defineProps<{\n options: PillOption[];\n modelValue: string;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: string): void;\n}>();\n\nconst selectedIndex = computed(() =>\n props.options.findIndex((o) => o.value === props.modelValue),\n);\n\nconst pillOffset = computed(\n () => `translateX(${Math.max(selectedIndex.value, 0) * 100}%)`,\n);\n</script>\n\n<template>\n <div\n role=\"radiogroup\"\n class=\"tpl:relative tpl:grid tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1\"\n :style=\"{\n gridTemplateColumns: `repeat(${options.length}, 1fr)`,\n backgroundColor: 'var(--tpl-bg-hover)',\n }\"\n >\n <!-- Sliding pill — hidden when modelValue matches no option,\n otherwise it would silently sit on the first option and create\n a visual mismatch with aria-checked. -->\n <div\n v-if=\"selectedIndex >= 0\"\n class=\"tpl:absolute tpl:inset-y-1 tpl:rounded-[var(--tpl-radius-sm)]\"\n :style=\"{\n left: '4px',\n width: `calc((100% - 8px) / ${options.length})`,\n transform: pillOffset,\n backgroundColor: 'var(--tpl-bg)',\n boxShadow: 'var(--tpl-shadow)',\n transition: 'transform 120ms cubic-bezier(0.16, 1, 0.3, 1)',\n }\"\n ></div>\n\n <button\n v-for=\"option in options\"\n :key=\"option.value\"\n role=\"radio\"\n :aria-checked=\"modelValue === option.value\"\n :aria-label=\"option.label\"\n class=\"tpl:relative tpl:z-10 tpl:flex tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:py-[5px] tpl:text-xs tpl:font-medium\"\n :style=\"{\n color:\n modelValue === option.value\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n transition: 'color 120ms cubic-bezier(0.16, 1, 0.3, 1)',\n }\"\n :title=\"option.label\"\n @click=\"emit('update:modelValue', option.value)\"\n >\n <component\n :is=\"option.icon\"\n v-if=\"option.icon\"\n :size=\"14\"\n :stroke-width=\"2\"\n />\n <span v-else>{{ option.label }}</span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { Component } from \"vue\";\nimport { computed } from \"vue\";\n\nexport interface PillOption {\n value: string;\n label: string;\n icon?: Component;\n}\n\nconst props = defineProps<{\n options: PillOption[];\n modelValue: string;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: string): void;\n}>();\n\nconst selectedIndex = computed(() =>\n props.options.findIndex((o) => o.value === props.modelValue),\n);\n\nconst pillOffset = computed(\n () => `translateX(${Math.max(selectedIndex.value, 0) * 100}%)`,\n);\n</script>\n\n<template>\n <div\n role=\"radiogroup\"\n class=\"tpl:relative tpl:grid tpl:rounded-[var(--tpl-radius-sm)] tpl:p-1\"\n :style=\"{\n gridTemplateColumns: `repeat(${options.length}, 1fr)`,\n backgroundColor: 'var(--tpl-bg-hover)',\n }\"\n >\n <!-- Sliding pill — hidden when modelValue matches no option,\n otherwise it would silently sit on the first option and create\n a visual mismatch with aria-checked. -->\n <div\n v-if=\"selectedIndex >= 0\"\n class=\"tpl:absolute tpl:inset-y-1 tpl:rounded-[var(--tpl-radius-sm)]\"\n :style=\"{\n left: '4px',\n width: `calc((100% - 8px) / ${options.length})`,\n transform: pillOffset,\n backgroundColor: 'var(--tpl-bg)',\n boxShadow: 'var(--tpl-shadow)',\n transition: 'transform 120ms cubic-bezier(0.16, 1, 0.3, 1)',\n }\"\n ></div>\n\n <button\n v-for=\"option in options\"\n :key=\"option.value\"\n role=\"radio\"\n :aria-checked=\"modelValue === option.value\"\n :aria-label=\"option.label\"\n class=\"tpl:relative tpl:z-10 tpl:flex tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:py-[5px] tpl:text-xs tpl:font-medium\"\n :style=\"{\n color:\n modelValue === option.value\n ? 'var(--tpl-primary)'\n : 'var(--tpl-text-muted)',\n transition: 'color 120ms cubic-bezier(0.16, 1, 0.3, 1)',\n }\"\n :title=\"option.label\"\n @click=\"emit('update:modelValue', option.value)\"\n >\n <component\n :is=\"option.icon\"\n v-if=\"option.icon\"\n :size=\"14\"\n :stroke-width=\"2\"\n />\n <span v-else>{{ option.label }}</span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n inputGroupInputClass,\n inputSuffixClass,\n} from \"../../constants/styleConstants\";\n\ndefineProps<{\n modelValue: number;\n min?: number;\n max?: number;\n suffix: string;\n /**\n * `data-testid` for the `<input>`. A plain attribute on this component falls\n * through to the wrapping `<div>`, which is not the element a test reads a\n * value from.\n */\n testid?: string;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: number): void;\n}>();\n\nfunction onInput(event: Event): void {\n const el = event.target as HTMLInputElement;\n // A number input reports in-progress unparseable content as an EMPTY string\n // with `badInput` set, so `Number(el.value)` is 0 and indistinguishable from\n // a cleared field. Emitting here overwrites the real value with 0 before the\n // number being typed ever arrives. Typing \"-\" is the everyday case: measured\n // in Chrome, it fires `input` with value \"\" + badInput true, and only the\n // following \"5\" fires again with \"-5\". `min` does not help — it drives\n // constraint validation, not the reported value.\n if (el.validity?.badInput) return;\n emit(\"update:modelValue\", Number(el.value));\n}\n</script>\n\n<template>\n <div class=\"tpl:flex tpl:items-stretch\">\n <input\n type=\"number\"\n :data-testid=\"testid\"\n :class=\"inputGroupInputClass\"\n :value=\"modelValue\"\n :min=\"min\"\n :max=\"max\"\n @input=\"onInput\"\n />\n <span :class=\"inputSuffixClass\">{{ suffix }}</span>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {\n inputGroupInputClass,\n inputSuffixClass,\n} from \"../../constants/styleConstants\";\n\ndefineProps<{\n modelValue: number;\n min?: number;\n max?: number;\n suffix: string;\n /**\n * `data-testid` for the `<input>`. A plain attribute on this component falls\n * through to the wrapping `<div>`, which is not the element a test reads a\n * value from.\n */\n testid?: string;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: number): void;\n}>();\n\nfunction onInput(event: Event): void {\n const el = event.target as HTMLInputElement;\n // A number input reports in-progress unparseable content as an EMPTY string\n // with `badInput` set, so `Number(el.value)` is 0 and indistinguishable from\n // a cleared field. Emitting here overwrites the real value with 0 before the\n // number being typed ever arrives. Typing \"-\" is the everyday case: measured\n // in Chrome, it fires `input` with value \"\" + badInput true, and only the\n // following \"5\" fires again with \"-5\". `min` does not help — it drives\n // constraint validation, not the reported value.\n if (el.validity?.badInput) return;\n emit(\"update:modelValue\", Number(el.value));\n}\n</script>\n\n<template>\n <div class=\"tpl:flex tpl:items-stretch\">\n <input\n type=\"number\"\n :data-testid=\"testid\"\n :class=\"inputGroupInputClass\"\n :value=\"modelValue\"\n :min=\"min\"\n :max=\"max\"\n @input=\"onInput\"\n />\n <span :class=\"inputSuffixClass\">{{ suffix }}</span>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { labelClass } from \"../../constants/styleConstants\";\n\ndefineProps<{\n label?: string;\n}>();\n</script>\n\n<template>\n <div class=\"tpl:mb-3.5\">\n <label v-if=\"label\" :class=\"labelClass\">{{ label }}</label>\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { labelClass } from \"../../constants/styleConstants\";\n\ndefineProps<{\n label?: string;\n}>();\n</script>\n\n<template>\n <div class=\"tpl:mb-3.5\">\n <label v-if=\"label\" :class=\"labelClass\">{{ label }}</label>\n <slot />\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { E as e, F as t, N as n, R as r, S as i, at as a, b as o, ct as s, f as c, g as l, h as u, m as d, p as f, u as p, ut as m, y as h } from "./draggable-
|
|
2
|
-
import { h as g, z as _ } from "./keys-
|
|
3
|
-
import { t as v } from "./useI18n-
|
|
4
|
-
import { Ht as y, Mt as b, dt as x, r as S, st as C, u as w } from "./icons-
|
|
5
|
-
import { t as T } from "./useScrollToBlock-
|
|
1
|
+
import { E as e, F as t, N as n, R as r, S as i, at as a, b as o, ct as s, f as c, g as l, h as u, m as d, p as f, u as p, ut as m, y as h } from "./draggable-D2vo-aQI.js";
|
|
2
|
+
import { h as g, z as _ } from "./keys-BJ770Mwm.js";
|
|
3
|
+
import { t as v } from "./useI18n-DIhawILp.js";
|
|
4
|
+
import { Ht as y, Mt as b, dt as x, r as S, st as C, u as w } from "./icons-BTdLXRXn.js";
|
|
5
|
+
import { t as T } from "./useScrollToBlock-KcSAuXKz.js";
|
|
6
6
|
//#region src/components/sidebar/IssuesPanel.vue?vue&type=script&setup=true&lang.ts
|
|
7
7
|
var E = { class: "tpl:flex tpl:flex-col tpl:gap-4 tpl:p-4" }, D = { class: "tpl:flex tpl:items-center tpl:gap-2" }, O = { class: "tpl:m-0 tpl:text-sm tpl:font-semibold tpl:text-[var(--tpl-text)]" }, k = ["title"], A = {
|
|
8
8
|
key: 0,
|
|
@@ -97,4 +97,4 @@ var E = { class: "tpl:flex tpl:flex-col tpl:gap-4 tpl:p-4" }, D = { class: "tpl:
|
|
|
97
97
|
//#endregion
|
|
98
98
|
export { z as default };
|
|
99
99
|
|
|
100
|
-
//# sourceMappingURL=IssuesPanel-
|
|
100
|
+
//# sourceMappingURL=IssuesPanel-iC2hgrXx.js.map
|