@mhmo91/schmancy 0.10.5 → 0.10.6
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/custom-elements.json +4 -707
- package/dist/agent/{flow-CaPi2G8y.js.map → flow-3RrZM-e7.js.map} +1 -1
- package/dist/agent/schmancy.agent.js +2807 -4687
- package/dist/agent/schmancy.agent.js.map +1 -1
- package/dist/agent/schmancy.manifest.json +6 -471
- package/dist/agent/{vendor-jsqr-r7GNh4P3.js.map → vendor-jsqr-BUVwyoGC.js.map} +1 -1
- package/dist/agent/{vendor-material-color-Be96dpGE.js.map → vendor-material-color-33Mj762T.js.map} +1 -1
- package/dist/{area-D5haQE-J.js → area-CIZZ5tbB.js} +1 -1
- package/dist/{area-D5haQE-J.js.map → area-CIZZ5tbB.js.map} +1 -1
- package/dist/{area-CSQdhCBF.cjs → area-oZjYJlUy.cjs} +1 -1
- package/dist/{area-CSQdhCBF.cjs.map → area-oZjYJlUy.cjs.map} +1 -1
- package/dist/area.cjs +1 -1
- package/dist/area.js +1 -1
- package/dist/{autocomplete-DtyjZJ1E.js → autocomplete-C1oDLuol.js} +2 -2
- package/dist/{autocomplete-DtyjZJ1E.js.map → autocomplete-C1oDLuol.js.map} +1 -1
- package/dist/{autocomplete-B_bJXUjm.cjs → autocomplete-X20i6D62.cjs} +1 -1
- package/dist/{autocomplete-B_bJXUjm.cjs.map → autocomplete-X20i6D62.cjs.map} +1 -1
- package/dist/autocomplete.cjs +1 -1
- package/dist/autocomplete.js +1 -1
- package/dist/avatar.cjs +1 -1
- package/dist/avatar.js +2 -2
- package/dist/badge.cjs +1 -1
- package/dist/badge.js +1 -1
- package/dist/{boat-BJLCp-Hv.cjs → boat-CUx58Gwe.cjs} +1 -1
- package/dist/{boat-BJLCp-Hv.cjs.map → boat-CUx58Gwe.cjs.map} +1 -1
- package/dist/{boat-MT8bRT8u.js → boat-CpE0yAlK.js} +1 -1
- package/dist/{boat-MT8bRT8u.js.map → boat-CpE0yAlK.js.map} +1 -1
- package/dist/boat.cjs +1 -1
- package/dist/boat.js +1 -1
- package/dist/breadcrumb.cjs +1 -1
- package/dist/breadcrumb.js +1 -1
- package/dist/{busy-6BqWGryX.js → busy-C9n-DUY4.js} +1 -1
- package/dist/{busy-6BqWGryX.js.map → busy-C9n-DUY4.js.map} +1 -1
- package/dist/{busy-DSF2E-zy.cjs → busy-D1DKZhgV.cjs} +1 -1
- package/dist/{busy-DSF2E-zy.cjs.map → busy-D1DKZhgV.cjs.map} +1 -1
- package/dist/busy.cjs +1 -1
- package/dist/busy.js +1 -1
- package/dist/button.cjs +1 -1
- package/dist/button.js +1 -1
- package/dist/{card-CvuVha-W.js → card-B3hN-qzk.js} +1 -1
- package/dist/{card-CvuVha-W.js.map → card-B3hN-qzk.js.map} +1 -1
- package/dist/{card-DnKnaHzf.cjs → card-DZJ7qjf2.cjs} +1 -1
- package/dist/{card-DnKnaHzf.cjs.map → card-DZJ7qjf2.cjs.map} +1 -1
- package/dist/card.cjs +1 -1
- package/dist/card.js +1 -1
- package/dist/charts.cjs +1 -1
- package/dist/charts.js +1 -1
- package/dist/{checkbox-QDRsE8cp.js → checkbox-CvmB1ev9.js} +1 -1
- package/dist/{checkbox-QDRsE8cp.js.map → checkbox-CvmB1ev9.js.map} +1 -1
- package/dist/{checkbox-D3u8Wm9r.cjs → checkbox-DapdzDow.cjs} +1 -1
- package/dist/{checkbox-D3u8Wm9r.cjs.map → checkbox-DapdzDow.cjs.map} +1 -1
- package/dist/checkbox.cjs +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/{chips-CMoQzop1.cjs → chips-7g6mWRuh.cjs} +1 -1
- package/dist/{chips-CMoQzop1.cjs.map → chips-7g6mWRuh.cjs.map} +1 -1
- package/dist/{chips-Dy9vx8JS.js → chips-C8Y3_3ke.js} +2 -2
- package/dist/{chips-Dy9vx8JS.js.map → chips-C8Y3_3ke.js.map} +1 -1
- package/dist/chips.cjs +1 -1
- package/dist/chips.js +2 -2
- package/dist/connectivity.cjs +1 -1
- package/dist/connectivity.js +1 -1
- package/dist/content-drawer.cjs +1 -1
- package/dist/content-drawer.js +1 -1
- package/dist/{date-range-Boesjlic.js → date-range-DdcaPX7C.js} +2 -2
- package/dist/{date-range-Boesjlic.js.map → date-range-DdcaPX7C.js.map} +1 -1
- package/dist/{date-range-B2NuihKA.cjs → date-range-ZfUl4duV.cjs} +1 -1
- package/dist/{date-range-B2NuihKA.cjs.map → date-range-ZfUl4duV.cjs.map} +1 -1
- package/dist/{date-range-inline-BI6_4Ahl.cjs → date-range-inline-D-d7N6bh.cjs} +1 -1
- package/dist/{date-range-inline-BI6_4Ahl.cjs.map → date-range-inline-D-d7N6bh.cjs.map} +1 -1
- package/dist/{date-range-inline-DBuND2pc.js → date-range-inline-QQmIWhZ4.js} +1 -1
- package/dist/{date-range-inline-DBuND2pc.js.map → date-range-inline-QQmIWhZ4.js.map} +1 -1
- package/dist/date-range-inline.cjs +1 -1
- package/dist/date-range-inline.js +1 -1
- package/dist/date-range.cjs +1 -1
- package/dist/date-range.js +1 -1
- package/dist/delay.cjs +1 -1
- package/dist/delay.js +2 -2
- package/dist/{details-BRs_z5-k.cjs → details-3rL6UQU8.cjs} +1 -1
- package/dist/{details-BRs_z5-k.cjs.map → details-3rL6UQU8.cjs.map} +1 -1
- package/dist/{details-BrGrUTGC.js → details-Dpjh-XnJ.js} +1 -1
- package/dist/{details-BrGrUTGC.js.map → details-Dpjh-XnJ.js.map} +1 -1
- package/dist/details.cjs +1 -1
- package/dist/details.js +1 -1
- package/dist/{divider-W3TiDasp.js → divider-BdfEKQsH.js} +1 -1
- package/dist/{divider-W3TiDasp.js.map → divider-BdfEKQsH.js.map} +1 -1
- package/dist/{divider-BOxQ2T9h.cjs → divider-CutXDz3F.cjs} +1 -1
- package/dist/{divider-BOxQ2T9h.cjs.map → divider-CutXDz3F.cjs.map} +1 -1
- package/dist/divider.cjs +1 -1
- package/dist/divider.js +1 -1
- package/dist/dropdown.cjs +1 -1
- package/dist/dropdown.js +1 -1
- package/dist/{expand-CnccBF91.cjs → expand-DM6zfZf7.cjs} +1 -1
- package/dist/{expand-CnccBF91.cjs.map → expand-DM6zfZf7.cjs.map} +1 -1
- package/dist/{expand-Pu8fZ0jZ.js → expand-DrgMPJbu.js} +2 -2
- package/dist/{expand-Pu8fZ0jZ.js.map → expand-DrgMPJbu.js.map} +1 -1
- package/dist/expand.cjs +1 -1
- package/dist/expand.js +1 -1
- package/dist/{extra-DxEWs41z.js → extra-B6gFu4_1.js} +1 -1
- package/dist/{extra-DxEWs41z.js.map → extra-B6gFu4_1.js.map} +1 -1
- package/dist/{extra-B8IPs6gG.cjs → extra-DJRYaOXe.cjs} +1 -1
- package/dist/{extra-B8IPs6gG.cjs.map → extra-DJRYaOXe.cjs.map} +1 -1
- package/dist/extra.cjs +1 -1
- package/dist/extra.js +1 -1
- package/dist/{float-WCVdp3um.js → float-1iihPek5.js} +1 -1
- package/dist/{float-WCVdp3um.js.map → float-1iihPek5.js.map} +1 -1
- package/dist/{float-BRKa-P6Z.cjs → float-Ckyk85XG.cjs} +1 -1
- package/dist/{float-BRKa-P6Z.cjs.map → float-Ckyk85XG.cjs.map} +1 -1
- package/dist/float.cjs +1 -1
- package/dist/float.js +1 -1
- package/dist/{form-CI59gad4.js.map → form-BF1c3Dk1.js.map} +1 -1
- package/dist/{form-B2qudx_q.cjs.map → form-DeO5XX3b.cjs.map} +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.js +1 -1
- package/dist/handover/agent-runtime-followups.md +1 -1
- package/dist/handover/agent-runtime-v1.md +3 -3
- package/dist/{hashContent-a8uVr3xs.js.map → hashContent-BU6jl5ih.js.map} +1 -1
- package/dist/{hashContent-ejkBgDnN.cjs.map → hashContent-Bobsobip.cjs.map} +1 -1
- package/dist/{icons-DXEbmg-O.cjs → icons-CV-fiGcW.cjs} +1 -1
- package/dist/{icons-DXEbmg-O.cjs.map → icons-CV-fiGcW.cjs.map} +1 -1
- package/dist/{icons-C0ufCcdp.js → icons-DUkcTZAY.js} +1 -1
- package/dist/{icons-C0ufCcdp.js.map → icons-DUkcTZAY.js.map} +1 -1
- package/dist/icons.cjs +1 -1
- package/dist/icons.js +1 -1
- package/dist/{iframe-c9lGxw7x.js → iframe-C9tj7F6Y.js} +1 -1
- package/dist/{iframe-c9lGxw7x.js.map → iframe-C9tj7F6Y.js.map} +1 -1
- package/dist/{iframe-C6RVODkW.cjs → iframe-DF97oGtZ.cjs} +1 -1
- package/dist/{iframe-C6RVODkW.cjs.map → iframe-DF97oGtZ.cjs.map} +1 -1
- package/dist/iframe.cjs +1 -1
- package/dist/iframe.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +70 -72
- package/dist/{input-Pmj_bH37.js → input-DE7x223Y.js} +1 -1
- package/dist/{input-Pmj_bH37.js.map → input-DE7x223Y.js.map} +1 -1
- package/dist/{input-B4HM-9-H.cjs → input-TW9G3n7X.cjs} +1 -1
- package/dist/{input-B4HM-9-H.cjs.map → input-TW9G3n7X.cjs.map} +1 -1
- package/dist/{input-chip-BIGgd_7w.js → input-chip-BdoaVw_D.js} +1 -1
- package/dist/{input-chip-BIGgd_7w.js.map → input-chip-BdoaVw_D.js.map} +1 -1
- package/dist/{input-chip-BoDisY6c.cjs → input-chip-Do48eI5r.cjs} +1 -1
- package/dist/{input-chip-BoDisY6c.cjs.map → input-chip-Do48eI5r.cjs.map} +1 -1
- package/dist/input.cjs +1 -1
- package/dist/input.js +1 -1
- package/dist/json.cjs +1 -1
- package/dist/json.js +2 -2
- package/dist/kbd.cjs +1 -1
- package/dist/kbd.js +1 -1
- package/dist/layout.cjs +1 -1
- package/dist/layout.js +1 -1
- package/dist/{lightbox-K1eJTYXP.js → lightbox-DcutIyjx.js} +2 -2
- package/dist/{lightbox-K1eJTYXP.js.map → lightbox-DcutIyjx.js.map} +1 -1
- package/dist/{lightbox-DK1vDKm3.cjs → lightbox-sPfnYzjJ.cjs} +1 -1
- package/dist/{lightbox-DK1vDKm3.cjs.map → lightbox-sPfnYzjJ.cjs.map} +1 -1
- package/dist/lightbox.cjs +1 -1
- package/dist/lightbox.js +1 -1
- package/dist/{list-Ds0Nv1y5.js → list-BWrtrdgs.js} +1 -1
- package/dist/{list-Ds0Nv1y5.js.map → list-BWrtrdgs.js.map} +1 -1
- package/dist/{list-CEuVqAxN.cjs → list-C4vasUly.cjs} +1 -1
- package/dist/{list-CEuVqAxN.cjs.map → list-C4vasUly.cjs.map} +1 -1
- package/dist/list.cjs +1 -1
- package/dist/list.js +1 -1
- package/dist/{map-BrBSrIqg.cjs → map-BAQ9FEB6.cjs} +1 -1
- package/dist/{map-BrBSrIqg.cjs.map → map-BAQ9FEB6.cjs.map} +1 -1
- package/dist/{map-1uwxxvBa.js → map-CEreveeI.js} +1 -1
- package/dist/{map-1uwxxvBa.js.map → map-CEreveeI.js.map} +1 -1
- package/dist/map.cjs +1 -1
- package/dist/map.js +1 -1
- package/dist/{menu-Bly30Nje.cjs → menu-3yXDZusj.cjs} +1 -1
- package/dist/{menu-Bly30Nje.cjs.map → menu-3yXDZusj.cjs.map} +1 -1
- package/dist/{menu-L8MK1ma5.js → menu-CxChOxWT.js} +2 -2
- package/dist/{menu-L8MK1ma5.js.map → menu-CxChOxWT.js.map} +1 -1
- package/dist/menu.cjs +1 -1
- package/dist/menu.js +1 -1
- package/dist/mixins-Db7gjDah.cjs +298 -0
- package/dist/{mixins-CAb0b03r.cjs.map → mixins-Db7gjDah.cjs.map} +1 -1
- package/dist/mixins-Dw6hVfy-.js +627 -0
- package/dist/{mixins-B34UxxCe.js.map → mixins-Dw6hVfy-.js.map} +1 -1
- package/dist/mixins.cjs +1 -1
- package/dist/mixins.js +1 -1
- package/dist/nav-drawer.cjs +1 -1
- package/dist/nav-drawer.js +1 -1
- package/dist/navigation-bar.cjs +1 -1
- package/dist/navigation-bar.js +1 -1
- package/dist/navigation-rail.cjs +1 -1
- package/dist/navigation-rail.js +1 -1
- package/dist/{notification-7fSbk8hm.cjs → notification-DKYy9qVe.cjs} +1 -1
- package/dist/{notification-7fSbk8hm.cjs.map → notification-DKYy9qVe.cjs.map} +1 -1
- package/dist/{notification-DB25M-qo.js → notification-ycbUBbOu.js} +2 -2
- package/dist/{notification-DB25M-qo.js.map → notification-ycbUBbOu.js.map} +1 -1
- package/dist/notification.cjs +1 -1
- package/dist/notification.js +1 -1
- package/dist/{option-DDHa25k5.js → option-DtOhMd3k.js} +1 -1
- package/dist/{option-DDHa25k5.js.map → option-DtOhMd3k.js.map} +1 -1
- package/dist/{option-HF9Xqbuq.cjs → option-zgVge3BH.cjs} +1 -1
- package/dist/{option-HF9Xqbuq.cjs.map → option-zgVge3BH.cjs.map} +1 -1
- package/dist/option.cjs +1 -1
- package/dist/option.js +1 -1
- package/dist/{overlay-stack-CCiTaf_C.js.map → overlay-stack-DCDS17uj.js.map} +1 -1
- package/dist/{overlay-stack-CFGiYf34.cjs.map → overlay-stack-DPIe_aYv.cjs.map} +1 -1
- package/dist/overlay.cjs +1 -1
- package/dist/{overlay.confirm-body-BDG94R0x.js → overlay.confirm-body-AFqYBqrI.js} +1 -1
- package/dist/{overlay.confirm-body-BDG94R0x.js.map → overlay.confirm-body-AFqYBqrI.js.map} +1 -1
- package/dist/{overlay.confirm-body-b4Nx_OVf.cjs → overlay.confirm-body-DctQLDao.cjs} +1 -1
- package/dist/{overlay.confirm-body-b4Nx_OVf.cjs.map → overlay.confirm-body-DctQLDao.cjs.map} +1 -1
- package/dist/overlay.js +3 -3
- package/dist/{overlay.service-BUCuZa6V.js → overlay.service-B9On2-Aa.js} +2 -2
- package/dist/{overlay.service-BUCuZa6V.js.map → overlay.service-B9On2-Aa.js.map} +1 -1
- package/dist/{overlay.service-CRHZZY9F.cjs → overlay.service-k2nCE4pi.cjs} +1 -1
- package/dist/{overlay.service-CRHZZY9F.cjs.map → overlay.service-k2nCE4pi.cjs.map} +1 -1
- package/dist/page.cjs +1 -1
- package/dist/page.js +2 -2
- package/dist/{payment-card-form-C4jb-OdM.js → payment-card-form-Be1-OVlL.js} +1 -1
- package/dist/{payment-card-form-C4jb-OdM.js.map → payment-card-form-Be1-OVlL.js.map} +1 -1
- package/dist/{payment-card-form-WEx4CscR.cjs → payment-card-form-CNnGePG4.cjs} +1 -1
- package/dist/{payment-card-form-WEx4CscR.cjs.map → payment-card-form-CNnGePG4.cjs.map} +1 -1
- package/dist/payment-card-form.cjs +1 -1
- package/dist/payment-card-form.js +1 -1
- package/dist/{progress-CqOyMM4i.js → progress-BFWzmTlz.js} +1 -1
- package/dist/{progress-CqOyMM4i.js.map → progress-BFWzmTlz.js.map} +1 -1
- package/dist/{progress-54R4QRgW.cjs → progress-C4TGG2eN.cjs} +1 -1
- package/dist/{progress-54R4QRgW.cjs.map → progress-C4TGG2eN.cjs.map} +1 -1
- package/dist/progress.cjs +1 -1
- package/dist/progress.js +1 -1
- package/dist/qr-scanner.cjs +1 -1
- package/dist/qr-scanner.js +1 -1
- package/dist/{radio-group-B4zbBIZF.js → radio-group-DTNAW5dd.js} +1 -1
- package/dist/{radio-group-B4zbBIZF.js.map → radio-group-DTNAW5dd.js.map} +1 -1
- package/dist/{radio-group-BJqZpYVy.cjs → radio-group-xLRp1g57.cjs} +1 -1
- package/dist/{radio-group-BJqZpYVy.cjs.map → radio-group-xLRp1g57.cjs.map} +1 -1
- package/dist/radio-group.cjs +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/range.cjs +1 -1
- package/dist/range.js +1 -1
- package/dist/{rxjs-utils-BXpvHN4-.js.map → rxjs-utils-BK8VMe3K.js.map} +1 -1
- package/dist/{rxjs-utils-CaC-tdot.cjs.map → rxjs-utils-DhOKenkS.cjs.map} +1 -1
- package/dist/rxjs-utils.cjs +1 -1
- package/dist/rxjs-utils.js +1 -1
- package/dist/{scroll-CYm6Krus.js → scroll-BCmdqSQU.js} +1 -1
- package/dist/{scroll-CYm6Krus.js.map → scroll-BCmdqSQU.js.map} +1 -1
- package/dist/{scroll-iSRovYYt.cjs → scroll-Bdgb-vRy.cjs} +1 -1
- package/dist/{scroll-iSRovYYt.cjs.map → scroll-Bdgb-vRy.cjs.map} +1 -1
- package/dist/{select-1WHseXP6.js → select-COGARE0b.js} +2 -2
- package/dist/{select-1WHseXP6.js.map → select-COGARE0b.js.map} +1 -1
- package/dist/{select-DiQHtQJN.cjs → select-Cv5t_PT3.cjs} +1 -1
- package/dist/{select-DiQHtQJN.cjs.map → select-Cv5t_PT3.cjs.map} +1 -1
- package/dist/select.cjs +1 -1
- package/dist/select.js +1 -1
- package/dist/skeleton.cjs +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/skills/INDEX.md +1 -4
- package/dist/skills/schmancy/INDEX.md +1 -4
- package/dist/slider.cjs +1 -1
- package/dist/slider.js +1 -1
- package/dist/{splash-screen-CJL8DGDe.cjs → splash-screen-B8rFbjqT.cjs} +1 -1
- package/dist/{splash-screen-CJL8DGDe.cjs.map → splash-screen-B8rFbjqT.cjs.map} +1 -1
- package/dist/{splash-screen-BwvtKMdN.js → splash-screen-DbGbGttg.js} +1 -1
- package/dist/{splash-screen-BwvtKMdN.js.map → splash-screen-DbGbGttg.js.map} +1 -1
- package/dist/splash-screen.cjs +1 -1
- package/dist/splash-screen.js +1 -1
- package/dist/{src-UaZeROcW.js → src-YRir9pOP.js} +37 -39
- package/dist/{src-UaZeROcW.js.map → src-YRir9pOP.js.map} +1 -1
- package/dist/{src-Bwr2NR0A.cjs → src-b8D-Ec-Q.cjs} +1 -1
- package/dist/{src-Bwr2NR0A.cjs.map → src-b8D-Ec-Q.cjs.map} +1 -1
- package/dist/steps.cjs +1 -1
- package/dist/steps.js +1 -1
- package/dist/{surface-DPUkQ3OL.js → surface-BE7sGTBt.js} +1 -1
- package/dist/{surface-DPUkQ3OL.js.map → surface-BE7sGTBt.js.map} +1 -1
- package/dist/{surface-DE5iuI8e.cjs → surface-BvudRtf5.cjs} +1 -1
- package/dist/{surface-DE5iuI8e.cjs.map → surface-BvudRtf5.cjs.map} +1 -1
- package/dist/surface.cjs +1 -1
- package/dist/surface.js +1 -1
- package/dist/switch.cjs +1 -1
- package/dist/switch.js +1 -1
- package/dist/table.cjs +1 -1
- package/dist/table.js +1 -1
- package/dist/{tabs-CsDQ72Qk.cjs → tabs-C0XKld1Z.cjs} +1 -1
- package/dist/{tabs-CsDQ72Qk.cjs.map → tabs-C0XKld1Z.cjs.map} +1 -1
- package/dist/{tabs-B2XEQPQl.js → tabs-DIzCRsA3.js} +1 -1
- package/dist/{tabs-B2XEQPQl.js.map → tabs-DIzCRsA3.js.map} +1 -1
- package/dist/tabs.cjs +1 -1
- package/dist/tabs.js +1 -1
- package/dist/teleport.cjs +1 -1
- package/dist/teleport.js +1 -1
- package/dist/{textarea-aeAP9cDG.cjs → textarea-BCDCGCJd.cjs} +1 -1
- package/dist/{textarea-aeAP9cDG.cjs.map → textarea-BCDCGCJd.cjs.map} +1 -1
- package/dist/{textarea-C_ps0lL-.js → textarea-UbZzBwqm.js} +1 -1
- package/dist/{textarea-C_ps0lL-.js.map → textarea-UbZzBwqm.js.map} +1 -1
- package/dist/textarea.cjs +1 -1
- package/dist/textarea.js +1 -1
- package/dist/{theme-DAYTVw13.cjs → theme-CIsI-sFj.cjs} +1 -1
- package/dist/{theme-DAYTVw13.cjs.map → theme-CIsI-sFj.cjs.map} +1 -1
- package/dist/{theme-DAx1iRNr.js → theme-Qh-yPEPL.js} +2 -2
- package/dist/{theme-DAx1iRNr.js.map → theme-Qh-yPEPL.js.map} +1 -1
- package/dist/{theme-button-BrHkzCtj.js → theme-button-CjTnfs9x.js} +1 -1
- package/dist/{theme-button-BrHkzCtj.js.map → theme-button-CjTnfs9x.js.map} +1 -1
- package/dist/{theme-button-LsMKY_N_.cjs → theme-button-Dv1D_Vil.cjs} +1 -1
- package/dist/{theme-button-LsMKY_N_.cjs.map → theme-button-Dv1D_Vil.cjs.map} +1 -1
- package/dist/theme-button.cjs +1 -1
- package/dist/theme-button.js +1 -1
- package/dist/theme.cjs +1 -1
- package/dist/{theme.interface-DESopuZS.cjs.map → theme.interface-BeW-sz_g.cjs.map} +1 -1
- package/dist/{theme.interface-C_034TxG.js.map → theme.interface-v7SkAnDH.js.map} +1 -1
- package/dist/theme.js +3 -3
- package/dist/timeline.cjs +1 -1
- package/dist/timeline.js +1 -1
- package/dist/tree.cjs +1 -1
- package/dist/tree.js +1 -1
- package/dist/typography.cjs +1 -1
- package/dist/typography.js +1 -1
- package/dist/{utils-BzFQfaIr.js → utils-BfOze6Tk.js} +1 -1
- package/dist/{utils-BzFQfaIr.js.map → utils-BfOze6Tk.js.map} +1 -1
- package/dist/{utils-oLBkMvor.cjs → utils-CJ9y2Jz9.cjs} +1 -1
- package/dist/{utils-oLBkMvor.cjs.map → utils-CJ9y2Jz9.cjs.map} +1 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +2 -2
- package/dist/visually-hidden.cjs +1 -1
- package/dist/visually-hidden.js +1 -1
- package/dist/{window-BJrKS6Zr.cjs → window-9HOUXrTU.cjs} +1 -1
- package/dist/{window-BJrKS6Zr.cjs.map → window-9HOUXrTU.cjs.map} +1 -1
- package/dist/{window-CyDuTN80.js → window-B_55dzk0.js} +2 -2
- package/dist/{window-CyDuTN80.js.map → window-B_55dzk0.js.map} +1 -1
- package/dist/window.cjs +1 -1
- package/dist/window.js +1 -1
- package/package.json +1 -2
- package/skills/schmancy/INDEX.md +1 -4
- package/src/index.ts +0 -2
- package/types/src/index.d.ts +0 -2
- package/dist/agent/vendor-highlight-CHJZQQB7.js +0 -2178
- package/dist/agent/vendor-highlight-CHJZQQB7.js.map +0 -1
- package/dist/code-highlight-Ddp0oZnm.cjs +0 -190
- package/dist/code-highlight-Ddp0oZnm.cjs.map +0 -1
- package/dist/code-highlight-DtE2-ObF.js +0 -296
- package/dist/code-highlight-DtE2-ObF.js.map +0 -1
- package/dist/code-highlight.cjs +0 -1
- package/dist/code-highlight.js +0 -2
- package/dist/mailbox-CDWqbVvZ.cjs +0 -1140
- package/dist/mailbox-CDWqbVvZ.cjs.map +0 -1
- package/dist/mailbox-DD2How0H.js +0 -1607
- package/dist/mailbox-DD2How0H.js.map +0 -1
- package/dist/mailbox.cjs +0 -1
- package/dist/mailbox.js +0 -2
- package/dist/mixins-B34UxxCe.js +0 -627
- package/dist/mixins-CAb0b03r.cjs +0 -298
- package/dist/skills/code-highlight.md +0 -47
- package/dist/skills/mailbox.md +0 -102
- package/dist/skills/schmancy/code-highlight.md +0 -47
- package/dist/skills/schmancy/mailbox.md +0 -102
- package/skills/schmancy/code-highlight.md +0 -47
- package/skills/schmancy/mailbox.md +0 -102
- package/src/code-highlight/code-highlight.ts +0 -345
- package/src/code-highlight/code-preview.ts +0 -125
- package/src/code-highlight/index.ts +0 -3
- package/src/mailbox/README.md +0 -128
- package/src/mailbox/email-editor.ts +0 -1076
- package/src/mailbox/email-layout-selector.ts +0 -58
- package/src/mailbox/email-recipients.ts +0 -599
- package/src/mailbox/email-template-picker.ts +0 -303
- package/src/mailbox/email-viewer.ts +0 -717
- package/src/mailbox/index.ts +0 -31
- package/src/mailbox/mailbox.ts +0 -364
- package/src/mailbox/types.ts +0 -180
- package/types/src/code-highlight/code-highlight.d.ts +0 -49
- package/types/src/code-highlight/code-preview.d.ts +0 -30
- package/types/src/code-highlight/index.d.ts +0 -3
- package/types/src/mailbox/email-editor.d.ts +0 -101
- package/types/src/mailbox/email-layout-selector.d.ts +0 -18
- package/types/src/mailbox/email-recipients.d.ts +0 -122
- package/types/src/mailbox/email-template-picker.d.ts +0 -54
- package/types/src/mailbox/email-viewer.d.ts +0 -86
- package/types/src/mailbox/index.d.ts +0 -12
- package/types/src/mailbox/mailbox.d.ts +0 -82
- package/types/src/mailbox/types.d.ts +0 -176
- /package/dist/agent/{flow-CaPi2G8y.js → flow-3RrZM-e7.js} +0 -0
- /package/dist/agent/{vendor-jsqr-r7GNh4P3.js → vendor-jsqr-BUVwyoGC.js} +0 -0
- /package/dist/agent/{vendor-material-color-Be96dpGE.js → vendor-material-color-33Mj762T.js} +0 -0
- /package/dist/{form-CI59gad4.js → form-BF1c3Dk1.js} +0 -0
- /package/dist/{form-B2qudx_q.cjs → form-DeO5XX3b.cjs} +0 -0
- /package/dist/{hashContent-a8uVr3xs.js → hashContent-BU6jl5ih.js} +0 -0
- /package/dist/{hashContent-ejkBgDnN.cjs → hashContent-Bobsobip.cjs} +0 -0
- /package/dist/{overlay-stack-CCiTaf_C.js → overlay-stack-DCDS17uj.js} +0 -0
- /package/dist/{overlay-stack-CFGiYf34.cjs → overlay-stack-DPIe_aYv.cjs} +0 -0
- /package/dist/{rxjs-utils-BXpvHN4-.js → rxjs-utils-BK8VMe3K.js} +0 -0
- /package/dist/{rxjs-utils-CaC-tdot.cjs → rxjs-utils-DhOKenkS.cjs} +0 -0
- /package/dist/{theme.interface-DESopuZS.cjs → theme.interface-BeW-sz_g.cjs} +0 -0
- /package/dist/{theme.interface-C_034TxG.js → theme.interface-v7SkAnDH.js} +0 -0
|
@@ -1,1076 +0,0 @@
|
|
|
1
|
-
import { SchmancyElement } from '@mixins/index'
|
|
2
|
-
import { css, html } from 'lit'
|
|
3
|
-
import { customElement, property, state } from 'lit/decorators.js'
|
|
4
|
-
import { createRef, ref } from 'lit/directives/ref.js'
|
|
5
|
-
import { repeat } from 'lit/directives/repeat.js'
|
|
6
|
-
import { when } from 'lit/directives/when.js'
|
|
7
|
-
import { fromEvent, takeUntil } from 'rxjs'
|
|
8
|
-
import { $notify } from '../notification'
|
|
9
|
-
import { show } from '../overlay/overlay.service'
|
|
10
|
-
import './email-layout-selector'
|
|
11
|
-
import SchmancyTextarea from '../textarea/textarea'
|
|
12
|
-
import { SchmancyEmailTemplatePicker } from './email-template-picker'
|
|
13
|
-
import type { EmailAttachment, EmailComposeConfig, EmailTemplate } from './types'
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Email editor component with rich text formatting and file attachments
|
|
17
|
-
*
|
|
18
|
-
* Features:
|
|
19
|
-
* - Markdown formatting toolbar
|
|
20
|
-
* - Image upload and insertion
|
|
21
|
-
* - File attachments with drag & drop
|
|
22
|
-
* - Layout templates (columns, sidebars, image rows)
|
|
23
|
-
* - Real-time character/word count
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```html
|
|
27
|
-
* <schmancy-email-editor
|
|
28
|
-
* .subject="Welcome to our service"
|
|
29
|
-
* .body="Email content..."
|
|
30
|
-
* @editor-change=${handleChange}
|
|
31
|
-
* ></schmancy-email-editor>
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
@customElement('schmancy-email-editor')
|
|
35
|
-
export class SchmancyEmailEditor extends SchmancyElement {
|
|
36
|
-
static styles = [css`
|
|
37
|
-
:host {
|
|
38
|
-
display: block;
|
|
39
|
-
height: 100%;
|
|
40
|
-
}
|
|
41
|
-
`]
|
|
42
|
-
|
|
43
|
-
/** Email subject */
|
|
44
|
-
@property({ type: String }) subject = ''
|
|
45
|
-
|
|
46
|
-
/** Email body content (markdown) */
|
|
47
|
-
@property({ type: String }) body = ''
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/** Disable all interactions */
|
|
51
|
-
@property({ type: Boolean }) disabled = false
|
|
52
|
-
|
|
53
|
-
/** Email attachments */
|
|
54
|
-
@property({ type: Array }) attachments: EmailAttachment[] = []
|
|
55
|
-
|
|
56
|
-
/** Configuration for upload handlers */
|
|
57
|
-
@property({ type: Object }) config: EmailComposeConfig = {}
|
|
58
|
-
|
|
59
|
-
/** Available email templates */
|
|
60
|
-
@property({ type: Array }) templates: EmailTemplate[] = this.getDefaultTemplates()
|
|
61
|
-
|
|
62
|
-
/** Internal state */
|
|
63
|
-
@state() private dragOver = false
|
|
64
|
-
@state() private isUploading = false
|
|
65
|
-
|
|
66
|
-
/** Element references */
|
|
67
|
-
private subjectInputRef = createRef<HTMLInputElement>()
|
|
68
|
-
private bodyTextAreaRef = createRef<SchmancyTextarea>()
|
|
69
|
-
private fileInputRef = createRef<HTMLInputElement>()
|
|
70
|
-
private imageInputRef = createRef<HTMLInputElement>()
|
|
71
|
-
|
|
72
|
-
connectedCallback() {
|
|
73
|
-
super.connectedCallback()
|
|
74
|
-
this.addEventListeners()
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
disconnectedCallback() {
|
|
78
|
-
super.disconnectedCallback()
|
|
79
|
-
// Event listeners are automatically cleaned up via takeUntil(this.disconnecting)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** Get default email templates */
|
|
83
|
-
private getDefaultTemplates(): EmailTemplate[] {
|
|
84
|
-
return [
|
|
85
|
-
{
|
|
86
|
-
id: 'welcome',
|
|
87
|
-
name: 'Welcome Email',
|
|
88
|
-
subject: 'Welcome to Our Community! 🌟',
|
|
89
|
-
description: 'A warm welcome message for new users',
|
|
90
|
-
category: 'onboarding',
|
|
91
|
-
body: `# Welcome to Our Community!
|
|
92
|
-
|
|
93
|
-
We're thrilled to have you on board. Thank you for joining us on this journey.
|
|
94
|
-
|
|
95
|
-
## What's Next?
|
|
96
|
-
|
|
97
|
-
* **Explore** your dashboard and discover all the features
|
|
98
|
-
* **Connect** with other community members
|
|
99
|
-
* **Get support** whenever you need it - we're here to help
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
*Need assistance? Simply reply to this email and we'll get back to you within 24 hours.*
|
|
104
|
-
|
|
105
|
-
Best regards,
|
|
106
|
-
The Team`
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
id: 'newsletter',
|
|
110
|
-
name: 'Newsletter',
|
|
111
|
-
subject: 'Weekly Insights & Updates',
|
|
112
|
-
description: 'Regular newsletter template with updates and insights',
|
|
113
|
-
category: 'communication',
|
|
114
|
-
body: `# This Week's Highlights
|
|
115
|
-
|
|
116
|
-
## Featured Story
|
|
117
|
-
|
|
118
|
-
**[Article Title]**
|
|
119
|
-
Brief description of the main story or update that you want to highlight this week.
|
|
120
|
-
|
|
121
|
-
[Read More](https://example.com)
|
|
122
|
-
|
|
123
|
-
## Quick Updates
|
|
124
|
-
|
|
125
|
-
* **Update 1**: Brief description of an important update
|
|
126
|
-
* **Update 2**: Another noteworthy development
|
|
127
|
-
* **Update 3**: Additional news worth sharing
|
|
128
|
-
|
|
129
|
-
## Upcoming Events
|
|
130
|
-
|
|
131
|
-
**[Event Name]** - *Date*
|
|
132
|
-
Short description of the upcoming event.
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
*Thanks for reading! Forward this to a friend who might enjoy it.*
|
|
137
|
-
|
|
138
|
-
Until next week,
|
|
139
|
-
The Team`
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
id: 'product-launch',
|
|
143
|
-
name: 'Product Launch',
|
|
144
|
-
subject: 'Introducing Our Latest Innovation 🚀',
|
|
145
|
-
description: 'Announce new products or features',
|
|
146
|
-
category: 'marketing',
|
|
147
|
-
body: `# Something Amazing is Here
|
|
148
|
-
|
|
149
|
-
We've been working hard behind the scenes, and today we're excited to introduce our latest creation.
|
|
150
|
-
|
|
151
|
-
## Key Features
|
|
152
|
-
|
|
153
|
-
* **Feature 1**: Benefit that matters to your users
|
|
154
|
-
* **Feature 2**: Another compelling capability
|
|
155
|
-
* **Feature 3**: The feature that sets you apart
|
|
156
|
-
|
|
157
|
-
## Early Access
|
|
158
|
-
|
|
159
|
-
As a valued member, you get **exclusive early access** starting today.
|
|
160
|
-
|
|
161
|
-
[Get Started Now](https://example.com)
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
*Questions? We'd love to hear from you. Just hit reply!*
|
|
166
|
-
|
|
167
|
-
Best,
|
|
168
|
-
The Product Team`
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
id: 'event-invitation',
|
|
172
|
-
name: 'Event Invitation',
|
|
173
|
-
subject: 'You\'re Invited: [Event Name]',
|
|
174
|
-
description: 'Professional event invitation template',
|
|
175
|
-
category: 'events',
|
|
176
|
-
body: `# You're Invited!
|
|
177
|
-
|
|
178
|
-
## [Event Name]
|
|
179
|
-
|
|
180
|
-
**When**: [Date & Time]
|
|
181
|
-
**Where**: [Location or Virtual Link]
|
|
182
|
-
**Duration**: [Duration]
|
|
183
|
-
|
|
184
|
-
Join us for an exclusive gathering where we'll explore [brief event description].
|
|
185
|
-
|
|
186
|
-
## What to Expect
|
|
187
|
-
|
|
188
|
-
* **Networking** with industry professionals
|
|
189
|
-
* **Insights** from leading experts
|
|
190
|
-
* **Interactive** sessions and discussions
|
|
191
|
-
|
|
192
|
-
## RSVP Required
|
|
193
|
-
|
|
194
|
-
Space is limited, so please confirm your attendance by [RSVP Date].
|
|
195
|
-
|
|
196
|
-
[Confirm Attendance](https://example.com)
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
*Can't make it? Let us know and we'll share the key highlights with you.*
|
|
201
|
-
|
|
202
|
-
Looking forward to seeing you there,
|
|
203
|
-
The Events Team`
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
id: 'thank-you',
|
|
207
|
-
name: 'Thank You',
|
|
208
|
-
subject: 'Thank You - It Means Everything',
|
|
209
|
-
description: 'Express gratitude to customers or supporters',
|
|
210
|
-
category: 'appreciation',
|
|
211
|
-
body: `# Thank You
|
|
212
|
-
|
|
213
|
-
Your support means the world to us.
|
|
214
|
-
|
|
215
|
-
Whether you've been with us from the beginning or just joined our community, we want you to know how much we appreciate you.
|
|
216
|
-
|
|
217
|
-
## Because of You
|
|
218
|
-
|
|
219
|
-
* We've been able to improve our service
|
|
220
|
-
* Our community has grown stronger
|
|
221
|
-
* We've achieved milestones we never thought possible
|
|
222
|
-
|
|
223
|
-
## What's Next
|
|
224
|
-
|
|
225
|
-
We're committed to continuing to earn your trust and providing even more value in the coming months.
|
|
226
|
-
|
|
227
|
-
---
|
|
228
|
-
|
|
229
|
-
*Your feedback shapes everything we do. Reply anytime with thoughts or suggestions.*
|
|
230
|
-
|
|
231
|
-
With genuine gratitude,
|
|
232
|
-
The Team`
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
id: 'feedback-request',
|
|
236
|
-
name: 'Feedback Request',
|
|
237
|
-
subject: 'Your Opinion Matters - 2 Minutes?',
|
|
238
|
-
description: 'Request feedback or reviews from users',
|
|
239
|
-
category: 'feedback',
|
|
240
|
-
body: `# We'd Love Your Feedback
|
|
241
|
-
|
|
242
|
-
Your experience matters to us, and we're always looking for ways to improve.
|
|
243
|
-
|
|
244
|
-
## Quick Favor?
|
|
245
|
-
|
|
246
|
-
Could you spare **2 minutes** to share your thoughts? Your honest feedback helps us serve you better.
|
|
247
|
-
|
|
248
|
-
[Share Your Feedback](https://example.com)
|
|
249
|
-
|
|
250
|
-
## What We're Asking
|
|
251
|
-
|
|
252
|
-
* How has your experience been so far?
|
|
253
|
-
* What's working well for you?
|
|
254
|
-
* What could we improve?
|
|
255
|
-
|
|
256
|
-
## Thank You Gift
|
|
257
|
-
|
|
258
|
-
As a small token of appreciation, everyone who completes our feedback form receives [incentive].
|
|
259
|
-
|
|
260
|
-
---
|
|
261
|
-
|
|
262
|
-
*Every response is read personally by our team. We take your input seriously.*
|
|
263
|
-
|
|
264
|
-
Thanks in advance,
|
|
265
|
-
The Team`
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
id: 'password-reset',
|
|
269
|
-
name: 'Password Reset',
|
|
270
|
-
subject: 'Reset Your Password - Action Required',
|
|
271
|
-
description: 'Secure password reset instructions',
|
|
272
|
-
category: 'security',
|
|
273
|
-
body: `# Password Reset Request
|
|
274
|
-
|
|
275
|
-
We received a request to reset the password for your account.
|
|
276
|
-
|
|
277
|
-
## Reset Your Password
|
|
278
|
-
|
|
279
|
-
Click the button below to create a new password. This link will expire in **24 hours** for your security.
|
|
280
|
-
|
|
281
|
-
[Reset Password](https://example.com/reset)
|
|
282
|
-
|
|
283
|
-
## Didn't Request This?
|
|
284
|
-
|
|
285
|
-
If you didn't request a password reset, please ignore this email. Your account remains secure.
|
|
286
|
-
|
|
287
|
-
## Need Help?
|
|
288
|
-
|
|
289
|
-
If you're having trouble with the reset process, contact our support team and we'll assist you right away.
|
|
290
|
-
|
|
291
|
-
---
|
|
292
|
-
|
|
293
|
-
*For security reasons, this link can only be used once and expires in 24 hours.*
|
|
294
|
-
|
|
295
|
-
Best regards,
|
|
296
|
-
Security Team`
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
id: 'order-confirmation',
|
|
300
|
-
name: 'Order Confirmation',
|
|
301
|
-
subject: 'Order Confirmed - #[ORDER-NUMBER]',
|
|
302
|
-
description: 'Professional order confirmation template',
|
|
303
|
-
category: 'commerce',
|
|
304
|
-
body: `# Order Confirmation
|
|
305
|
-
|
|
306
|
-
Thanks for your order! We've received your payment and are preparing your items for shipment.
|
|
307
|
-
|
|
308
|
-
## Order Details
|
|
309
|
-
|
|
310
|
-
**Order Number**: #[ORDER-NUMBER]
|
|
311
|
-
**Order Date**: [DATE]
|
|
312
|
-
**Total**: $[AMOUNT]
|
|
313
|
-
|
|
314
|
-
## Items Ordered
|
|
315
|
-
|
|
316
|
-
* **[Item 1]** - Quantity: [QTY] - $[PRICE]
|
|
317
|
-
* **[Item 2]** - Quantity: [QTY] - $[PRICE]
|
|
318
|
-
|
|
319
|
-
## Shipping Information
|
|
320
|
-
|
|
321
|
-
**Address**: [SHIPPING ADDRESS]
|
|
322
|
-
**Method**: [SHIPPING METHOD]
|
|
323
|
-
**Estimated Delivery**: [DELIVERY DATE]
|
|
324
|
-
|
|
325
|
-
## Next Steps
|
|
326
|
-
|
|
327
|
-
You'll receive a tracking number via email once your order ships (usually within 1-2 business days).
|
|
328
|
-
|
|
329
|
-
[Track Your Order](https://example.com/track)
|
|
330
|
-
|
|
331
|
-
---
|
|
332
|
-
|
|
333
|
-
*Questions about your order? Reply to this email or contact our support team.*
|
|
334
|
-
|
|
335
|
-
Thank you for your business,
|
|
336
|
-
The Fulfillment Team`
|
|
337
|
-
}
|
|
338
|
-
]
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
private addEventListeners() {
|
|
342
|
-
// Keyboard events
|
|
343
|
-
fromEvent(this, 'keydown').pipe(
|
|
344
|
-
takeUntil(this.disconnecting)
|
|
345
|
-
).subscribe(this.handleKeyDown)
|
|
346
|
-
|
|
347
|
-
// Document paste events
|
|
348
|
-
fromEvent(document, 'paste').pipe(
|
|
349
|
-
takeUntil(this.disconnecting)
|
|
350
|
-
).subscribe(this.handlePaste)
|
|
351
|
-
|
|
352
|
-
// Document drag events
|
|
353
|
-
fromEvent(document, 'dragenter').pipe(
|
|
354
|
-
takeUntil(this.disconnecting)
|
|
355
|
-
).subscribe(this.handleDragEnter)
|
|
356
|
-
|
|
357
|
-
fromEvent(document, 'dragleave').pipe(
|
|
358
|
-
takeUntil(this.disconnecting)
|
|
359
|
-
).subscribe(this.handleDocumentDragLeave)
|
|
360
|
-
|
|
361
|
-
fromEvent(document, 'drop').pipe(
|
|
362
|
-
takeUntil(this.disconnecting)
|
|
363
|
-
).subscribe(this.handleDocumentDrop)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/** Handle keyboard shortcuts and tab indentation */
|
|
367
|
-
private handleKeyDown = (e: KeyboardEvent) => {
|
|
368
|
-
if (this.disabled) return
|
|
369
|
-
|
|
370
|
-
// Tab key inserts 2 spaces instead of changing focus
|
|
371
|
-
const textarea = this.bodyTextAreaRef.value?.shadowRoot?.querySelector('textarea')
|
|
372
|
-
if (e.key === 'Tab' && e.target === textarea) {
|
|
373
|
-
e.preventDefault()
|
|
374
|
-
this.insertAtCursor(' ')
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/** Handle paste events for image pasting */
|
|
379
|
-
private handlePaste = (event: ClipboardEvent) => {
|
|
380
|
-
const textarea = this.bodyTextAreaRef.value?.shadowRoot?.querySelector('textarea')
|
|
381
|
-
if (this.disabled || document.activeElement !== textarea) return
|
|
382
|
-
|
|
383
|
-
const items = event.clipboardData?.items
|
|
384
|
-
if (!items) return
|
|
385
|
-
|
|
386
|
-
for (let i = 0; i < items.length; i++) {
|
|
387
|
-
const item = items[i]
|
|
388
|
-
if (item.type.indexOf('image') !== -1) {
|
|
389
|
-
event.preventDefault()
|
|
390
|
-
const file = item.getAsFile()
|
|
391
|
-
if (file) {
|
|
392
|
-
this.uploadImage(file)
|
|
393
|
-
}
|
|
394
|
-
break
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/** Handle subject input changes */
|
|
400
|
-
private handleSubjectChange = (event: Event) => {
|
|
401
|
-
const input = event.target as HTMLInputElement
|
|
402
|
-
this.subject = input.value
|
|
403
|
-
this.dispatchChange()
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/** Handle body textarea changes */
|
|
407
|
-
private handleBodyChange = (event: CustomEvent<{ value: string }>) => {
|
|
408
|
-
this.body = event.detail.value
|
|
409
|
-
this.dispatchChange()
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/** Dispatch composer change event */
|
|
413
|
-
private dispatchChange = () => {
|
|
414
|
-
this.dispatchEvent(new CustomEvent('editor-change', {
|
|
415
|
-
detail: {
|
|
416
|
-
subject: this.subject,
|
|
417
|
-
body: this.body,
|
|
418
|
-
attachments: this.attachments
|
|
419
|
-
},
|
|
420
|
-
bubbles: true,
|
|
421
|
-
composed: true
|
|
422
|
-
}))
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/** Insert text at cursor position */
|
|
426
|
-
private insertAtCursor(text: string, selectText?: string) {
|
|
427
|
-
if (!this.bodyTextAreaRef.value) return
|
|
428
|
-
|
|
429
|
-
// For schmancy-textarea, access the internal textarea
|
|
430
|
-
const textarea = this.bodyTextAreaRef.value.shadowRoot?.querySelector('textarea')
|
|
431
|
-
if (!textarea) return
|
|
432
|
-
|
|
433
|
-
const start = textarea.selectionStart
|
|
434
|
-
const end = textarea.selectionEnd
|
|
435
|
-
|
|
436
|
-
const newValue =
|
|
437
|
-
textarea.value.substring(0, start) +
|
|
438
|
-
text +
|
|
439
|
-
textarea.value.substring(end)
|
|
440
|
-
|
|
441
|
-
this.body = newValue
|
|
442
|
-
this.dispatchChange()
|
|
443
|
-
|
|
444
|
-
this.updateComplete.then(() => {
|
|
445
|
-
const updatedTextarea = this.bodyTextAreaRef.value?.shadowRoot?.querySelector('textarea')
|
|
446
|
-
if (updatedTextarea) {
|
|
447
|
-
updatedTextarea.focus()
|
|
448
|
-
if (selectText) {
|
|
449
|
-
const selectStart = start + text.indexOf(selectText)
|
|
450
|
-
const selectEnd = selectStart + selectText.length
|
|
451
|
-
updatedTextarea.setSelectionRange(selectStart, selectEnd)
|
|
452
|
-
} else {
|
|
453
|
-
updatedTextarea.setSelectionRange(start + text.length, start + text.length)
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
return
|
|
457
|
-
})
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/** Wrap selected text with formatting */
|
|
461
|
-
private wrapSelection(before: string, after: string, placeholder: string) {
|
|
462
|
-
if (!this.bodyTextAreaRef.value) return
|
|
463
|
-
|
|
464
|
-
// For schmancy-textarea, access the internal textarea
|
|
465
|
-
const textarea = this.bodyTextAreaRef.value.shadowRoot?.querySelector('textarea')
|
|
466
|
-
if (!textarea) return
|
|
467
|
-
|
|
468
|
-
const start = textarea.selectionStart
|
|
469
|
-
const end = textarea.selectionEnd
|
|
470
|
-
const selectedText = textarea.value.substring(start, end)
|
|
471
|
-
|
|
472
|
-
const textToWrap = selectedText || placeholder
|
|
473
|
-
const newText = before + textToWrap + after
|
|
474
|
-
|
|
475
|
-
const newValue =
|
|
476
|
-
textarea.value.substring(0, start) +
|
|
477
|
-
newText +
|
|
478
|
-
textarea.value.substring(end)
|
|
479
|
-
|
|
480
|
-
this.body = newValue
|
|
481
|
-
this.dispatchChange()
|
|
482
|
-
|
|
483
|
-
this.updateComplete.then(() => {
|
|
484
|
-
const updatedTextarea = this.bodyTextAreaRef.value?.shadowRoot?.querySelector('textarea')
|
|
485
|
-
if (updatedTextarea) {
|
|
486
|
-
updatedTextarea.focus()
|
|
487
|
-
if (!selectedText) {
|
|
488
|
-
// Select the placeholder text
|
|
489
|
-
updatedTextarea.setSelectionRange(start + before.length, start + before.length + placeholder.length)
|
|
490
|
-
} else {
|
|
491
|
-
// Position cursor at the end
|
|
492
|
-
updatedTextarea.setSelectionRange(start + newText.length, start + newText.length)
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
return
|
|
496
|
-
})
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/** Open layout selection dialog */
|
|
500
|
-
private openLayoutDialog = () => {
|
|
501
|
-
// Inline-template overlay; the selector's `layout-select` event is
|
|
502
|
-
// re-dispatched as `close` so `show()` resolves with the chosen layout.
|
|
503
|
-
show<string>(html`
|
|
504
|
-
<schmancy-email-layout-selector
|
|
505
|
-
@layout-select=${(e: CustomEvent) => {
|
|
506
|
-
e.currentTarget?.dispatchEvent(
|
|
507
|
-
new CustomEvent('close', { detail: e.detail.layout, bubbles: true, composed: true }),
|
|
508
|
-
)
|
|
509
|
-
}}
|
|
510
|
-
></schmancy-email-layout-selector>
|
|
511
|
-
`)
|
|
512
|
-
.pipe(takeUntil(this.disconnecting))
|
|
513
|
-
.subscribe(layout => {
|
|
514
|
-
if (layout) this.applyLayout(layout)
|
|
515
|
-
})
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/** Open template picker */
|
|
519
|
-
private openTemplatePicker = () => {
|
|
520
|
-
show<EmailTemplate>(SchmancyEmailTemplatePicker, { props: { templates: this.templates } })
|
|
521
|
-
.pipe(takeUntil(this.disconnecting))
|
|
522
|
-
.subscribe(template => {
|
|
523
|
-
if (template) this.handleTemplateSelected(template)
|
|
524
|
-
})
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
/** Handle template selection */
|
|
528
|
-
private handleTemplateSelected = (template: EmailTemplate) => {
|
|
529
|
-
this.subject = template.subject
|
|
530
|
-
this.body = template.body
|
|
531
|
-
this.dispatchChange()
|
|
532
|
-
$notify.success(`Template "${template.name}" applied successfully`)
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
/** Apply layout template to content */
|
|
536
|
-
private applyLayout = (layoutType: string) => {
|
|
537
|
-
const layouts: Record<string, string> = {
|
|
538
|
-
'columns-2': `
|
|
539
|
-
:::layout columns-2
|
|
540
|
-
<div class="column">
|
|
541
|
-
{height=300px}
|
|
542
|
-
|
|
543
|
-
**Photo Title**
|
|
544
|
-
|
|
545
|
-
Replace the placeholder image above with your own photo. The height=300px ensures both images have equal height while width adjusts automatically.
|
|
546
|
-
</div>
|
|
547
|
-
|
|
548
|
-
<div class="column">
|
|
549
|
-
{height=300px}
|
|
550
|
-
|
|
551
|
-
**Photo Title**
|
|
552
|
-
|
|
553
|
-
Use the same height value (300px) for both images to keep them aligned perfectly side by side.
|
|
554
|
-
</div>
|
|
555
|
-
:::
|
|
556
|
-
`,
|
|
557
|
-
'columns-3': `
|
|
558
|
-
:::layout columns-3
|
|
559
|
-
<div class="column">
|
|
560
|
-
{height=200px}
|
|
561
|
-
|
|
562
|
-
**Item Title**
|
|
563
|
-
|
|
564
|
-
Brief description or caption for this item.
|
|
565
|
-
</div>
|
|
566
|
-
|
|
567
|
-
<div class="column">
|
|
568
|
-
{height=200px}
|
|
569
|
-
|
|
570
|
-
**Item Title**
|
|
571
|
-
|
|
572
|
-
Brief description or caption for this item.
|
|
573
|
-
</div>
|
|
574
|
-
|
|
575
|
-
<div class="column">
|
|
576
|
-
{height=200px}
|
|
577
|
-
|
|
578
|
-
**Item Title**
|
|
579
|
-
|
|
580
|
-
Brief description or caption for this item.
|
|
581
|
-
</div>
|
|
582
|
-
:::
|
|
583
|
-
`,
|
|
584
|
-
'sidebar-left': `
|
|
585
|
-
:::layout sidebar-left
|
|
586
|
-
<div class="sidebar">
|
|
587
|
-
**Sidebar Content**
|
|
588
|
-
|
|
589
|
-
* Navigation item 1
|
|
590
|
-
* Navigation item 2
|
|
591
|
-
* Navigation item 3
|
|
592
|
-
</div>
|
|
593
|
-
|
|
594
|
-
<div class="main">
|
|
595
|
-
**Main Content Area**
|
|
596
|
-
|
|
597
|
-
Your primary content goes here. This area takes up most of the width while the sidebar provides supplementary information or navigation.
|
|
598
|
-
</div>
|
|
599
|
-
:::
|
|
600
|
-
`,
|
|
601
|
-
'sidebar-right': `
|
|
602
|
-
:::layout sidebar-right
|
|
603
|
-
<div class="main">
|
|
604
|
-
**Main Content Area**
|
|
605
|
-
|
|
606
|
-
Your primary content goes here. This area takes up most of the width while the sidebar provides supplementary information or navigation.
|
|
607
|
-
</div>
|
|
608
|
-
|
|
609
|
-
<div class="sidebar">
|
|
610
|
-
**Sidebar Content**
|
|
611
|
-
|
|
612
|
-
* Quick links
|
|
613
|
-
* Related info
|
|
614
|
-
* Contact details
|
|
615
|
-
</div>
|
|
616
|
-
:::
|
|
617
|
-
`,
|
|
618
|
-
'image-row': `
|
|
619
|
-
:::layout image-row
|
|
620
|
-
<div class="image">
|
|
621
|
-
{height=250px}
|
|
622
|
-
</div>
|
|
623
|
-
|
|
624
|
-
<div class="image">
|
|
625
|
-
{height=250px}
|
|
626
|
-
</div>
|
|
627
|
-
|
|
628
|
-
<div class="image">
|
|
629
|
-
{height=250px}
|
|
630
|
-
</div>
|
|
631
|
-
:::
|
|
632
|
-
`
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
const layoutMarkdown = layouts[layoutType]
|
|
636
|
-
if (layoutMarkdown) {
|
|
637
|
-
this.insertAtCursor(layoutMarkdown)
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
/** Upload image with configurable handler */
|
|
642
|
-
private uploadImage = async (file: File) => {
|
|
643
|
-
if (!file.type.startsWith('image/')) {
|
|
644
|
-
$notify.error(`File "${file.name}" is not an image`)
|
|
645
|
-
return
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// Check file size (max 10MB for images)
|
|
649
|
-
const maxSize = 10 * 1024 * 1024
|
|
650
|
-
if (file.size > maxSize) {
|
|
651
|
-
$notify.error(`Image "${file.name}" is too large. Maximum size is 10MB.`)
|
|
652
|
-
return
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
// Show loading state
|
|
656
|
-
this.isUploading = true
|
|
657
|
-
|
|
658
|
-
try {
|
|
659
|
-
let url: string
|
|
660
|
-
|
|
661
|
-
if (this.config.imageUploadHandler) {
|
|
662
|
-
// Use custom upload handler
|
|
663
|
-
url = await this.config.imageUploadHandler(file)
|
|
664
|
-
} else if (this.config.uploadHandler) {
|
|
665
|
-
// Use generic upload handler
|
|
666
|
-
url = await this.config.uploadHandler(file)
|
|
667
|
-
} else {
|
|
668
|
-
// Fallback to data URL for preview
|
|
669
|
-
url = await this.createDataUrl(file)
|
|
670
|
-
$notify.warning('No upload handler configured. Using local preview.')
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
// Get image dimensions
|
|
674
|
-
const dimensions = await this.getImageDimensions(file)
|
|
675
|
-
|
|
676
|
-
// Insert markdown at cursor position
|
|
677
|
-
this.insertImageMarkdown(url, file.name, dimensions.width, dimensions.height)
|
|
678
|
-
|
|
679
|
-
$notify.success('Image uploaded successfully')
|
|
680
|
-
} catch (error) {
|
|
681
|
-
console.error('Upload failed:', error)
|
|
682
|
-
$notify.error('Failed to upload image')
|
|
683
|
-
} finally {
|
|
684
|
-
this.isUploading = false
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
/** Create data URL for local preview */
|
|
689
|
-
private createDataUrl = (file: File): Promise<string> => {
|
|
690
|
-
return new Promise((resolve, reject) => {
|
|
691
|
-
const reader = new FileReader()
|
|
692
|
-
reader.addEventListener('load', () => resolve(reader.result as string), { once: true })
|
|
693
|
-
reader.addEventListener('error', () => reject(reader.error), { once: true })
|
|
694
|
-
reader.readAsDataURL(file)
|
|
695
|
-
})
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
/** Get image dimensions */
|
|
699
|
-
private getImageDimensions = (file: File): Promise<{width: number, height: number}> => {
|
|
700
|
-
return new Promise((resolve) => {
|
|
701
|
-
const img = new Image()
|
|
702
|
-
img.addEventListener('load', () => {
|
|
703
|
-
resolve({ width: img.width, height: img.height })
|
|
704
|
-
URL.revokeObjectURL(img.src)
|
|
705
|
-
}, { once: true })
|
|
706
|
-
img.addEventListener('error', () => {
|
|
707
|
-
resolve({ width: 400, height: 300 }) // Default dimensions
|
|
708
|
-
URL.revokeObjectURL(img.src)
|
|
709
|
-
}, { once: true })
|
|
710
|
-
img.src = URL.createObjectURL(file)
|
|
711
|
-
})
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
/** Insert image markdown at cursor */
|
|
715
|
-
private insertImageMarkdown = (url: string, alt: string, width: number, _height: number) => {
|
|
716
|
-
const textarea = this.bodyTextAreaRef.value?.shadowRoot?.querySelector('textarea')
|
|
717
|
-
if (!textarea) return
|
|
718
|
-
|
|
719
|
-
const markdown = `{width=${Math.min(width, 600)}px height=auto}`
|
|
720
|
-
|
|
721
|
-
const start = textarea.selectionStart
|
|
722
|
-
const end = textarea.selectionEnd
|
|
723
|
-
const newValue =
|
|
724
|
-
this.body.substring(0, start) +
|
|
725
|
-
markdown +
|
|
726
|
-
this.body.substring(end)
|
|
727
|
-
|
|
728
|
-
this.body = newValue
|
|
729
|
-
this.dispatchChange()
|
|
730
|
-
|
|
731
|
-
// Set cursor after inserted markdown
|
|
732
|
-
this.updateComplete.then(() => {
|
|
733
|
-
const updatedTextarea = this.bodyTextAreaRef.value?.shadowRoot?.querySelector('textarea')
|
|
734
|
-
if (updatedTextarea) {
|
|
735
|
-
const newPosition = start + markdown.length
|
|
736
|
-
updatedTextarea.setSelectionRange(newPosition, newPosition)
|
|
737
|
-
updatedTextarea.focus()
|
|
738
|
-
}
|
|
739
|
-
return
|
|
740
|
-
})
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
/** Handle file input changes */
|
|
745
|
-
private handleFileChange = (event: Event) => {
|
|
746
|
-
const input = event.target as HTMLInputElement
|
|
747
|
-
const files = input.files
|
|
748
|
-
if (files) {
|
|
749
|
-
for (let i = 0; i < files.length; i++) {
|
|
750
|
-
const file = files[i]
|
|
751
|
-
if (file.type.startsWith('image/')) {
|
|
752
|
-
this.uploadImage(file)
|
|
753
|
-
} else {
|
|
754
|
-
this.addFile(file)
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
input.value = ''
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
/** Handle image selection */
|
|
762
|
-
private handleImageSelect = (event: Event) => {
|
|
763
|
-
const input = event.target as HTMLInputElement
|
|
764
|
-
const file = input.files?.[0]
|
|
765
|
-
if (file && file.type.startsWith('image/')) {
|
|
766
|
-
this.uploadImage(file)
|
|
767
|
-
}
|
|
768
|
-
input.value = '' // Reset for next selection
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
/** Drag and drop handlers */
|
|
772
|
-
private handleDrop = (event: DragEvent) => {
|
|
773
|
-
event.preventDefault()
|
|
774
|
-
this.dragOver = false
|
|
775
|
-
|
|
776
|
-
const files = event.dataTransfer?.files
|
|
777
|
-
if (files) {
|
|
778
|
-
for (let i = 0; i < files.length; i++) {
|
|
779
|
-
const file = files[i]
|
|
780
|
-
if (file.type.startsWith('image/')) {
|
|
781
|
-
this.uploadImage(file)
|
|
782
|
-
} else {
|
|
783
|
-
this.addFile(file)
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
private handleDragEnter = (event: DragEvent) => {
|
|
790
|
-
event.preventDefault()
|
|
791
|
-
this.dragOver = true
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
private handleDocumentDragLeave = (event: DragEvent) => {
|
|
795
|
-
event.preventDefault()
|
|
796
|
-
this.dragOver = false
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
private handleDocumentDrop = (event: DragEvent) => {
|
|
800
|
-
event.preventDefault()
|
|
801
|
-
this.dragOver = false
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
private handleDragOver = (event: DragEvent) => {
|
|
805
|
-
event.preventDefault()
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
private handleDragLeave = (event: DragEvent) => {
|
|
809
|
-
event.preventDefault()
|
|
810
|
-
// Let document handler manage this
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
/** Add file as attachment */
|
|
814
|
-
private addFile = (file: File) => {
|
|
815
|
-
// Check file size (max 10MB)
|
|
816
|
-
const maxSize = 10 * 1024 * 1024
|
|
817
|
-
if (file.size > maxSize) {
|
|
818
|
-
$notify.error(`File "${file.name}" is too large. Maximum size is 10MB.`)
|
|
819
|
-
return
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
// Check if file already exists
|
|
823
|
-
const exists = this.attachments.some(att =>
|
|
824
|
-
att.name === file.name && att.size === file.size
|
|
825
|
-
)
|
|
826
|
-
if (exists) {
|
|
827
|
-
$notify.warning(`File "${file.name}" is already attached.`)
|
|
828
|
-
return
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
const attachment: EmailAttachment = {
|
|
832
|
-
id: crypto.randomUUID(),
|
|
833
|
-
file,
|
|
834
|
-
name: file.name,
|
|
835
|
-
size: file.size,
|
|
836
|
-
type: file.type || 'application/octet-stream'
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
this.attachments = [...this.attachments, attachment]
|
|
840
|
-
this.dispatchChange()
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
/** Remove attachment */
|
|
844
|
-
private removeAttachment = (attachmentId: string) => {
|
|
845
|
-
this.attachments = this.attachments.filter(att => att.id !== attachmentId)
|
|
846
|
-
this.dispatchChange()
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
render() {
|
|
851
|
-
return html`
|
|
852
|
-
<schmancy-surface
|
|
853
|
-
type="solid"
|
|
854
|
-
rounded="all"
|
|
855
|
-
class=${this.classMap({
|
|
856
|
-
'border-2 border-dashed border-primary': this.dragOver,
|
|
857
|
-
'h-full flex flex-col': true
|
|
858
|
-
})}
|
|
859
|
-
@drop=${this.handleDrop}
|
|
860
|
-
@dragover=${this.handleDragOver}
|
|
861
|
-
@dragleave=${this.handleDragLeave}
|
|
862
|
-
>
|
|
863
|
-
<div class="flex flex-col h-full gap-4">
|
|
864
|
-
|
|
865
|
-
<!-- Header Section with Subject -->
|
|
866
|
-
<div class="shrink-0 p-4 pb-0 space-y-4">
|
|
867
|
-
<!-- Subject Field -->
|
|
868
|
-
<div class="space-y-2">
|
|
869
|
-
<schmancy-typography type="label" token="md">
|
|
870
|
-
Subject *
|
|
871
|
-
</schmancy-typography>
|
|
872
|
-
<schmancy-input
|
|
873
|
-
${ref(this.subjectInputRef)}
|
|
874
|
-
.value=${this.subject}
|
|
875
|
-
@input=${this.handleSubjectChange}
|
|
876
|
-
placeholder="Enter email subject..."
|
|
877
|
-
.disabled=${this.disabled}
|
|
878
|
-
class="w-full"
|
|
879
|
-
></schmancy-input>
|
|
880
|
-
</div>
|
|
881
|
-
</div>
|
|
882
|
-
|
|
883
|
-
<!-- Formatting Toolbar -->
|
|
884
|
-
<div class="shrink-0 px-4">
|
|
885
|
-
<schmancy-surface type="subtle" rounded="all" class="p-3">
|
|
886
|
-
<div class="flex flex-wrap gap-2 items-center">
|
|
887
|
-
<!-- Text Formatting Group -->
|
|
888
|
-
<div class="flex gap-1">
|
|
889
|
-
<schmancy-icon-button
|
|
890
|
-
size="sm"
|
|
891
|
-
variant="text"
|
|
892
|
-
title="Bold"
|
|
893
|
-
?disabled=${this.disabled}
|
|
894
|
-
@click=${() => this.wrapSelection('**', '**', 'bold text')}
|
|
895
|
-
>
|
|
896
|
-
<schmancy-icon>format_bold</schmancy-icon>
|
|
897
|
-
</schmancy-icon-button>
|
|
898
|
-
<schmancy-icon-button
|
|
899
|
-
size="sm"
|
|
900
|
-
variant="text"
|
|
901
|
-
title="Italic"
|
|
902
|
-
?disabled=${this.disabled}
|
|
903
|
-
@click=${() => this.wrapSelection('*', '*', 'italic text')}
|
|
904
|
-
>
|
|
905
|
-
<schmancy-icon>format_italic</schmancy-icon>
|
|
906
|
-
</schmancy-icon-button>
|
|
907
|
-
<schmancy-icon-button
|
|
908
|
-
size="sm"
|
|
909
|
-
variant="text"
|
|
910
|
-
title="Link"
|
|
911
|
-
?disabled=${this.disabled}
|
|
912
|
-
@click=${() => this.insertAtCursor('[link text](https://example.com)', 'link text')}
|
|
913
|
-
>
|
|
914
|
-
<schmancy-icon>link</schmancy-icon>
|
|
915
|
-
</schmancy-icon-button>
|
|
916
|
-
</div>
|
|
917
|
-
|
|
918
|
-
<!-- Divider -->
|
|
919
|
-
<div class="h-6 w-px bg-outline-variant"></div>
|
|
920
|
-
|
|
921
|
-
<!-- Structure Formatting Group -->
|
|
922
|
-
<div class="flex gap-1">
|
|
923
|
-
<schmancy-icon-button
|
|
924
|
-
size="sm"
|
|
925
|
-
variant="text"
|
|
926
|
-
title="Heading"
|
|
927
|
-
?disabled=${this.disabled}
|
|
928
|
-
@click=${() => this.insertAtCursor('\n# Heading\n', 'Heading')}
|
|
929
|
-
>
|
|
930
|
-
<schmancy-icon>title</schmancy-icon>
|
|
931
|
-
</schmancy-icon-button>
|
|
932
|
-
<schmancy-icon-button
|
|
933
|
-
size="sm"
|
|
934
|
-
variant="text"
|
|
935
|
-
title="Bullet List"
|
|
936
|
-
?disabled=${this.disabled}
|
|
937
|
-
@click=${() => this.insertAtCursor('\n* List item\n', 'List item')}
|
|
938
|
-
>
|
|
939
|
-
<schmancy-icon>format_list_bulleted</schmancy-icon>
|
|
940
|
-
</schmancy-icon-button>
|
|
941
|
-
</div>
|
|
942
|
-
|
|
943
|
-
<!-- Divider -->
|
|
944
|
-
<div class="h-6 w-px bg-outline-variant"></div>
|
|
945
|
-
|
|
946
|
-
<!-- Media and Layout Group -->
|
|
947
|
-
<div class="flex gap-1">
|
|
948
|
-
<schmancy-icon-button
|
|
949
|
-
size="sm"
|
|
950
|
-
variant="text"
|
|
951
|
-
title="Insert Image"
|
|
952
|
-
?disabled=${this.disabled || this.isUploading}
|
|
953
|
-
@click=${() => this.imageInputRef.value?.click()}
|
|
954
|
-
>
|
|
955
|
-
${when(this.isUploading,
|
|
956
|
-
() => html`<schmancy-progress size="sm" class="w-4 h-4"></schmancy-progress>`,
|
|
957
|
-
() => html`<schmancy-icon>image</schmancy-icon>`
|
|
958
|
-
)}
|
|
959
|
-
</schmancy-icon-button>
|
|
960
|
-
<schmancy-icon-button
|
|
961
|
-
size="sm"
|
|
962
|
-
variant="text"
|
|
963
|
-
title="Insert Layout"
|
|
964
|
-
?disabled=${this.disabled}
|
|
965
|
-
@click=${this.openLayoutDialog}
|
|
966
|
-
>
|
|
967
|
-
<schmancy-icon>mobile_layout</schmancy-icon>
|
|
968
|
-
</schmancy-icon-button>
|
|
969
|
-
<schmancy-icon-button
|
|
970
|
-
size="sm"
|
|
971
|
-
variant="text"
|
|
972
|
-
title="Use Template"
|
|
973
|
-
?disabled=${this.disabled || this.templates.length === 0}
|
|
974
|
-
@click=${this.openTemplatePicker}
|
|
975
|
-
>
|
|
976
|
-
<schmancy-icon>description</schmancy-icon>
|
|
977
|
-
</schmancy-icon-button>
|
|
978
|
-
</div>
|
|
979
|
-
</div>
|
|
980
|
-
</schmancy-surface>
|
|
981
|
-
</div>
|
|
982
|
-
|
|
983
|
-
<!-- Textarea Container - Takes remaining space -->
|
|
984
|
-
<div class="flex-1 px-4 relative min-h-0">
|
|
985
|
-
<schmancy-textarea
|
|
986
|
-
${ref(this.bodyTextAreaRef)}
|
|
987
|
-
.value=${this.body}
|
|
988
|
-
@change=${this.handleBodyChange}
|
|
989
|
-
placeholder="Enter your email message here...
|
|
990
|
-
|
|
991
|
-
Use the toolbar buttons above for formatting, or type markdown directly:
|
|
992
|
-
**bold**, *italic*, [link](url), 
|
|
993
|
-
|
|
994
|
-
Drag & drop images or press Ctrl+V to paste from clipboard.
|
|
995
|
-
Tab key inserts 2 spaces for better formatting."
|
|
996
|
-
.disabled=${this.disabled}
|
|
997
|
-
.required=${true}
|
|
998
|
-
.rows=${4}
|
|
999
|
-
class="w-full font-mono text-sm"
|
|
1000
|
-
></schmancy-textarea>
|
|
1001
|
-
|
|
1002
|
-
<!-- Upload Progress Overlay -->
|
|
1003
|
-
${when(this.isUploading, () => html`
|
|
1004
|
-
<div class="absolute top-3 right-3 z-10">
|
|
1005
|
-
<schmancy-surface type="subtle" rounded="all" class="p-2">
|
|
1006
|
-
<div class="flex items-center gap-2">
|
|
1007
|
-
<schmancy-progress size="sm" class="w-4 h-4"></schmancy-progress>
|
|
1008
|
-
<schmancy-typography type="body" token="xs">Uploading...</schmancy-typography>
|
|
1009
|
-
</div>
|
|
1010
|
-
</schmancy-surface>
|
|
1011
|
-
</div>
|
|
1012
|
-
`)}
|
|
1013
|
-
</div>
|
|
1014
|
-
|
|
1015
|
-
<!-- Footer Section -->
|
|
1016
|
-
<div class="shrink-0 p-4 pt-0 space-y-2">
|
|
1017
|
-
<!-- Character/Word Counter -->
|
|
1018
|
-
<div class="text-center">
|
|
1019
|
-
<schmancy-typography type="body" token="xs">
|
|
1020
|
-
${this.body.length} characters • ${this.body.trim() ? this.body.trim().split(/\s+/).length : 0} words
|
|
1021
|
-
</schmancy-typography>
|
|
1022
|
-
</div>
|
|
1023
|
-
|
|
1024
|
-
<!-- Attachments Display (if any) -->
|
|
1025
|
-
${when(this.attachments.length > 0, () => html`
|
|
1026
|
-
<div class="space-y-2">
|
|
1027
|
-
<schmancy-typography type="label" token="sm" class="flex items-center gap-2">
|
|
1028
|
-
<schmancy-icon size="16px">attach_file</schmancy-icon>
|
|
1029
|
-
Attachments (${this.attachments.length})
|
|
1030
|
-
</schmancy-typography>
|
|
1031
|
-
<div class="flex flex-wrap gap-2">
|
|
1032
|
-
${repeat(this.attachments, att => att.id, (attachment) => html`
|
|
1033
|
-
<schmancy-chip class="text-xs">
|
|
1034
|
-
<span class="truncate max-w-32">${attachment.name}</span>
|
|
1035
|
-
<button
|
|
1036
|
-
@click=${() => this.removeAttachment(attachment.id)}
|
|
1037
|
-
class="ml-2 text-error hover:text-error-container"
|
|
1038
|
-
title="Remove attachment"
|
|
1039
|
-
>
|
|
1040
|
-
<schmancy-icon size="14px">close</schmancy-icon>
|
|
1041
|
-
</button>
|
|
1042
|
-
</schmancy-chip>
|
|
1043
|
-
`)}
|
|
1044
|
-
</div>
|
|
1045
|
-
</div>
|
|
1046
|
-
`)}
|
|
1047
|
-
</div>
|
|
1048
|
-
|
|
1049
|
-
<!-- Hidden File Inputs -->
|
|
1050
|
-
<div class="hidden">
|
|
1051
|
-
<input
|
|
1052
|
-
${ref(this.fileInputRef)}
|
|
1053
|
-
type="file"
|
|
1054
|
-
multiple
|
|
1055
|
-
@change=${this.handleFileChange}
|
|
1056
|
-
>
|
|
1057
|
-
<input
|
|
1058
|
-
${ref(this.imageInputRef)}
|
|
1059
|
-
type="file"
|
|
1060
|
-
accept="image/*"
|
|
1061
|
-
@change=${this.handleImageSelect}
|
|
1062
|
-
>
|
|
1063
|
-
</div>
|
|
1064
|
-
|
|
1065
|
-
</div>
|
|
1066
|
-
</schmancy-surface>
|
|
1067
|
-
|
|
1068
|
-
`
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
declare global {
|
|
1073
|
-
interface HTMLElementTagNameMap {
|
|
1074
|
-
'schmancy-email-editor': SchmancyEmailEditor
|
|
1075
|
-
}
|
|
1076
|
-
}
|