@mhmo91/schmancy 0.9.10 → 0.9.11
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 -4
- package/dist/badge.cjs +1 -1
- package/dist/badge.js +1 -1
- package/dist/button.cjs +29 -29
- package/dist/button.cjs.map +1 -1
- package/dist/button.js +52 -50
- package/dist/button.js.map +1 -1
- package/dist/{card-DUq_MsxC.cjs.map → card-Bht1QcYl.cjs.map} +1 -1
- package/dist/{card-C8Ns2mRo.js.map → card-DiNYPJ9b.js.map} +1 -1
- package/dist/card.cjs +1 -1
- package/dist/card.js +1 -1
- package/dist/{checkbox-qPH_5Viu.cjs → checkbox-CRzu7URt.cjs} +1 -1
- package/dist/{checkbox-qPH_5Viu.cjs.map → checkbox-CRzu7URt.cjs.map} +1 -1
- package/dist/{checkbox-D18r6c0V.js → checkbox-dRBf89qt.js} +1 -1
- package/dist/{checkbox-D18r6c0V.js.map → checkbox-dRBf89qt.js.map} +1 -1
- package/dist/checkbox.cjs +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/{chips-0rKPqQt8.js.map → chips-Bma_B3J-.js.map} +1 -1
- package/dist/{chips-BI_kt5BS.cjs.map → chips-CXknD-vY.cjs.map} +1 -1
- package/dist/chips.cjs +1 -1
- package/dist/chips.js +1 -1
- package/dist/{code-highlight-DGInmDAW.cjs.map → code-highlight-BROOsNA_.cjs.map} +1 -1
- package/dist/{code-highlight-ClzG4FL4.js.map → code-highlight-DjiyaDcX.js.map} +1 -1
- package/dist/code-highlight.cjs +1 -1
- package/dist/code-highlight.js +1 -1
- package/dist/{components-RbvrLE3U.js.map → components-DKgu88mm.js.map} +1 -1
- package/dist/{components-7hOtFi_q.cjs.map → components-ubXwQbGs.cjs.map} +1 -1
- package/dist/components.cjs +1 -1
- package/dist/components.js +1 -1
- package/dist/content-drawer.cjs +1 -1
- package/dist/content-drawer.js +1 -1
- package/dist/context-B81Q3U_1.cjs +1 -0
- package/dist/context-B81Q3U_1.cjs.map +1 -0
- package/dist/context-Dnj4ofbV.js +3 -0
- package/dist/context-Dnj4ofbV.js.map +1 -0
- package/dist/{date-range-CfIIPIA_.js → date-range-CwqFuGGK.js} +2 -2
- package/dist/{date-range-CfIIPIA_.js.map → date-range-CwqFuGGK.js.map} +1 -1
- package/dist/{date-range-inline-B87TDYI6.js.map → date-range-inline-B_g1YXu3.js.map} +1 -1
- package/dist/{date-range-inline-De-M0VmL.cjs.map → date-range-inline-LLC3Y0mi.cjs.map} +1 -1
- package/dist/date-range-inline.cjs +1 -1
- package/dist/date-range-inline.js +1 -1
- package/dist/{date-range-B0kW9np7.cjs → date-range-n_xPONd5.cjs} +1 -1
- package/dist/{date-range-B0kW9np7.cjs.map → date-range-n_xPONd5.cjs.map} +1 -1
- package/dist/date-range.cjs +1 -1
- package/dist/date-range.js +1 -1
- package/dist/{delay-k_HiVnhP.cjs → delay-BFpu_Yz9.cjs} +1 -1
- package/dist/{delay-k_HiVnhP.cjs.map → delay-BFpu_Yz9.cjs.map} +1 -1
- package/dist/{delay-CPoyWZuQ.js → delay-Bkd3SOTy.js} +1 -1
- package/dist/{delay-CPoyWZuQ.js.map → delay-Bkd3SOTy.js.map} +1 -1
- package/dist/delay.cjs +1 -1
- package/dist/delay.js +1 -1
- package/dist/{details-CQIbCUY0.cjs.map → details-Bal2g3J4.cjs.map} +1 -1
- package/dist/{details-BU5kx0Jh.js.map → details-DZq61CD5.js.map} +1 -1
- package/dist/details.cjs +1 -1
- package/dist/details.js +1 -1
- package/dist/{dialog-service-ClFrOWf4.js → dialog-service-CCFGpU7a.js} +1 -1
- package/dist/{dialog-service-ClFrOWf4.js.map → dialog-service-CCFGpU7a.js.map} +1 -1
- package/dist/{dialog-service-DcuAavp2.cjs → dialog-service-DXLGSshF.cjs} +1 -1
- package/dist/{dialog-service-DcuAavp2.cjs.map → dialog-service-DXLGSshF.cjs.map} +1 -1
- package/dist/dialog.cjs +1 -1
- package/dist/dialog.js +1 -1
- package/dist/{divider-D9borfuG.js.map → divider-ChK7lCQF.js.map} +1 -1
- package/dist/{divider-IX9sp29l.cjs.map → divider-RjZbewe8.cjs.map} +1 -1
- package/dist/divider.cjs +1 -1
- package/dist/divider.js +1 -1
- package/dist/{expand-Dw9tbuFG.js → expand-CUrWPZu-.js} +1 -1
- package/dist/{expand-Dw9tbuFG.js.map → expand-CUrWPZu-.js.map} +1 -1
- package/dist/{expand-dIrDcH9Y.cjs → expand-DwZKr9hD.cjs} +1 -1
- package/dist/{expand-dIrDcH9Y.cjs.map → expand-DwZKr9hD.cjs.map} +1 -1
- package/dist/expand.cjs +1 -1
- package/dist/expand.js +1 -1
- package/dist/{extra-BFpPepJn.cjs.map → extra-BE9p8l3U.cjs.map} +1 -1
- package/dist/{extra-D3sZLtFY.js.map → extra-C7xp1GQG.js.map} +1 -1
- package/dist/extra.cjs +1 -1
- package/dist/extra.js +1 -1
- package/dist/{float-CJ3SuEcG.cjs → float-DoHSvH7R.cjs} +1 -1
- package/dist/{float-CJ3SuEcG.cjs.map → float-DoHSvH7R.cjs.map} +1 -1
- package/dist/{float-BKd4pilD.js → float-kRCgEf_1.js} +1 -1
- package/dist/{float-BKd4pilD.js.map → float-kRCgEf_1.js.map} +1 -1
- package/dist/float.cjs +1 -1
- package/dist/float.js +1 -1
- package/dist/{flow-CqgDEIqK.js.map → flow-BPDtbhLe.js.map} +1 -1
- package/dist/{flow-DSu4PLt1.cjs.map → flow-Dn9AZktE.cjs.map} +1 -1
- package/dist/{form-D2cJ58TB.js.map → form-C1qS9uvS.js.map} +1 -1
- package/dist/{form-CAY9GSCd.cjs.map → form-CzD0JLxM.cjs.map} +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.js +1 -1
- package/dist/{hashContent-nD2uWwi2.js.map → hashContent-BUqULUiZ.js.map} +1 -1
- package/dist/{hashContent-kKvXKFa9.cjs.map → hashContent-CI39BY-_.cjs.map} +1 -1
- package/dist/{icons-1AkKNd7O.cjs → icons-Bz84Dr-q.cjs} +4 -4
- package/dist/icons-Bz84Dr-q.cjs.map +1 -0
- package/dist/{icons-DqIVrIIK.js → icons-D93IZn6-.js} +29 -25
- package/dist/icons-D93IZn6-.js.map +1 -0
- package/dist/icons.cjs +1 -1
- package/dist/icons.js +1 -1
- package/dist/{iframe-CtDetaw3.cjs.map → iframe-Cmanzy9x.cjs.map} +1 -1
- package/dist/{iframe-D4R1Rq7G.js.map → iframe-DyOg96rn.js.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 +36 -36
- package/dist/{input-DMjpf6V8.cjs.map → input-DIuyi3Gm.cjs.map} +1 -1
- package/dist/{input-Ri72dn5t.js.map → input-HzweUBSn.js.map} +1 -1
- package/dist/input.cjs +1 -1
- package/dist/input.js +1 -1
- package/dist/{intersection-LfEsy29T.js.map → intersection-C0JuW_7U.js.map} +1 -1
- package/dist/{intersection-D1v1UCVv.cjs.map → intersection-MvbRovUz.cjs.map} +1 -1
- package/dist/json.cjs +1 -1
- package/dist/json.js +1 -1
- package/dist/{layout-Dh0qW7XU.js → layout-D7OCZ8rE.js} +1 -1
- package/dist/{layout-Dh0qW7XU.js.map → layout-D7OCZ8rE.js.map} +1 -1
- package/dist/{layout-B1gXjlIO.cjs → layout-DIuACbuC.cjs} +1 -1
- package/dist/{layout-B1gXjlIO.cjs.map → layout-DIuACbuC.cjs.map} +1 -1
- package/dist/layout.cjs +1 -1
- package/dist/layout.js +2 -2
- package/dist/{lightbox-BUuGltX9.cjs → lightbox-DFbqNGoX.cjs} +1 -1
- package/dist/{lightbox-BUuGltX9.cjs.map → lightbox-DFbqNGoX.cjs.map} +1 -1
- package/dist/{lightbox-BM_Bpk_l.js → lightbox-DL-v1tk9.js} +1 -1
- package/dist/{lightbox-BM_Bpk_l.js.map → lightbox-DL-v1tk9.js.map} +1 -1
- package/dist/lightbox.cjs +1 -1
- package/dist/lightbox.js +1 -1
- package/dist/{list-C1GMiAi_.cjs.map → list-D99W7WvC.cjs.map} +1 -1
- package/dist/{list-DrF_av2K.js.map → list-DZTLJ-2e.js.map} +1 -1
- package/dist/list.cjs +1 -1
- package/dist/list.js +1 -1
- package/dist/{mailbox-BjB502y9.js → mailbox-BBV6hDAa.js} +3 -3
- package/dist/{mailbox-BjB502y9.js.map → mailbox-BBV6hDAa.js.map} +1 -1
- package/dist/{mailbox-D0iXsqyx.cjs → mailbox-CW7zc0v-.cjs} +1 -1
- package/dist/{mailbox-D0iXsqyx.cjs.map → mailbox-CW7zc0v-.cjs.map} +1 -1
- package/dist/mailbox.cjs +1 -1
- package/dist/mailbox.js +1 -1
- package/dist/{map-uRYJeifl.cjs.map → map-CSQMA89X.cjs.map} +1 -1
- package/dist/{map-BZTxFRVH.js.map → map-PvojF8B3.js.map} +1 -1
- package/dist/map.cjs +1 -1
- package/dist/map.js +1 -1
- package/dist/{menu-CXFa_bk4.cjs → menu-3XXOfmrj.cjs} +1 -1
- package/dist/{menu-CXFa_bk4.cjs.map → menu-3XXOfmrj.cjs.map} +1 -1
- package/dist/{menu-BamT46lt.js → menu-B_o1fOPW.js} +1 -1
- package/dist/{menu-BamT46lt.js.map → menu-B_o1fOPW.js.map} +1 -1
- package/dist/menu.cjs +1 -1
- package/dist/menu.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/{notification-COgjQodt.js → notification-BMtrJG-Y.js} +1 -1
- package/dist/{notification-COgjQodt.js.map → notification-BMtrJG-Y.js.map} +1 -1
- package/dist/{notification-Xid-o7gi.cjs → notification-NnsatHAh.cjs} +1 -1
- package/dist/{notification-Xid-o7gi.cjs.map → notification-NnsatHAh.cjs.map} +1 -1
- package/dist/notification.cjs +1 -1
- package/dist/notification.js +1 -1
- package/dist/{option-DdYe_l1A.js.map → option-CNzW-sdU.js.map} +1 -1
- package/dist/{option-CNWUeHW3.cjs.map → option-DxIFpYpC.cjs.map} +1 -1
- package/dist/option.cjs +1 -1
- package/dist/option.js +1 -1
- package/dist/{overlay-stack-Ca4EK2Mu.js.map → overlay-stack-BJt_r6aZ.js.map} +1 -1
- package/dist/{overlay-stack-CEYGD9T1.cjs.map → overlay-stack-J_eJCUTX.cjs.map} +1 -1
- package/dist/page.cjs +1 -1
- package/dist/page.js +1 -1
- package/dist/{progress-Bw-VD6wH.cjs.map → progress-Cw6Qn3Kb.cjs.map} +1 -1
- package/dist/{progress-OQvbUkDs.js.map → progress-DHmYCHmy.js.map} +1 -1
- package/dist/progress.cjs +1 -1
- package/dist/progress.js +1 -1
- package/dist/{radio-group-DI1JXW5r.js.map → radio-group-DneItRXU.js.map} +1 -1
- package/dist/{radio-group-D5t8f2Ob.cjs.map → radio-group-xgKQTd6h.cjs.map} +1 -1
- package/dist/radio-group.cjs +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/{rxjs-utils-Bldch1RO.js.map → rxjs-utils-CN9fv8Xq.js.map} +1 -1
- package/dist/{rxjs-utils-hAgKC7vk.cjs.map → rxjs-utils-Vn6DCKgL.cjs.map} +1 -1
- package/dist/rxjs-utils.cjs +1 -1
- package/dist/rxjs-utils.js +1 -1
- package/dist/{scroll-Dym-6yPI.js.map → scroll-D7QJYev7.js.map} +1 -1
- package/dist/{scroll-BG5qMncw.cjs.map → scroll-DZAB4JFv.cjs.map} +1 -1
- package/dist/{select-C3L3imJM.js → select-B2T3RZng.js} +1 -1
- package/dist/{select-C3L3imJM.js.map → select-B2T3RZng.js.map} +1 -1
- package/dist/{select-B1nN5Ac4.cjs → select-D2eLEDUT.cjs} +1 -1
- package/dist/{select-B1nN5Ac4.cjs.map → select-D2eLEDUT.cjs.map} +1 -1
- package/dist/select.cjs +1 -1
- package/dist/select.js +1 -1
- package/dist/{sheet-BS9WlMaj.js → sheet-BiGXZPdu.js} +1 -1
- package/dist/{sheet-BS9WlMaj.js.map → sheet-BiGXZPdu.js.map} +1 -1
- package/dist/{sheet-BZRMpyXt.cjs → sheet-NaecDxuR.cjs} +1 -1
- package/dist/{sheet-BZRMpyXt.cjs.map → sheet-NaecDxuR.cjs.map} +1 -1
- package/dist/sheet.cjs +1 -1
- package/dist/sheet.js +2 -2
- package/dist/{sheet.service-l9jTUaot.cjs → sheet.service-CQq5hUNb.cjs} +1 -1
- package/dist/{sheet.service-l9jTUaot.cjs.map → sheet.service-CQq5hUNb.cjs.map} +1 -1
- package/dist/{sheet.service-DQWkiYEe.js → sheet.service-gek7Spb6.js} +1 -1
- package/dist/{sheet.service-DQWkiYEe.js.map → sheet.service-gek7Spb6.js.map} +1 -1
- package/dist/skills/SKILL.md +1 -1
- package/dist/skills/schmancy/SKILL.md +1 -1
- package/dist/{splash-screen-DuFJ0gbD.cjs.map → splash-screen-CxPHf-SC.cjs.map} +1 -1
- package/dist/{splash-screen-M-v_jiLs.js.map → splash-screen-Dc6LDIbK.js.map} +1 -1
- package/dist/splash-screen.cjs +1 -1
- package/dist/splash-screen.js +1 -1
- package/dist/{src-Ba-S6DFW.cjs → src-BP8bYUHc.cjs} +1 -1
- package/dist/{src-Ba-S6DFW.cjs.map → src-BP8bYUHc.cjs.map} +1 -1
- package/dist/{src-CbR3znbw.js → src-BYrvfmFF.js} +39 -39
- package/dist/{src-CbR3znbw.js.map → src-BYrvfmFF.js.map} +1 -1
- package/dist/{surface-kM2aYH4g.js.map → surface-B2cmGNZ2.js.map} +1 -1
- package/dist/{surface-PECoCLgx.cjs.map → surface-C9plkl5F.cjs.map} +1 -1
- package/dist/surface.cjs +1 -1
- package/dist/surface.js +1 -1
- package/dist/{table-CENjXiu-.cjs → table-6xNLZh3K.cjs} +2 -2
- package/dist/{table-CENjXiu-.cjs.map → table-6xNLZh3K.cjs.map} +1 -1
- package/dist/{table-DrMgc8Aw.js → table-BCJgjSvq.js} +2 -2
- package/dist/{table-DrMgc8Aw.js.map → table-BCJgjSvq.js.map} +1 -1
- package/dist/table.cjs +1 -1
- package/dist/table.js +1 -1
- package/dist/{tabs-BvFiM0y-.js.map → tabs-BDqvhB54.js.map} +1 -1
- package/dist/{tabs-CRA9FMNl.cjs.map → tabs-pvevSaFB.cjs.map} +1 -1
- package/dist/tabs.cjs +1 -1
- package/dist/tabs.js +1 -1
- package/dist/tailwind.mixin-Bug3G6K6.cjs.map +1 -1
- package/dist/tailwind.mixin-ywtUNG2c.js.map +1 -1
- package/dist/teleport.cjs +1 -1
- package/dist/teleport.js +1 -1
- package/dist/{textarea-DD5gxIsG.js.map → textarea-BvZn41aa.js.map} +1 -1
- package/dist/{textarea-CfwGEIvf.cjs.map → textarea-D2v000gK.cjs.map} +1 -1
- package/dist/textarea.cjs +1 -1
- package/dist/textarea.js +1 -1
- package/dist/{theme-BiM_CUpn.cjs → theme-Dw9Ag_VS.cjs} +1 -1
- package/dist/{theme-BiM_CUpn.cjs.map → theme-Dw9Ag_VS.cjs.map} +1 -1
- package/dist/{theme-DNJmVFXF.js → theme-JvXazXJr.js} +1 -1
- package/dist/{theme-DNJmVFXF.js.map → theme-JvXazXJr.js.map} +1 -1
- package/dist/{theme-button-19T3SFrv.js.map → theme-button-Bh8wKXtV.js.map} +1 -1
- package/dist/{theme-button-BwJs6N4k.cjs.map → theme-button-qHd4AFsE.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-CM26m9te.cjs.map → theme.interface-CCE3L1ql.cjs.map} +1 -1
- package/dist/{theme.interface-FAUIgbIq.js.map → theme.interface-Cyqv5XWY.js.map} +1 -1
- package/dist/theme.js +2 -2
- package/dist/{tslib.es6-Bd-92OW3.cjs.map → tslib.es6-PMITL0Z3.cjs.map} +1 -1
- package/dist/{tslib.es6-CI1onEZb.js.map → tslib.es6-vJQZBGJO.js.map} +1 -1
- package/dist/{typewriter-BH7nsW7R.cjs → typewriter-C5uDB2Lu.cjs} +1 -1
- package/dist/{typewriter-BH7nsW7R.cjs.map → typewriter-C5uDB2Lu.cjs.map} +1 -1
- package/dist/{typewriter-Z-8bbwOh.js → typewriter-PpYJFsVi.js} +3 -3
- package/dist/{typewriter-Z-8bbwOh.js.map → typewriter-PpYJFsVi.js.map} +1 -1
- package/dist/typewriter.cjs +1 -1
- package/dist/typewriter.js +1 -1
- package/dist/{utils-D2kE-6zc.cjs → utils-C8PD8So2.cjs} +1 -1
- package/dist/{utils-D2kE-6zc.cjs.map → utils-C8PD8So2.cjs.map} +1 -1
- package/dist/{utils-Cq0m3LYo.js → utils-DVuCPDfw.js} +2 -2
- package/dist/{utils-Cq0m3LYo.js.map → utils-DVuCPDfw.js.map} +1 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +3 -3
- package/dist/{window-Du_ougyw.js → window-ChDgkb97.js} +1 -1
- package/dist/{window-Du_ougyw.js.map → window-ChDgkb97.js.map} +1 -1
- package/dist/{window-NDXXyj5v.cjs → window-Czfu-i4Y.cjs} +1 -1
- package/dist/{window-NDXXyj5v.cjs.map → window-Czfu-i4Y.cjs.map} +1 -1
- package/dist/window.cjs +1 -1
- package/dist/window.js +1 -1
- package/package.json +1 -1
- package/skills/schmancy/SKILL.md +1 -1
- package/src/button/button.ts +6 -1
- package/src/button/context.ts +9 -0
- package/src/icons/icon.ts +19 -3
- package/types/src/button/button.d.ts +4 -1
- package/types/src/button/context.d.ts +8 -0
- package/types/src/icons/icon.d.ts +9 -0
- package/dist/icons-1AkKNd7O.cjs.map +0 -1
- package/dist/icons-DqIVrIIK.js.map +0 -1
- /package/dist/{card-DUq_MsxC.cjs → card-Bht1QcYl.cjs} +0 -0
- /package/dist/{card-C8Ns2mRo.js → card-DiNYPJ9b.js} +0 -0
- /package/dist/{chips-0rKPqQt8.js → chips-Bma_B3J-.js} +0 -0
- /package/dist/{chips-BI_kt5BS.cjs → chips-CXknD-vY.cjs} +0 -0
- /package/dist/{code-highlight-DGInmDAW.cjs → code-highlight-BROOsNA_.cjs} +0 -0
- /package/dist/{code-highlight-ClzG4FL4.js → code-highlight-DjiyaDcX.js} +0 -0
- /package/dist/{components-RbvrLE3U.js → components-DKgu88mm.js} +0 -0
- /package/dist/{components-7hOtFi_q.cjs → components-ubXwQbGs.cjs} +0 -0
- /package/dist/{date-range-inline-B87TDYI6.js → date-range-inline-B_g1YXu3.js} +0 -0
- /package/dist/{date-range-inline-De-M0VmL.cjs → date-range-inline-LLC3Y0mi.cjs} +0 -0
- /package/dist/{details-CQIbCUY0.cjs → details-Bal2g3J4.cjs} +0 -0
- /package/dist/{details-BU5kx0Jh.js → details-DZq61CD5.js} +0 -0
- /package/dist/{divider-D9borfuG.js → divider-ChK7lCQF.js} +0 -0
- /package/dist/{divider-IX9sp29l.cjs → divider-RjZbewe8.cjs} +0 -0
- /package/dist/{extra-BFpPepJn.cjs → extra-BE9p8l3U.cjs} +0 -0
- /package/dist/{extra-D3sZLtFY.js → extra-C7xp1GQG.js} +0 -0
- /package/dist/{flow-CqgDEIqK.js → flow-BPDtbhLe.js} +0 -0
- /package/dist/{flow-DSu4PLt1.cjs → flow-Dn9AZktE.cjs} +0 -0
- /package/dist/{form-D2cJ58TB.js → form-C1qS9uvS.js} +0 -0
- /package/dist/{form-CAY9GSCd.cjs → form-CzD0JLxM.cjs} +0 -0
- /package/dist/{hashContent-nD2uWwi2.js → hashContent-BUqULUiZ.js} +0 -0
- /package/dist/{hashContent-kKvXKFa9.cjs → hashContent-CI39BY-_.cjs} +0 -0
- /package/dist/{iframe-CtDetaw3.cjs → iframe-Cmanzy9x.cjs} +0 -0
- /package/dist/{iframe-D4R1Rq7G.js → iframe-DyOg96rn.js} +0 -0
- /package/dist/{input-DMjpf6V8.cjs → input-DIuyi3Gm.cjs} +0 -0
- /package/dist/{input-Ri72dn5t.js → input-HzweUBSn.js} +0 -0
- /package/dist/{intersection-LfEsy29T.js → intersection-C0JuW_7U.js} +0 -0
- /package/dist/{intersection-D1v1UCVv.cjs → intersection-MvbRovUz.cjs} +0 -0
- /package/dist/{list-C1GMiAi_.cjs → list-D99W7WvC.cjs} +0 -0
- /package/dist/{list-DrF_av2K.js → list-DZTLJ-2e.js} +0 -0
- /package/dist/{map-uRYJeifl.cjs → map-CSQMA89X.cjs} +0 -0
- /package/dist/{map-BZTxFRVH.js → map-PvojF8B3.js} +0 -0
- /package/dist/{option-DdYe_l1A.js → option-CNzW-sdU.js} +0 -0
- /package/dist/{option-CNWUeHW3.cjs → option-DxIFpYpC.cjs} +0 -0
- /package/dist/{overlay-stack-Ca4EK2Mu.js → overlay-stack-BJt_r6aZ.js} +0 -0
- /package/dist/{overlay-stack-CEYGD9T1.cjs → overlay-stack-J_eJCUTX.cjs} +0 -0
- /package/dist/{progress-Bw-VD6wH.cjs → progress-Cw6Qn3Kb.cjs} +0 -0
- /package/dist/{progress-OQvbUkDs.js → progress-DHmYCHmy.js} +0 -0
- /package/dist/{radio-group-DI1JXW5r.js → radio-group-DneItRXU.js} +0 -0
- /package/dist/{radio-group-D5t8f2Ob.cjs → radio-group-xgKQTd6h.cjs} +0 -0
- /package/dist/{rxjs-utils-Bldch1RO.js → rxjs-utils-CN9fv8Xq.js} +0 -0
- /package/dist/{rxjs-utils-hAgKC7vk.cjs → rxjs-utils-Vn6DCKgL.cjs} +0 -0
- /package/dist/{scroll-Dym-6yPI.js → scroll-D7QJYev7.js} +0 -0
- /package/dist/{scroll-BG5qMncw.cjs → scroll-DZAB4JFv.cjs} +0 -0
- /package/dist/{splash-screen-DuFJ0gbD.cjs → splash-screen-CxPHf-SC.cjs} +0 -0
- /package/dist/{splash-screen-M-v_jiLs.js → splash-screen-Dc6LDIbK.js} +0 -0
- /package/dist/{surface-kM2aYH4g.js → surface-B2cmGNZ2.js} +0 -0
- /package/dist/{surface-PECoCLgx.cjs → surface-C9plkl5F.cjs} +0 -0
- /package/dist/{tabs-BvFiM0y-.js → tabs-BDqvhB54.js} +0 -0
- /package/dist/{tabs-CRA9FMNl.cjs → tabs-pvevSaFB.cjs} +0 -0
- /package/dist/{textarea-DD5gxIsG.js → textarea-BvZn41aa.js} +0 -0
- /package/dist/{textarea-CfwGEIvf.cjs → textarea-D2v000gK.cjs} +0 -0
- /package/dist/{theme-button-19T3SFrv.js → theme-button-Bh8wKXtV.js} +0 -0
- /package/dist/{theme-button-BwJs6N4k.cjs → theme-button-qHd4AFsE.cjs} +0 -0
- /package/dist/{theme.interface-CM26m9te.cjs → theme.interface-CCE3L1ql.cjs} +0 -0
- /package/dist/{theme.interface-FAUIgbIq.js → theme.interface-Cyqv5XWY.js} +0 -0
- /package/dist/{tslib.es6-Bd-92OW3.cjs → tslib.es6-PMITL0Z3.cjs} +0 -0
- /package/dist/{tslib.es6-CI1onEZb.js → tslib.es6-vJQZBGJO.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"window-NDXXyj5v.cjs","names":[],"sources":["../src/window/window-manager.ts","../src/window/window-position.ts","../src/window/window.ts"],"sourcesContent":["/**\n * Window Manager — singleton service for multi-window coordination.\n *\n * Tracks all schmancy-window instances: positions, z-indices, focus, visual states.\n * Components register on connectedCallback, unregister on disconnectedCallback.\n * Focus changes, position updates, and overlap queries all flow through here.\n *\n * Follows the ThemeService singleton pattern (theme/theme.service.ts).\n *\n * Example:\n * windowManager.register('chat-1', bounds, 'bottom-right')\n * windowManager.focus('chat-1') // bumps z-index, updates focusedId\n * const overlaps = windowManager.findOverlaps(projectedBounds, 'chat-1')\n */\n\nimport { BehaviorSubject, Observable, distinctUntilChanged, map } from 'rxjs'\nimport { overlayStack } from '../utils/overlay-stack.js'\nimport type { WindowBounds, WindowRecord, WindowRegistryState, SnapTarget } from './window-registry.js'\n\nconst STORAGE_PREFIX = 'schmancy-window-'\nconst LEGACY_STORAGE_PREFIX = 'schmancy-float-'\n\nclass WindowManagerService {\n\tprivate static instance: WindowManagerService\n\n\tprivate readonly _state$ = new BehaviorSubject<WindowRegistryState>({\n\t\twindows: new Map(),\n\t\tfocusedId: null,\n\t\tstackOrder: [],\n\t})\n\n\treadonly state$ = this._state$.asObservable()\n\n\tprivate constructor() {}\n\n\tstatic getInstance(): WindowManagerService {\n\t\tif (!WindowManagerService.instance) {\n\t\t\tWindowManagerService.instance = new WindowManagerService()\n\t\t}\n\t\treturn WindowManagerService.instance\n\t}\n\n\t// ── Synchronous accessors ──────────────────────────────────────────\n\n\tget windows(): Map<string, WindowRecord> {\n\t\treturn this._state$.value.windows\n\t}\n\n\tget focusedId(): string | null {\n\t\treturn this._state$.value.focusedId\n\t}\n\n\t// ── Registration ───────────────────────────────────────────────────\n\n\tregister(id: string, initialBounds: WindowBounds, snapTarget: SnapTarget): void {\n\t\tconst state = this._state$.value\n\t\tif (state.windows.has(id)) return\n\n\t\tconst zIndex = overlayStack.assignZIndex(id)\n\t\tconst record: WindowRecord = {\n\t\t\tid,\n\t\t\tbounds: initialBounds,\n\t\t\tvisualState: 'normal',\n\t\t\tzIndex,\n\t\t\topen: false,\n\t\t\tsnapTarget,\n\t\t}\n\n\t\tconst windows = new Map(state.windows)\n\t\twindows.set(id, record)\n\t\tconst stackOrder = overlayStack.getStackOrder()\n\n\t\tthis._state$.next({ ...state, windows, stackOrder })\n\t}\n\n\tunregister(id: string): void {\n\t\tconst state = this._state$.value\n\t\tif (!state.windows.has(id)) return\n\n\t\toverlayStack.releaseId(id)\n\t\tconst windows = new Map(state.windows)\n\t\twindows.delete(id)\n\t\tconst stackOrder = overlayStack.getStackOrder()\n\t\tconst focusedId = state.focusedId === id ? null : state.focusedId\n\n\t\tthis._state$.next({ ...state, windows, stackOrder, focusedId })\n\t}\n\n\t// ── State mutations ────────────────────────────────────────────────\n\n\tupdateBounds(id: string, bounds: WindowBounds): void {\n\t\tthis._updateRecord(id, { bounds })\n\t}\n\n\tupdateVisualState(id: string, visualState: WindowRecord['visualState']): void {\n\t\tthis._updateRecord(id, { visualState })\n\t}\n\n\tupdateOpen(id: string, open: boolean): void {\n\t\tthis._updateRecord(id, { open })\n\t}\n\n\tfocus(id: string): void {\n\t\tconst state = this._state$.value\n\t\tif (!state.windows.has(id)) return\n\t\tif (state.focusedId === id) return\n\n\t\tconst zIndex = overlayStack.bringToFront(id)\n\t\tconst windows = new Map(state.windows)\n\t\tconst record = windows.get(id)\n\t\tif (record) {\n\t\t\twindows.set(id, { ...record, zIndex })\n\t\t}\n\t\tconst stackOrder = overlayStack.getStackOrder()\n\n\t\tthis._state$.next({ ...state, windows, stackOrder, focusedId: id })\n\t}\n\n\t// ── Queries ────────────────────────────────────────────────────────\n\n\tfindOverlaps(bounds: WindowBounds, excludeId: string): WindowRecord[] {\n\t\tconst result: WindowRecord[] = []\n\t\tfor (const [id, record] of this._state$.value.windows) {\n\t\t\tif (id === excludeId) continue\n\t\t\tif (rectsOverlap(bounds, record.bounds)) {\n\t\t\t\tresult.push(record)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tgetNeighbors(id: string): WindowRecord[] {\n\t\tconst result: WindowRecord[] = []\n\t\tfor (const [otherId, record] of this._state$.value.windows) {\n\t\t\tif (otherId !== id) result.push(record)\n\t\t}\n\t\treturn result\n\t}\n\n\t// ── Selectors ──────────────────────────────────────────────────────\n\n\tselectWindow(id: string): Observable<WindowRecord | undefined> {\n\t\treturn this._state$.pipe(\n\t\t\tmap(state => state.windows.get(id)),\n\t\t\tdistinctUntilChanged(),\n\t\t)\n\t}\n\n\tselectFocused(): Observable<string | null> {\n\t\treturn this._state$.pipe(\n\t\t\tmap(state => state.focusedId),\n\t\t\tdistinctUntilChanged(),\n\t\t)\n\t}\n\n\t// ── Persistence ────────────────────────────────────────────────────\n\n\tloadPosition(id: string): { x: number; y: number; anchor: string } | null {\n\t\ttry {\n\t\t\t// Try new key first, fall back to legacy\n\t\t\tconst raw = localStorage.getItem(STORAGE_PREFIX + id) ?? localStorage.getItem(LEGACY_STORAGE_PREFIX + id)\n\t\t\tif (!raw) return null\n\t\t\treturn JSON.parse(raw) as { x: number; y: number; anchor: string }\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tsavePosition(id: string, data: { x: number; y: number; anchor: string }): void {\n\t\ttry {\n\t\t\tlocalStorage.setItem(STORAGE_PREFIX + id, JSON.stringify(data))\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\tclearPosition(id: string): void {\n\t\ttry {\n\t\t\tlocalStorage.removeItem(STORAGE_PREFIX + id)\n\t\t\tlocalStorage.removeItem(LEGACY_STORAGE_PREFIX + id)\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\t// ── Internal ───────────────────────────────────────────────────────\n\n\tprivate _updateRecord(id: string, updates: Partial<WindowRecord>): void {\n\t\tconst state = this._state$.value\n\t\tconst record = state.windows.get(id)\n\t\tif (!record) return\n\n\t\tconst windows = new Map(state.windows)\n\t\twindows.set(id, { ...record, ...updates })\n\t\tthis._state$.next({ ...state, windows })\n\t}\n}\n\n/** Simple rect overlap check (inline — no circular import with window-position) */\nfunction rectsOverlap(a: WindowBounds, b: WindowBounds): boolean {\n\treturn !(a.left >= b.left + b.width || a.left + a.width <= b.left || a.top >= b.top + b.height || a.top + a.height <= b.top)\n}\n\nexport const windowManager = WindowManagerService.getInstance()\n","/**\n * Window Position — pure functions for overlap resolution, cascade, and snapping.\n *\n * All functions are stateless: they take window bounds and viewport dimensions,\n * return new bounds. No side effects, no DOM access, no subscriptions.\n *\n * Example:\n * const projected = { left: 100, top: 400, width: 360, height: 500 }\n * const neighbors = windowManager.findOverlaps(projected, 'my-id')\n * const resolved = resolveOverlap(projected, neighbors, { width: 1440, height: 900 })\n * // → { left: 144, top: 444, width: 360, height: 500 } (cascaded away from conflict)\n */\n\nimport type { WindowBounds, WindowRecord } from './window-registry.js'\n\nconst HEAD_HEIGHT = 44\nconst CASCADE_OFFSET = HEAD_HEIGHT\nconst MAX_CASCADE_ATTEMPTS = 10\n\n/** Check if two rectangles overlap (edges touching does NOT count as overlap) */\nexport function rectsOverlap(a: WindowBounds, b: WindowBounds): boolean {\n\treturn !(a.left >= b.left + b.width || a.left + a.width <= b.left || a.top >= b.top + b.height || a.top + a.height <= b.top)\n}\n\n/**\n * Resolve overlap by cascading diagonally until no conflict.\n * Shifts by (HEAD_HEIGHT, HEAD_HEIGHT) per attempt, clamped to viewport.\n */\nexport function resolveOverlap(\n\tcandidate: WindowBounds,\n\texisting: WindowRecord[],\n\tviewport: { width: number; height: number },\n): WindowBounds {\n\tlet bounds = { ...candidate }\n\n\tfor (let attempt = 0; attempt < MAX_CASCADE_ATTEMPTS; attempt++) {\n\t\tconst hasOverlap = existing.some(w => rectsOverlap(bounds, w.bounds))\n\t\tif (!hasOverlap) break\n\n\t\tbounds = {\n\t\t\t...bounds,\n\t\t\tleft: bounds.left + CASCADE_OFFSET,\n\t\t\ttop: bounds.top + CASCADE_OFFSET,\n\t\t}\n\t}\n\n\treturn clampToViewport(bounds, viewport)\n}\n\n/**\n * Clamp bounds so the window stays fully within the viewport.\n */\nexport function clampToViewport(\n\tbounds: WindowBounds,\n\tviewport: { width: number; height: number },\n): WindowBounds {\n\treturn {\n\t\twidth: bounds.width,\n\t\theight: bounds.height,\n\t\tleft: Math.max(0, Math.min(bounds.left, viewport.width - bounds.width)),\n\t\ttop: Math.max(0, Math.min(bounds.top, viewport.height - bounds.height)),\n\t}\n}\n","import { $LitElement } from '@mixins/index'\nimport { css, html, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { styleMap } from 'lit/directives/style-map.js'\nimport {\n\tanimationFrameScheduler,\n\tauditTime,\n\tcatchError,\n\tEMPTY,\n\tfilter,\n\tfinalize,\n\tfrom,\n\tfromEvent,\n\tmap,\n\tmerge,\n\tObservable,\n\tswitchMap,\n\ttake,\n\ttakeUntil,\n\ttap,\n} from 'rxjs'\nimport { SPRING_SMOOTH, SPRING_SNAPPY } from '../utils/animation.js'\nimport { cursorGlow } from '../directives/cursor-glow'\nimport { reducedMotion$ } from '../directives/reduced-motion'\nimport { theme } from '../theme/theme.service.js'\nimport type { SnapCorner, WindowBounds, WindowVisualState } from './window-registry.js'\nimport { windowManager } from './window-manager.js'\nimport { resolveOverlap } from './window-position.js'\n\nconst HEAD_HEIGHT = 48\nconst DRAG_THRESHOLD = 5\n\ninterface Position {\n\tx: number\n\ty: number\n}\n\n@customElement('schmancy-window')\nexport default class SchmancyWindow extends $LitElement(css`\n\t:host {\n\t\tdisplay: contents;\n\t\tposition: relative;\n\t\tz-index: 1000;\n\t}\n\t:host([hidden]) {\n\t\tdisplay: none !important;\n\t}\n`) {\n\t@property({ type: String }) id: string = 'default'\n\t/** Override the expanded panel width (e.g. '320px', '24rem'). Defaults to responsive sizing. */\n\t@property({ type: String }) expandedWidth?: string\n\t/** Override the expanded panel height (e.g. '400px', '50vh'). */\n\t@property({ type: String }) expandedHeight?: string\n\t/** When true, uses a lower elevation shadow in the collapsed state. */\n\t@property({ type: Boolean, reflect: true }) lowered: boolean = false\n\t/** Corner the window is anchored to. */\n\t@property({ type: String }) corner: SnapCorner = 'bottom-right'\n\t/** When true, window can be resized by the user. */\n\t@property({ type: Boolean }) resizable = false\n\t/** When true, window stays at its dragged position instead of snapping to a corner. */\n\t@property({ type: Boolean }) freePosition = false\n\t/** Visual state of the window (minimized, normal, maximized). */\n\t@property({ type: String, reflect: true }) visualState: WindowVisualState = 'normal'\n\t/** Minimum width in pixels. */\n\t@property({ type: Number }) minWidth = 280\n\t/** Minimum height in pixels. */\n\t@property({ type: Number }) minHeight = 200\n\n\t/** Whether the body is expanded. */\n\t@property({ type: Boolean, reflect: true }) open = false\n\n\tprivate _currentAnimation?: Animation\n\n\t/** Lazy rendering: body content not in DOM until first expand. */\n\t@state() private _hasOpened = false\n\t/** Whether this window is the focused window in the manager — drives visual ring */\n\t@state() private _focused = false\n\n\t// Internal position -- plain fields, updated directly during drag\n\tprivate _position: Position = { x: 16, y: 16 }\n\t@state() private _currentCorner: SnapCorner = 'bottom-right'\n\n\t// Track applied corner to avoid unnecessary style.removeProperty calls during drag\n\tprivate _appliedCorner: string = ''\n\n\t// Refs\n\tprivate _containerRef = createRef<HTMLElement>()\n\tprivate _bodyRef = createRef<HTMLElement>()\n\tprivate _headRef = createRef<HTMLElement>()\n\n\t// ============================================\n\t// COMPUTED\n\t// ============================================\n\n\tprivate get panelWidth(): string {\n\t\treturn this.expandedWidth ?? 'min(360px, calc(100vw - 32px))'\n\t}\n\n\tprivate get isBottomCorner(): boolean {\n\t\treturn this._currentCorner.startsWith('bottom')\n\t}\n\n\tprivate get closedClipPath(): string {\n\t\treturn this.isBottomCorner\n\t\t\t? `inset(calc(100% - ${HEAD_HEIGHT}px) 0px 0px 0px round 22px)`\n\t\t\t: `inset(0px 0px calc(100% - ${HEAD_HEIGHT}px) 0px round 22px)`\n\t}\n\n\tprivate get openClipPath(): string {\n\t\treturn 'inset(0px 0px 0px 0px round 12px)'\n\t}\n\n\tprivate get elevation(): string {\n\t\tif (this.open) return '4'\n\t\treturn this.lowered ? '1' : '3'\n\t}\n\n\t// ============================================\n\t// POSITION MANAGEMENT\n\t// ============================================\n\n\tprivate _applyContainerPosition() {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\t\t// Only clear position properties when corner changes (avoids 4 style invalidations per drag frame)\n\t\tif (this._appliedCorner !== this._currentCorner) {\n\t\t\tcontainer.style.removeProperty('left')\n\t\t\tcontainer.style.removeProperty('right')\n\t\t\tcontainer.style.removeProperty('top')\n\t\t\tcontainer.style.removeProperty('bottom')\n\t\t\tthis._appliedCorner = this._currentCorner\n\t\t}\n\t\tconst { x, y } = this._position\n\t\tif (this._currentCorner.includes('right')) {\n\t\t\tcontainer.style.right = `${x}px`\n\t\t} else {\n\t\t\tcontainer.style.left = `${x}px`\n\t\t}\n\t\tif (this._currentCorner.includes('bottom')) {\n\t\t\tcontainer.style.bottom = `${y + theme.bottomOffset}px`\n\t\t} else {\n\t\t\tcontainer.style.top = `${y}px`\n\t\t}\n\t}\n\n\tprivate static readonly VALID_CORNERS = new Set<string>(['top-left', 'top-right', 'bottom-left', 'bottom-right'])\n\n\tprivate _loadPosition() {\n\t\tconst saved = windowManager.loadPosition(this.id)\n\t\tif (saved) {\n\t\t\tthis._position = { x: saved.x, y: saved.y }\n\t\t\tif (SchmancyWindow.VALID_CORNERS.has(saved.anchor)) {\n\t\t\t\tthis._currentCorner = saved.anchor as SnapCorner\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _savePosition() {\n\t\twindowManager.savePosition(this.id, { ...this._position, anchor: this._currentCorner })\n\t}\n\n\tprivate _validateBounds() {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\t\tconst rect = container.getBoundingClientRect()\n\t\tif (rect.width === 0) return\n\t\tconst vw = window.innerWidth\n\t\tconst vh = window.innerHeight\n\t\tconst isRight = this._currentCorner.includes('right')\n\t\tconst isBottom = this._currentCorner.includes('bottom')\n\t\tconst actualLeft = isRight ? vw - this._position.x - rect.width : this._position.x\n\t\tconst actualTop = isBottom ? vh - this._position.y - rect.height : this._position.y\n\t\tconst newLeft = Math.max(0, Math.min(actualLeft, vw - rect.width))\n\t\tconst newTop = Math.max(0, Math.min(actualTop, vh - rect.height))\n\t\tthis._position = {\n\t\t\tx: isRight ? vw - newLeft - rect.width : newLeft,\n\t\t\ty: isBottom ? vh - newTop - rect.height : newTop,\n\t\t}\n\t\tthis._applyContainerPosition()\n\t}\n\n\t// ============================================\n\t// CORNER SNAPPING\n\t// ============================================\n\n\tprivate _reorientToNearestCorner(skipAnimation = false): void {\n\t\t// Free position mode: skip corner snapping\n\t\tif (this.freePosition) {\n\t\t\tthis._savePosition()\n\t\t\tconst rect = this._containerRef.value?.getBoundingClientRect()\n\t\t\tif (rect) {\n\t\t\t\twindowManager.updateBounds(this.id, { left: rect.left, top: rect.top, width: rect.width, height: rect.height })\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\n\t\t// F -- record current screen position before DOM mutation\n\t\tconst rect = container.getBoundingClientRect()\n\n\t\t// L -- calculate nearest corner using head visual center\n\t\tconst currentIsBottom = this._currentCorner.includes('bottom')\n\t\tconst headCenterX = rect.left + rect.width / 2\n\t\tconst headCenterY = currentIsBottom\n\t\t\t? rect.bottom - HEAD_HEIGHT / 2\n\t\t\t: rect.top + HEAD_HEIGHT / 2\n\t\tconst side = headCenterX > window.innerWidth / 2 ? 'right' : 'left'\n\t\tconst vert = headCenterY > window.innerHeight / 2 ? 'bottom' : 'top'\n\t\tconst newCorner: SnapCorner = `${vert}-${side}` as SnapCorner\n\n\t\t// Snap corner and reset offset to standard edge gap\n\t\tthis._currentCorner = newCorner\n\t\tthis._position = { x: 16, y: 16 }\n\t\tthis._applyContainerPosition()\n\t\t// Sync clip-path to new corner\n\t\tif (!this.open) {\n\t\t\tcontainer.style.clipPath = this.closedClipPath\n\t\t}\n\n\t\tif (skipAnimation || reducedMotion$.value) {\n\t\t\tthis._savePosition()\n\t\t\tconst snapRect = container.getBoundingClientRect()\n\t\t\twindowManager.updateBounds(this.id, { left: snapRect.left, top: snapRect.top, width: snapRect.width, height: snapRect.height })\n\t\t\treturn\n\t\t}\n\n\t\t// I -- invert: shift element back to its original visual position\n\t\tconst newRect = container.getBoundingClientRect()\n\t\tconst dx = rect.left - newRect.left\n\t\tconst dy = rect.top - newRect.top\n\t\tcontainer.style.translate = `${dx}px ${dy}px`\n\n\t\t// P -- play: animate from the inverse offset to natural resting position\n\t\tconst flipKeyframes: Keyframe[] = [{ translate: `${dx}px ${dy}px` }, { translate: '0px 0px' }]\n\t\tconst anim = container.animate(\n\t\t\tflipKeyframes,\n\t\t\t{\n\t\t\t\tduration: SPRING_SMOOTH.duration,\n\t\t\t\teasing: SPRING_SMOOTH.easingFallback,\n\t\t\t\tfill: 'forwards',\n\t\t\t},\n\t\t)\n\t\tfrom(anim.finished).pipe(\n\t\t\ttake(1),\n\t\t\ttap(() => {\n\t\t\t\tif (container.isConnected) container.style.translate = ''\n\t\t\t\t// Report final resting bounds after animation completes\n\t\t\t\tconst finalRect = container.getBoundingClientRect()\n\t\t\t\twindowManager.updateBounds(this.id, { left: finalRect.left, top: finalRect.top, width: finalRect.width, height: finalRect.height })\n\t\t\t}),\n\t\t\tcatchError(() => EMPTY),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\n\t\tthis._savePosition()\n\t}\n\n\t// ============================================\n\t// DRAG PIPELINE\n\t// ============================================\n\n\tprivate _drag$(): Observable<never> {\n\t\treturn new Observable(() => {\n\t\t\tconst head = this._headRef.value\n\t\t\tconst container = this._containerRef.value\n\t\t\tif (!head || !container) return\n\n\t\t\tlet didDrag = false\n\n\t\t\tconst sub = fromEvent<PointerEvent>(head, 'pointerdown').pipe(\n\t\t\t\tfilter(e => e.button === 0),\n\t\t\t\tfilter(e => {\n\t\t\t\t\tconst tag = (e.target as HTMLElement).tagName?.toLowerCase()\n\t\t\t\t\treturn !['input', 'textarea', 'select', 'button'].includes(tag)\n\t\t\t\t\t\t&& !(e.target as HTMLElement).closest('schmancy-input, schmancy-icon-button, button, a')\n\t\t\t\t}),\n\t\t\t\ttap(e => {\n\t\t\t\t\te.preventDefault()\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t}),\n\t\t\t)\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(e => {\n\t\t\t\t\t\tconst rect = container.getBoundingClientRect()\n\t\t\t\t\t\tconst isBottom = this._currentCorner.includes('bottom')\n\t\t\t\t\t\tconst wasOpen = this.open\n\t\t\t\t\t\tdidDrag = false\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstartX: e.clientX,\n\t\t\t\t\t\t\tstartY: e.clientY,\n\t\t\t\t\t\t\toffsetX: e.clientX - rect.left,\n\t\t\t\t\t\t\toffsetY: e.clientY - rect.top,\n\t\t\t\t\t\t\trect,\n\t\t\t\t\t\t\tvw: window.innerWidth,\n\t\t\t\t\t\t\tvh: window.innerHeight,\n\t\t\t\t\t\t\tisBottom,\n\t\t\t\t\t\t\twasOpen,\n\t\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t\tswitchMap(({ startX, startY, offsetX, offsetY, rect, vw, vh, isBottom, wasOpen, pointerId }) => {\n\t\t\t\t\t\tconst move$ = fromEvent<PointerEvent>(window, 'pointermove').pipe(\n\t\t\t\t\t\t\tfilter(e => e.pointerId === pointerId),\n\t\t\t\t\t\t\tauditTime(0, animationFrameScheduler),\n\t\t\t\t\t\t\tmap(e => ({ clientX: e.clientX, clientY: e.clientY })),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst end$ = fromEvent<PointerEvent>(window, 'pointerup').pipe(\n\t\t\t\t\t\t\tfilter(e => e.pointerId === pointerId),\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\treturn move$.pipe(\n\t\t\t\t\t\t\ttap(({ clientX, clientY }) => {\n\t\t\t\t\t\t\t\tconst dx = clientX - startX\n\t\t\t\t\t\t\t\tconst dy = clientY - startY\n\t\t\t\t\t\t\t\tif (Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD && !didDrag) {\n\t\t\t\t\t\t\t\t\tdidDrag = true\n\t\t\t\t\t\t\t\t\tthis._applyDragVisuals(true)\n\t\t\t\t\t\t\t\t\t// Collapse on first confirmed drag move\n\t\t\t\t\t\t\t\t\tif (wasOpen) {\n\t\t\t\t\t\t\t\t\t\tthis.open = false\n\t\t\t\t\t\t\t\t\t\tcontainer.style.clipPath = this.closedClipPath\n\t\t\t\t\t\t\t\t\t\tcontainer.style.overflow = 'hidden'\n\t\t\t\t\t\t\t\t\t\tconst body = this._bodyRef.value\n\t\t\t\t\t\t\t\t\t\tif (body) {\n\t\t\t\t\t\t\t\t\t\t\tbody.inert = true\n\t\t\t\t\t\t\t\t\t\t\tbody.style.visibility = 'hidden'\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (!didDrag) return\n\n\t\t\t\t\t\t\t\tconst left = Math.max(0, Math.min(clientX - offsetX, vw - rect.width))\n\t\t\t\t\t\t\t\tconst minTop = isBottom ? HEAD_HEIGHT - rect.height : 0\n\t\t\t\t\t\t\t\tconst maxTop = isBottom ? vh - rect.height : vh - HEAD_HEIGHT\n\t\t\t\t\t\t\t\tconst top = Math.max(minTop, Math.min(clientY - offsetY, maxTop))\n\n\t\t\t\t\t\t\t\tthis._position = {\n\t\t\t\t\t\t\t\t\tx: this._currentCorner.includes('right') ? vw - left - rect.width : left,\n\t\t\t\t\t\t\t\t\ty: isBottom ? vh - top - rect.height : top,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis._applyContainerPosition()\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\ttakeUntil(end$),\n\t\t\t\t\t\t\tfinalize(() => {\n\t\t\t\t\t\t\t\tif (didDrag) {\n\t\t\t\t\t\t\t\t\tthis._reorientToNearestCorner()\n\t\t\t\t\t\t\t\t\tthis._applyDragVisuals(false)\n\t\t\t\t\t\t\t\t\tdidDrag = false\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tdidDrag = false\n\t\t\t\t\t\t\t\t\tthis.toggle()\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.subscribe()\n\n\t\t\treturn () => sub.unsubscribe()\n\t\t})\n\t}\n\n\t// ============================================\n\t// LIFECYCLE\n\t// ============================================\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\n\t\t// Pipeline 1: DOM setup + manager registration + drag + z-index sync\n\t\tfrom(this.updateComplete).pipe(\n\t\t\ttake(1),\n\t\t\ttap(() => {\n\t\t\t\tthis._currentCorner = this.corner\n\t\t\t\tthis._loadPosition()\n\t\t\t\tthis._applyContainerPosition()\n\t\t\t\tthis._initDOMState()\n\t\t\t\t// Register with window manager\n\t\t\t\tconst container = this._containerRef.value\n\t\t\t\tif (container) {\n\t\t\t\t\tconst rect = container.getBoundingClientRect()\n\t\t\t\t\tconst bounds: WindowBounds = { left: rect.left, top: rect.top, width: rect.width, height: rect.height }\n\t\t\t\t\twindowManager.register(this.id, bounds, this.freePosition ? 'free' : this._currentCorner)\n\t\t\t\t}\n\t\t\t}),\n\t\t\tswitchMap(() => merge(\n\t\t\t\tthis._drag$(),\n\t\t\t\twindowManager.selectWindow(this.id).pipe(\n\t\t\t\t\ttap(record => {\n\t\t\t\t\t\tif (!record) return\n\t\t\t\t\t\tconst container = this._containerRef.value\n\t\t\t\t\t\tif (container) container.style.zIndex = String(record.zIndex)\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\twindowManager.selectFocused().pipe(\n\t\t\t\t\ttap(focusedId => {\n\t\t\t\t\t\tthis._focused = focusedId === this.id\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\n\n\t\t// Pipeline 3: Environment -- one subscription\n\t\tmerge(\n\t\t\tfromEvent(window, 'resize').pipe(\n\t\t\t\tauditTime(0, animationFrameScheduler),\n\t\t\t\ttap(() => this._validateBounds()),\n\t\t\t),\n\t\t\ttheme.bottomOffset$.pipe(\n\t\t\t\ttap(() => this._applyContainerPosition()),\n\t\t\t),\n\t\t).pipe(takeUntil(this.disconnecting)).subscribe()\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\twindowManager.unregister(this.id)\n\t}\n\n\tprivate _initDOMState() {\n\t\tconst container = this._containerRef.value\n\t\tconst body = this._bodyRef.value\n\t\tif (!container) return\n\n\t\tthis._applyContainerPosition()\n\n\t\tif (this.open) {\n\t\t\tthis._hasOpened = true\n\t\t\tcontainer.style.overflow = ''\n\t\t\tif (body) {\n\t\t\t\tbody.inert = false\n\t\t\t\tbody.style.visibility = 'visible'\n\t\t\t}\n\t\t} else {\n\t\t\tcontainer.style.clipPath = this.closedClipPath\n\t\t\tcontainer.style.overflow = 'hidden'\n\t\t\tif (body) {\n\t\t\t\tbody.inert = true\n\t\t\t\tbody.style.visibility = 'hidden'\n\t\t\t}\n\t\t}\n\t}\n\n\t// ============================================\n\t// ANIMATION\n\t// ============================================\n\n\tprivate _animateOpen() {\n\t\tconst container = this._containerRef.value\n\t\tconst body = this._bodyRef.value\n\t\tif (!container) return\n\n\t\tthis._hasOpened = true\n\t\tthis.open = true\n\n\t\t// Overlap avoidance\n\t\tconst rect = container.getBoundingClientRect()\n\t\tconst projectedBounds: WindowBounds = {\n\t\t\tleft: rect.left,\n\t\t\ttop: this.isBottomCorner ? rect.top - 400 : rect.top,\n\t\t\twidth: rect.width,\n\t\t\theight: 400 + HEAD_HEIGHT,\n\t\t}\n\t\tconst overlaps = windowManager.findOverlaps(projectedBounds, this.id)\n\t\tif (overlaps.length > 0) {\n\t\t\tconst resolved = resolveOverlap(projectedBounds, overlaps, { width: window.innerWidth, height: window.innerHeight })\n\t\t\tif (Math.abs(resolved.left - projectedBounds.left) > 10 || Math.abs(resolved.top - projectedBounds.top) > 10) {\n\t\t\t\tconst isRight = this._currentCorner.includes('right')\n\t\t\t\tconst isBottom = this._currentCorner.includes('bottom')\n\t\t\t\tthis._position = {\n\t\t\t\t\tx: isRight ? window.innerWidth - resolved.left - resolved.width : resolved.left,\n\t\t\t\t\ty: isBottom ? window.innerHeight - resolved.top - resolved.height : resolved.top,\n\t\t\t\t}\n\t\t\t\tthis._applyContainerPosition()\n\t\t\t}\n\t\t}\n\n\t\tif (body) {\n\t\t\tbody.style.visibility = 'visible'\n\t\t\tbody.inert = false\n\t\t}\n\n\t\tif (reducedMotion$.value) {\n\t\t\tcontainer.style.clipPath = ''\n\t\t\tcontainer.style.overflow = ''\n\t\t\tthis.dispatchScopedEvent('window-toggle', { state: 'expanded' })\n\t\t\treturn\n\t\t}\n\n\t\tthis._currentAnimation?.cancel()\n\t\tcontainer.style.overflow = 'hidden'\n\t\tcontainer.style.willChange = 'opacity'\n\t\tconst openKeyframes: Keyframe[] = [\n\t\t\t{ clipPath: this.closedClipPath, opacity: 0.95 },\n\t\t\t{ clipPath: this.openClipPath, opacity: 1 },\n\t\t]\n\t\tconst anim = container.animate(openKeyframes, {\n\t\t\tduration: SPRING_SNAPPY.duration,\n\t\t\teasing: SPRING_SNAPPY.easingFallback,\n\t\t\tfill: 'forwards',\n\t\t})\n\t\tthis._currentAnimation = anim\n\n\t\tfrom(anim.finished).pipe(\n\t\t\ttake(1),\n\t\t\ttap(() => {\n\t\t\t\tif (container.isConnected) {\n\t\t\t\t\tcontainer.style.clipPath = ''\n\t\t\t\t\tcontainer.style.overflow = ''\n\t\t\t\t\tcontainer.style.willChange = ''\n\t\t\t\t}\n\t\t\t}),\n\t\t\tcatchError(() => EMPTY),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\n\t\tthis.dispatchScopedEvent('window-toggle', { state: 'expanded' })\n\t}\n\n\tprivate _animateClose() {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\n\t\tif (reducedMotion$.value) {\n\t\t\tcontainer.style.clipPath = this.closedClipPath\n\t\t\tcontainer.style.overflow = 'hidden'\n\t\t\tthis.open = false\n\t\t\tconst body = this._bodyRef.value\n\t\t\tif (body) { body.inert = true; body.style.visibility = 'hidden' }\n\t\t\tthis.dispatchScopedEvent('window-toggle', { state: 'collapsed' })\n\t\t\treturn\n\t\t}\n\n\t\tthis._currentAnimation?.cancel()\n\t\tcontainer.style.overflow = 'hidden'\n\t\tcontainer.style.willChange = 'opacity'\n\t\tconst closeKeyframes: Keyframe[] = [\n\t\t\t{ clipPath: this.openClipPath, opacity: 1 },\n\t\t\t{ clipPath: this.closedClipPath, opacity: 0.95 },\n\t\t]\n\t\tconst anim = container.animate(closeKeyframes, {\n\t\t\tduration: Math.round(SPRING_SNAPPY.duration * 0.7),\n\t\t\teasing: 'cubic-bezier(0.4, 0, 0.8, 0.15)',\n\t\t\tfill: 'forwards',\n\t\t})\n\t\tthis._currentAnimation = anim\n\n\t\tfrom(anim.finished).pipe(\n\t\t\ttake(1),\n\t\t\ttap(() => {\n\t\t\t\tthis.open = false\n\t\t\t\tcontainer.style.willChange = ''\n\t\t\t\tconst body = this._bodyRef.value\n\t\t\t\tif (body) { body.inert = true; body.style.visibility = 'hidden' }\n\t\t\t}),\n\t\t\tcatchError(() => EMPTY),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\n\t\tthis.dispatchScopedEvent('window-toggle', { state: 'collapsed' })\n\t}\n\n\t// ============================================\n\t// VISUAL STATE HELPERS\n\t// ============================================\n\n\t/** Apply drag visuals directly on DOM refs — avoids full Lit re-render for cursor + opacity */\n\tprivate _applyDragVisuals(dragging: boolean) {\n\t\tconst head = this._headRef.value\n\t\tconst container = this._containerRef.value\n\t\tif (head) {\n\t\t\thead.classList.toggle('cursor-grabbing', dragging)\n\t\t\thead.classList.toggle('cursor-move', !dragging)\n\t\t}\n\t\tif (container) {\n\t\t\tcontainer.style.opacity = dragging ? '0.95' : ''\n\t\t}\n\t}\n\n\tprivate _handleFocus = () => windowManager.focus(this.id)\n\n\tprivate _handleHeadKeydown = (e: KeyboardEvent) => {\n\t\tif (e.key === 'Enter' || e.key === ' ') {\n\t\t\te.preventDefault()\n\t\t\tthis.toggle()\n\t\t\treturn\n\t\t}\n\t\tif (e.key === 'ArrowUp' || e.key === 'ArrowDown' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n\t\t\te.preventDefault()\n\t\t\tconst step = e.shiftKey ? 20 : 5\n\t\t\tconst dx = e.key === 'ArrowRight' ? step : e.key === 'ArrowLeft' ? -step : 0\n\t\t\tconst dy = e.key === 'ArrowDown' ? step : e.key === 'ArrowUp' ? -step : 0\n\t\t\tthis._position = { x: this._position.x + dx, y: this._position.y + dy }\n\t\t\tthis._applyContainerPosition()\n\t\t\tthis._savePosition()\n\t\t}\n\t}\n\n\t// ============================================\n\t// PUBLIC API\n\t// ============================================\n\n\ttoggle() {\n\t\tif (this.open) this._animateClose()\n\t\telse this._animateOpen()\n\t}\n\n\texpand() {\n\t\tif (this.open) return\n\t\tthis._animateOpen()\n\t}\n\n\tclose() {\n\t\tif (!this.open) return\n\t\tthis._animateClose()\n\t}\n\n\t// ============================================\n\t// RENDER\n\t// ============================================\n\n\tprotected render(): unknown {\n\t\tconst isBottom = this._currentCorner.startsWith('bottom')\n\n\t\tconst containerClasses = classMap({\n\t\t\tfixed: true,\n\t\t\tflex: true,\n\t\t\t'flex-col': isBottom,\n\t\t\t'flex-col-reverse': !isBottom,\n\t\t\t'z-1000': true,\n\t\t\t'ring-1': !this._focused,\n\t\t\t'ring-2': this._focused,\n\t\t\t'ring-primary-default/30': this._focused,\n\t\t\t'ring-primary-default/15': this.open && !this._focused,\n\t\t\t'rounded-2xl': this.open,\n\t\t\t'ring-outline-variant/40': !this.open && !this._focused,\n\t\t\t'rounded-[22px]': !this.open,\n\t\t\t'overflow-hidden': true,\n\t\t})\n\n\t\tconst containerStyles = styleMap({\n\t\t\twidth: this.panelWidth,\n\t\t\t'max-height': 'calc(100vh - 32px)',\n\t\t\t'pointer-events': 'none',\n\t\t})\n\n\t\tconst bodyStyles = styleMap({\n\t\t\t'pointer-events': this.open ? 'auto' : 'none',\n\t\t})\n\n\t\tconst headClasses = classMap({\n\t\t\t'h-full': true,\n\t\t\t'px-3': true,\n\t\t\tflex: true,\n\t\t\t'items-center': true,\n\t\t\t'gap-2': true,\n\t\t\t'select-none': true,\n\t\t\t'cursor-move': true,\n\t\t})\n\n\t\treturn html`\n\t\t\t<schmancy-surface\n\t\t\t\t${ref(this._containerRef)}\n\t\t\t\ttype=\"glass\"\n\t\t\t\televation=\"${this.elevation}\"\n\t\t\t\tclass=${containerClasses}\n\t\t\t\tstyle=${containerStyles}\n\t\t\t\taria-expanded=${this.open}\n\t\t\t\t@pointerdown=${this._handleFocus}\n\t\t\t>\n\t\t\t\t<!-- Details section (visually above summary for bottom corners) -->\n\t\t\t\t<section\n\t\t\t\t\t${ref(this._bodyRef)}\n\t\t\t\t\tclass=\"flex-1 min-h-0 overflow-hidden flex flex-col\"\n\t\t\t\t\tstyle=${bodyStyles}\n\t\t\t\t\trole=\"region\"\n\t\t\t\t\taria-label=\"Expandable content\"\n\t\t\t\t>\n\t\t\t\t\t${this._hasOpened ? html`<slot name=\"details\"></slot>` : nothing}\n\t\t\t\t</section>\n\n\t\t\t\t<!-- Summary section -- always interactive, always visible -->\n\t\t\t\t<section\n\t\t\t\t\tclass=\"shrink-0 bg-surface-lowest\"\n\t\t\t\t\tstyle=${styleMap({ 'pointer-events': 'auto', height: `${HEAD_HEIGHT}px` })}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\t${ref(this._headRef)}\n\t\t\t\t\t\t${cursorGlow({ radius: 200, intensity: 0.10 })}\n\t\t\t\t\t\tclass=${headClasses}\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\ttabindex=\"0\"\n\t\t\t\t\t\ttitle=\"Drag to move, click to expand\"\n\t\t\t\t\t\taria-label=\"${this.open ? 'Collapse window' : 'Expand window'}\"\n\t\t\t\t\t\t@keydown=${this._handleHeadKeydown}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"flex-1 min-w-0\">\n\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\twidth=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"\n\t\t\t\t\t\t\tclass=\"shrink-0 text-surface-on/40 transition-transform duration-200 ${this.open ? 'rotate-180' : ''}\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<path d=\"M6 9L12 15L18 9\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t</schmancy-surface>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-window': SchmancyWindow\n\t}\n}\n"],"mappings":"8hBAmBA,IAAM,EAAiB,mBACjB,EAAwB,kBAmL9B,SAAS,EAAa,EAAiB,EAAA,CACtC,MAAA,EAAS,EAAE,MAAQ,EAAE,KAAO,EAAE,OAAS,EAAE,KAAO,EAAE,OAAS,EAAE,MAAQ,EAAE,KAAO,EAAE,IAAM,EAAE,QAAU,EAAE,IAAM,EAAE,QAAU,EAAE,KAGzH,IAAA,EAAa,EArLb,MAAM,CAAA,CAWL,aAAA,CAAA,KAAA,QAR2B,IAAI,EAAA,gBAAqC,CACnE,QAAS,IAAI,IACb,UAAW,KACX,WAAY,EAAA,CAAA,CAAA,CAAA,KAAA,OAGK,KAAK,QAAQ,cAAA,CAI/B,OAAA,aAAO,CAIN,MAHK,CACJ,EAAqB,WAAW,IAAI,EAE9B,EAAqB,SAK7B,IAAA,SAAI,CACH,OAAO,KAAK,QAAQ,MAAM,QAG3B,IAAA,WAAI,CACH,OAAO,KAAK,QAAQ,MAAM,UAK3B,SAAS,EAAY,EAA6B,EAAA,CACjD,IAAM,EAAQ,KAAK,QAAQ,MAC3B,GAAI,EAAM,QAAQ,IAAI,EAAA,CAAK,OAG3B,IAAM,EAAuB,CAC5B,GAAA,EACA,OAAQ,EACR,YAAa,SACb,OALc,EAAA,EAAa,aAAa,EAAA,CAMxC,KAAA,CAAM,EACN,WAAA,EAAA,CAGK,EAAU,IAAI,IAAI,EAAM,QAAA,CAC9B,EAAQ,IAAI,EAAI,EAAA,CAChB,IAAM,EAAa,EAAA,EAAa,eAAA,CAEhC,KAAK,QAAQ,KAAK,CAAA,GAAK,EAAO,QAAA,EAAS,WAAA,EAAA,CAAA,CAGxC,WAAW,EAAA,CACV,IAAM,EAAQ,KAAK,QAAQ,MAC3B,GAAA,CAAK,EAAM,QAAQ,IAAI,EAAA,CAAK,OAE5B,EAAA,EAAa,UAAU,EAAA,CACvB,IAAM,EAAU,IAAI,IAAI,EAAM,QAAA,CAC9B,EAAQ,OAAO,EAAA,CACf,IAAM,EAAa,EAAA,EAAa,eAAA,CAC1B,EAAY,EAAM,YAAc,EAAK,KAAO,EAAM,UAExD,KAAK,QAAQ,KAAK,CAAA,GAAK,EAAO,QAAA,EAAS,WAAA,EAAY,UAAA,EAAA,CAAA,CAKpD,aAAa,EAAY,EAAA,CACxB,KAAK,cAAc,EAAI,CAAE,OAAA,EAAA,CAAA,CAG1B,kBAAkB,EAAY,EAAA,CAC7B,KAAK,cAAc,EAAI,CAAE,YAAA,EAAA,CAAA,CAG1B,WAAW,EAAY,EAAA,CACtB,KAAK,cAAc,EAAI,CAAE,KAAA,EAAA,CAAA,CAG1B,MAAM,EAAA,CACL,IAAM,EAAQ,KAAK,QAAQ,MAE3B,GADA,CAAK,EAAM,QAAQ,IAAI,EAAA,EACnB,EAAM,YAAc,EAAI,OAE5B,IAAM,EAAS,EAAA,EAAa,aAAa,EAAA,CACnC,EAAU,IAAI,IAAI,EAAM,QAAA,CACxB,EAAS,EAAQ,IAAI,EAAA,CACvB,GACH,EAAQ,IAAI,EAAI,CAAA,GAAK,EAAQ,OAAA,EAAA,CAAA,CAE9B,IAAM,EAAa,EAAA,EAAa,eAAA,CAEhC,KAAK,QAAQ,KAAK,CAAA,GAAK,EAAO,QAAA,EAAS,WAAA,EAAY,UAAW,EAAA,CAAA,CAK/D,aAAa,EAAsB,EAAA,CAClC,IAAM,EAAyB,EAAA,CAC/B,IAAK,GAAA,CAAO,EAAI,KAAW,KAAK,QAAQ,MAAM,QACzC,IAAO,GACP,EAAa,EAAQ,EAAO,OAAA,EAC/B,EAAO,KAAK,EAAA,CAGd,OAAO,EAGR,aAAa,EAAA,CACZ,IAAM,EAAyB,EAAA,CAC/B,IAAK,GAAA,CAAO,EAAS,KAAW,KAAK,QAAQ,MAAM,QAC9C,IAAY,GAAI,EAAO,KAAK,EAAA,CAEjC,OAAO,EAKR,aAAa,EAAA,CACZ,OAAO,KAAK,QAAQ,MAAA,EAAA,EAAA,KACf,GAAS,EAAM,QAAQ,IAAI,EAAA,CAAA,EAAI,EAAA,EAAA,uBAAA,CAAA,CAKrC,eAAA,CACC,OAAO,KAAK,QAAQ,MAAA,EAAA,EAAA,KACf,GAAS,EAAM,UAAA,EAAU,EAAA,EAAA,uBAAA,CAAA,CAO/B,aAAa,EAAA,CACZ,GAAA,CAEC,IAAM,EAAM,aAAa,QAAQ,EAAiB,EAAA,EAAO,aAAa,QAAQ,EAAwB,EAAA,CACtG,OAAK,EACE,KAAK,MAAM,EAAA,CADD,UAAA,CAGjB,OAAO,MAIT,aAAa,EAAY,EAAA,CACxB,GAAA,CACC,aAAa,QAAQ,EAAiB,EAAI,KAAK,UAAU,EAAA,CAAA,MAAA,GAM3D,cAAc,EAAA,CACb,GAAA,CACC,aAAa,WAAW,EAAiB,EAAA,CACzC,aAAa,WAAW,EAAwB,EAAA,MAAA,GAQlD,cAAsB,EAAY,EAAA,CACjC,IAAM,EAAQ,KAAK,QAAQ,MACrB,EAAS,EAAM,QAAQ,IAAI,EAAA,CACjC,GAAA,CAAK,EAAQ,OAEb,IAAM,EAAU,IAAI,IAAI,EAAM,QAAA,CAC9B,EAAQ,IAAI,EAAI,CAAA,GAAK,EAAA,GAAW,EAAA,CAAA,CAChC,KAAK,QAAQ,KAAK,CAAA,GAAK,EAAO,QAAA,EAAA,CAAA,GASkB,aAAA,CC/KlD,SAAgB,EACf,EACA,EACA,EAAA,CAEA,IAAI,EAAS,CAAA,GAAK,EAAA,CAElB,IAAK,IAAI,EAAU,EAAG,EAlBM,IAmBR,EAAS,KAAK,GAAA,CAAK,MAhBX,GAgBwB,EAhBP,EAgBe,EAAE,OAAA,EAfrD,EAAE,MAAQ,EAAE,KAAO,EAAE,OAAS,EAAE,KAAO,EAAE,OAAS,EAAE,MAAQ,EAAE,KAAO,EAAE,IAAM,EAAE,QAAU,EAAE,IAAM,EAAE,QAAU,EAAE,SAD5F,EAAiB,GAAA,CAeS,IAIrD,EAAS,CAAA,GACL,EACH,KAAM,EAAO,KA1BI,GA2BjB,IAAK,EAAO,IA3BK,GAAA,CA+BnB,OAMD,SACC,EACA,EAAA,CAEA,MAAO,CACN,MAAO,EAAO,MACd,OAAQ,EAAO,OACf,KAAM,KAAK,IAAI,EAAG,KAAK,IAAI,EAAO,KAAM,EAAS,MAAQ,EAAO,MAAA,CAAA,CAChE,IAAK,KAAK,IAAI,EAAG,KAAK,IAAI,EAAO,IAAK,EAAS,OAAS,EAAO,OAAA,CAAA,CAAA,EAdzC,EAAQ,EAAA,CCfhC,IAAM,EAAc,GASL,EAAA,cAA6B,EAAA,EAAY,EAAA,GAAG;;;;;;;;;uDAUjB,UAAA,KAAA,QAAA,CAMsB,EAAA,KAAA,OAEd,eAAA,KAAA,UAAA,CAER,EAAA,KAAA,aAAA,CAEG,EAAA,KAAA,YAEgC,SAAA,KAAA,SAErC,IAAA,KAAA,UAEC,IAAA,KAAA,KAAA,CAGW,EAAA,KAAA,WAAA,CAKrB,EAAA,KAAA,SAAA,CAEF,EAAA,KAAA,UAGE,CAAE,EAAG,GAAI,EAAG,GAAA,CAAA,KAAA,eACI,eAAA,KAAA,eAGb,GAAA,KAAA,eAAA,EAAA,EAAA,YAAA,CAAA,KAAA,UAAA,EAAA,EAAA,YAAA,CAAA,KAAA,UAAA,EAAA,EAAA,YAAA,CAAA,KAAA,iBAofJ,EAAc,MAAM,KAAK,GAAA,CAAA,KAAA,mBAExB,GAAA,CAC7B,GAAI,EAAE,MAAQ,SAAW,EAAE,MAAQ,IAGlC,OAFA,EAAE,gBAAA,CAAA,KACF,KAAK,QAAA,CAGN,GAAI,EAAE,MAAQ,WAAa,EAAE,MAAQ,aAAe,EAAE,MAAQ,aAAe,EAAE,MAAQ,aAAc,CACpG,EAAE,gBAAA,CACF,IAAM,EAAO,EAAE,SAAW,GAAK,EACzB,EAAK,EAAE,MAAQ,aAAe,EAAO,EAAE,MAAQ,YAAR,CAAuB,EAAO,EACrE,EAAK,EAAE,MAAQ,YAAc,EAAO,EAAE,MAAQ,UAAR,CAAqB,EAAO,EACxE,KAAK,UAAY,CAAE,EAAG,KAAK,UAAU,EAAI,EAAI,EAAG,KAAK,UAAU,EAAI,EAAA,CACnE,KAAK,yBAAA,CACL,KAAK,eAAA,GAxfP,IAAA,YAAY,CACX,OAAO,KAAK,eAAiB,iCAG9B,IAAA,gBAAY,CACX,OAAO,KAAK,eAAe,WAAW,SAAA,CAGvC,IAAA,gBAAY,CACX,OAAO,KAAK,eACT,kDACA,kDAGJ,IAAA,cAAY,CACX,MAAO,oCAGR,IAAA,WAAY,CACX,OAAI,KAAK,KAAa,IACf,KAAK,QAAU,IAAM,IAO7B,yBAAA,CACC,IAAM,EAAY,KAAK,cAAc,MACrC,GAAA,CAAK,EAAW,OAEZ,KAAK,iBAAmB,KAAK,iBAChC,EAAU,MAAM,eAAe,OAAA,CAC/B,EAAU,MAAM,eAAe,QAAA,CAC/B,EAAU,MAAM,eAAe,MAAA,CAC/B,EAAU,MAAM,eAAe,SAAA,CAC/B,KAAK,eAAiB,KAAK,gBAE5B,GAAA,CAAM,EAAE,EAAA,EAAG,GAAM,KAAK,UAClB,KAAK,eAAe,SAAS,QAAA,CAChC,EAAU,MAAM,MAAQ,GAAG,EAAA,IAE3B,EAAU,MAAM,KAAO,GAAG,EAAA,IAEvB,KAAK,eAAe,SAAS,SAAA,CAChC,EAAU,MAAM,OAAS,GAAG,EAAI,EAAA,EAAM,aAAA,IAEtC,EAAU,MAAM,IAAM,GAAG,EAAA,IAAA,OAAA,KAAA,cAIa,IAAI,IAAY,CAAC,WAAY,YAAa,cAAe,eAAA,CAAA,CAEjG,eAAA,CACC,IAAM,EAAQ,EAAc,aAAa,KAAK,GAAA,CAC1C,IACH,KAAK,UAAY,CAAE,EAAG,EAAM,EAAG,EAAG,EAAM,EAAA,CACxC,EAAmB,cAAc,IAAI,EAAM,OAAA,GAC1C,KAAK,eAAiB,EAAM,SAK/B,eAAA,CACC,EAAc,aAAa,KAAK,GAAI,CAAA,GAAK,KAAK,UAAW,OAAQ,KAAK,eAAA,CAAA,CAGvE,iBAAA,CACC,IAAM,EAAY,KAAK,cAAc,MACrC,GAAA,CAAK,EAAW,OAChB,IAAM,EAAO,EAAU,uBAAA,CACvB,GAAI,EAAK,QAAU,EAAG,OACtB,IAAM,EAAK,OAAO,WACZ,EAAK,OAAO,YACZ,EAAU,KAAK,eAAe,SAAS,QAAA,CACvC,EAAW,KAAK,eAAe,SAAS,SAAA,CACxC,EAAa,EAAU,EAAK,KAAK,UAAU,EAAI,EAAK,MAAQ,KAAK,UAAU,EAC3E,EAAY,EAAW,EAAK,KAAK,UAAU,EAAI,EAAK,OAAS,KAAK,UAAU,EAC5E,EAAU,KAAK,IAAI,EAAG,KAAK,IAAI,EAAY,EAAK,EAAK,MAAA,CAAA,CACrD,EAAS,KAAK,IAAI,EAAG,KAAK,IAAI,EAAW,EAAK,EAAK,OAAA,CAAA,CACzD,KAAK,UAAY,CAChB,EAAG,EAAU,EAAK,EAAU,EAAK,MAAQ,EACzC,EAAG,EAAW,EAAK,EAAS,EAAK,OAAS,EAAA,CAE3C,KAAK,yBAAA,CAON,yBAAiC,EAAA,CAAgB,EAAA,CAEhD,GAAI,KAAK,aAAc,CACtB,KAAK,eAAA,CACL,IAAM,EAAO,KAAK,cAAc,OAAO,uBAAA,CACnC,GACH,EAAc,aAAa,KAAK,GAAI,CAAE,KAAM,EAAK,KAAM,IAAK,EAAK,IAAK,MAAO,EAAK,MAAO,OAAQ,EAAK,OAAA,CAAA,CAEvG,OAGD,IAAM,EAAY,KAAK,cAAc,MACrC,GAAA,CAAK,EAAW,OAGhB,IAAM,EAAO,EAAU,uBAAA,CAGjB,EAAkB,KAAK,eAAe,SAAS,SAAA,CAC/C,EAAc,EAAK,KAAO,EAAK,MAAQ,EACvC,EAAc,EACjB,EAAK,OAAS,GACd,EAAK,IAAM,GACR,EAAO,EAAc,OAAO,WAAa,EAAI,QAAU,OAEvD,EAAwB,GADjB,EAAc,OAAO,YAAc,EAAI,SAAW,MAAA,GACtB,IAWzC,GARA,KAAK,eAAiB,EACtB,KAAK,UAAY,CAAE,EAAG,GAAI,EAAG,GAAA,CAC7B,KAAK,yBAAA,CAEA,KAAK,OACT,EAAU,MAAM,SAAW,KAAK,gBAG7B,GAAiB,EAAA,EAAe,MAAO,CAC1C,KAAK,eAAA,CACL,IAAM,EAAW,EAAU,uBAAA,CAC3B,EAAc,aAAa,KAAK,GAAI,CAAE,KAAM,EAAS,KAAM,IAAK,EAAS,IAAK,MAAO,EAAS,MAAO,OAAQ,EAAS,OAAA,CAAA,CACtH,OAID,IAAM,EAAU,EAAU,uBAAA,CACpB,EAAK,EAAK,KAAO,EAAQ,KACzB,EAAK,EAAK,IAAM,EAAQ,IAC9B,EAAU,MAAM,UAAY,GAAG,EAAA,KAAQ,EAAA,IAGvC,IAAM,EAA4B,CAAC,CAAE,UAAW,GAAG,EAAA,KAAQ,EAAA,IAAA,CAAU,CAAE,UAAW,UAAA,CAAA,EASlF,EAAA,EAAA,MARa,EAAU,QACtB,EACA,CACC,SAAU,EAAA,EAAc,SACxB,OAAQ,EAAA,EAAc,eACtB,KAAM,WAAA,CAAA,CAGE,SAAA,CAAU,MAAA,EAAA,EAAA,MACd,EAAA,EAAE,EAAA,EAAA,SAAA,CAEF,EAAU,cAAa,EAAU,MAAM,UAAY,IAEvD,IAAM,EAAY,EAAU,uBAAA,CAC5B,EAAc,aAAa,KAAK,GAAI,CAAE,KAAM,EAAU,KAAM,IAAK,EAAU,IAAK,MAAO,EAAU,MAAO,OAAQ,EAAU,OAAA,CAAA,EAAA,EACzH,EAAA,EAAA,gBACe,EAAA,MAAA,EAAM,EAAA,EAAA,WACb,KAAK,cAAA,CAAA,CACd,WAAA,CAEF,KAAK,eAAA,CAON,QAAA,CACC,OAAO,IAAI,EAAA,eAAA,CACV,IAAM,EAAO,KAAK,SAAS,MACrB,EAAY,KAAK,cAAc,MACrC,GAAA,CAAK,GAAA,CAAS,EAAW,OAEzB,IAAI,EAAA,CAAU,EAER,GAAA,EAAA,EAAA,WAA8B,EAAM,cAAA,CAAe,MAAA,EAAA,EAAA,QACjD,GAAK,EAAE,SAAW,EAAX,EAAa,EAAA,EAAA,QACpB,GAAA,CACN,IAAM,EAAO,EAAE,OAAuB,SAAS,aAAA,CAC/C,MAAA,CAAQ,CAAC,QAAS,WAAY,SAAU,SAAA,CAAU,SAAS,EAAA,EAAA,CACrD,EAAE,OAAuB,QAAQ,kDAAA,EAAA,EACtC,EAAA,EAAA,KACE,GAAA,CACH,EAAE,gBAAA,CACF,EAAE,iBAAA,EAAA,CAAA,CAGF,MAAA,EAAA,EAAA,KACI,GAAA,CACH,IAAM,EAAO,EAAU,uBAAA,CACjB,EAAW,KAAK,eAAe,SAAS,SAAA,CACxC,EAAU,KAAK,KAErB,MADA,GAAA,CAAU,EACH,CACN,OAAQ,EAAE,QACV,OAAQ,EAAE,QACV,QAAS,EAAE,QAAU,EAAK,KAC1B,QAAS,EAAE,QAAU,EAAK,IAC1B,KAAA,EACA,GAAI,OAAO,WACX,GAAI,OAAO,YACX,SAAA,EACA,QAAA,EACA,UAAW,EAAE,UAAA,EAAA,EAEb,EAAA,EAAA,YAAA,CACW,OAAA,EAAQ,OAAA,EAAQ,QAAA,EAAS,QAAA,EAAS,KAAA,EAAM,GAAA,EAAI,GAAA,EAAI,SAAA,EAAU,QAAA,EAAS,UAAA,KAAA,CAC/E,IAAM,GAAA,EAAA,EAAA,WAAgC,OAAQ,cAAA,CAAe,MAAA,EAAA,EAAA,QACrD,GAAK,EAAE,YAAc,EAAA,EAAU,EAAA,EAAA,WAC5B,EAAG,EAAA,wBAAA,EAAwB,EAAA,EAAA,KACjC,IAAA,CAAQ,QAAS,EAAE,QAAS,QAAS,EAAE,QAAA,EAAA,CAAA,CAEtC,GAAA,EAAA,EAAA,WAA+B,OAAQ,YAAA,CAAa,MAAA,EAAA,EAAA,QAClD,GAAK,EAAE,YAAc,EAAA,CAAA,CAG7B,OAAO,EAAM,MAAA,EAAA,EAAA,MAAA,CACL,QAAA,EAAS,QAAA,KAAA,CACf,IAAM,EAAK,EAAU,EACf,EAAK,EAAU,EACrB,GAAI,KAAK,KAAK,EAAK,EAAK,EAAK,EAAA,CA9Rd,GAAA,CA8RuC,IACrD,EAAA,CAAU,EACV,KAAK,kBAAA,CAAkB,EAAA,CAEnB,GAAS,CACZ,KAAK,KAAA,CAAO,EACZ,EAAU,MAAM,SAAW,KAAK,eAChC,EAAU,MAAM,SAAW,SAC3B,IAAM,EAAO,KAAK,SAAS,MACvB,IACH,EAAK,MAAA,CAAQ,EACb,EAAK,MAAM,WAAa,UAI3B,GAAA,CAAK,EAAS,OAEd,IAAM,EAAO,KAAK,IAAI,EAAG,KAAK,IAAI,EAAU,EAAS,EAAK,EAAK,MAAA,CAAA,CACzD,EAAS,EAAW,EAAc,EAAK,OAAS,EAChD,EAAS,EAAW,EAAK,EAAK,OAAS,EAAK,EAC5C,EAAM,KAAK,IAAI,EAAQ,KAAK,IAAI,EAAU,EAAS,EAAA,CAAA,CAEzD,KAAK,UAAY,CAChB,EAAG,KAAK,eAAe,SAAS,QAAA,CAAW,EAAK,EAAO,EAAK,MAAQ,EACpE,EAAG,EAAW,EAAK,EAAM,EAAK,OAAS,EAAA,CAExC,KAAK,yBAAA,EAAA,EACJ,EAAA,EAAA,WACQ,EAAA,EAAK,EAAA,EAAA,cAAA,CAEV,GACH,KAAK,0BAAA,CACL,KAAK,kBAAA,CAAkB,EAAA,CACvB,EAAA,CAAU,IAEV,EAAA,CAAU,EACV,KAAK,QAAA,GAAA,CAAA,EAAA,CAAA,CAMT,WAAA,CAEF,UAAa,EAAI,aAAA,EAAA,CAQnB,mBAAA,CACC,MAAM,mBAAA,EAGN,EAAA,EAAA,MAAK,KAAK,eAAA,CAAgB,MAAA,EAAA,EAAA,MACpB,EAAA,EAAE,EAAA,EAAA,SAAA,CAEN,KAAK,eAAiB,KAAK,OAC3B,KAAK,eAAA,CACL,KAAK,yBAAA,CACL,KAAK,eAAA,CAEL,IAAM,EAAY,KAAK,cAAc,MACrC,GAAI,EAAW,CACd,IAAM,EAAO,EAAU,uBAAA,CACjB,EAAuB,CAAE,KAAM,EAAK,KAAM,IAAK,EAAK,IAAK,MAAO,EAAK,MAAO,OAAQ,EAAK,OAAA,CAC/F,EAAc,SAAS,KAAK,GAAI,EAAQ,KAAK,aAAe,OAAS,KAAK,eAAA,GAAA,EAE1E,EAAA,EAAA,gBAAA,EAAA,EAAA,OAED,KAAK,QAAA,CACL,EAAc,aAAa,KAAK,GAAA,CAAI,MAAA,EAAA,EAAA,KAC/B,GAAA,CACH,GAAA,CAAK,EAAQ,OACb,IAAM,EAAY,KAAK,cAAc,MACjC,IAAW,EAAU,MAAM,OAAS,OAAO,EAAO,OAAA,GAAA,CAAA,CAGxD,EAAc,eAAA,CAAgB,MAAA,EAAA,EAAA,KACzB,GAAA,CACH,KAAK,SAAW,IAAc,KAAK,IAAA,CAAA,CAAA,CAAA,EAGpC,EAAA,EAAA,WACQ,KAAK,cAAA,CAAA,CACd,WAAA,EAIF,EAAA,EAAA,QAAA,EAAA,EAAA,WACW,OAAQ,SAAA,CAAU,MAAA,EAAA,EAAA,WACjB,EAAG,EAAA,wBAAA,EAAwB,EAAA,EAAA,SAC3B,KAAK,iBAAA,CAAA,CAAA,CAEhB,EAAA,EAAM,cAAc,MAAA,EAAA,EAAA,SACT,KAAK,yBAAA,CAAA,CAAA,CAAA,CAEf,MAAA,EAAA,EAAA,WAAe,KAAK,cAAA,CAAA,CAAgB,WAAA,CAGvC,sBAAA,CACC,MAAM,sBAAA,CACN,EAAc,WAAW,KAAK,GAAA,CAG/B,eAAA,CACC,IAAM,EAAY,KAAK,cAAc,MAC/B,EAAO,KAAK,SAAS,MACtB,IAEL,KAAK,yBAAA,CAED,KAAK,MACR,KAAK,WAAA,CAAa,EAClB,EAAU,MAAM,SAAW,GACvB,IACH,EAAK,MAAA,CAAQ,EACb,EAAK,MAAM,WAAa,aAGzB,EAAU,MAAM,SAAW,KAAK,eAChC,EAAU,MAAM,SAAW,SACvB,IACH,EAAK,MAAA,CAAQ,EACb,EAAK,MAAM,WAAa,YAS3B,cAAA,CACC,IAAM,EAAY,KAAK,cAAc,MAC/B,EAAO,KAAK,SAAS,MAC3B,GAAA,CAAK,EAAW,OAEhB,KAAK,WAAA,CAAa,EAClB,KAAK,KAAA,CAAO,EAGZ,IAAM,EAAO,EAAU,uBAAA,CACjB,EAAgC,CACrC,KAAM,EAAK,KACX,IAAK,KAAK,eAAiB,EAAK,IAAM,IAAM,EAAK,IACjD,MAAO,EAAK,MACZ,OAAQ,IAAA,CAEH,EAAW,EAAc,aAAa,EAAiB,KAAK,GAAA,CAClE,GAAI,EAAS,OAAS,EAAG,CACxB,IAAM,EAAW,EAAe,EAAiB,EAAU,CAAE,MAAO,OAAO,WAAY,OAAQ,OAAO,YAAA,CAAA,CACtG,GAAI,KAAK,IAAI,EAAS,KAAO,EAAgB,KAAA,CAAQ,IAAM,KAAK,IAAI,EAAS,IAAM,EAAgB,IAAA,CAAO,GAAI,CAC7G,IAAM,EAAU,KAAK,eAAe,SAAS,QAAA,CACvC,EAAW,KAAK,eAAe,SAAS,SAAA,CAC9C,KAAK,UAAY,CAChB,EAAG,EAAU,OAAO,WAAa,EAAS,KAAO,EAAS,MAAQ,EAAS,KAC3E,EAAG,EAAW,OAAO,YAAc,EAAS,IAAM,EAAS,OAAS,EAAS,IAAA,CAE9E,KAAK,yBAAA,EASP,GALI,IACH,EAAK,MAAM,WAAa,UACxB,EAAK,MAAA,CAAQ,GAGV,EAAA,EAAe,MAIlB,MAHA,GAAU,MAAM,SAAW,GAC3B,EAAU,MAAM,SAAW,GAAA,KAC3B,KAAK,oBAAoB,gBAAiB,CAAE,MAAO,WAAA,CAAA,CAIpD,KAAK,mBAAmB,QAAA,CACxB,EAAU,MAAM,SAAW,SAC3B,EAAU,MAAM,WAAa,UAC7B,IAAM,EAA4B,CACjC,CAAE,SAAU,KAAK,eAAgB,QAAS,IAAA,CAC1C,CAAE,SAAU,KAAK,aAAc,QAAS,EAAA,CAAA,CAEnC,EAAO,EAAU,QAAQ,EAAe,CAC7C,SAAU,EAAA,EAAc,SACxB,OAAQ,EAAA,EAAc,eACtB,KAAM,WAAA,CAAA,CAEP,KAAK,kBAAoB,GAEzB,EAAA,EAAA,MAAK,EAAK,SAAA,CAAU,MAAA,EAAA,EAAA,MACd,EAAA,EAAE,EAAA,EAAA,SAAA,CAEF,EAAU,cACb,EAAU,MAAM,SAAW,GAC3B,EAAU,MAAM,SAAW,GAC3B,EAAU,MAAM,WAAa,KAAA,EAE7B,EAAA,EAAA,gBACe,EAAA,MAAA,EAAM,EAAA,EAAA,WACb,KAAK,cAAA,CAAA,CACd,WAAA,CAEF,KAAK,oBAAoB,gBAAiB,CAAE,MAAO,WAAA,CAAA,CAGpD,eAAA,CACC,IAAM,EAAY,KAAK,cAAc,MACrC,GAAA,CAAK,EAAW,OAEhB,GAAI,EAAA,EAAe,MAAO,CACzB,EAAU,MAAM,SAAW,KAAK,eAChC,EAAU,MAAM,SAAW,SAC3B,KAAK,KAAA,CAAO,EACZ,IAAM,EAAO,KAAK,SAAS,MACvB,IAAQ,EAAK,MAAA,CAAQ,EAAM,EAAK,MAAM,WAAa,UACvD,KAAK,oBAAoB,gBAAiB,CAAE,MAAO,YAAA,CAAA,CACnD,OAGD,KAAK,mBAAmB,QAAA,CACxB,EAAU,MAAM,SAAW,SAC3B,EAAU,MAAM,WAAa,UAC7B,IAAM,EAA6B,CAClC,CAAE,SAAU,KAAK,aAAc,QAAS,EAAA,CACxC,CAAE,SAAU,KAAK,eAAgB,QAAS,IAAA,CAAA,CAErC,EAAO,EAAU,QAAQ,EAAgB,CAC9C,SAAU,KAAK,MAA+B,GAAzB,EAAA,EAAc,SAAA,CACnC,OAAQ,kCACR,KAAM,WAAA,CAAA,CAEP,KAAK,kBAAoB,GAEzB,EAAA,EAAA,MAAK,EAAK,SAAA,CAAU,MAAA,EAAA,EAAA,MACd,EAAA,EAAE,EAAA,EAAA,SAAA,CAEN,KAAK,KAAA,CAAO,EACZ,EAAU,MAAM,WAAa,GAC7B,IAAM,EAAO,KAAK,SAAS,MACvB,IAAQ,EAAK,MAAA,CAAQ,EAAM,EAAK,MAAM,WAAa,WAAA,EACtD,EAAA,EAAA,gBACe,EAAA,MAAA,EAAM,EAAA,EAAA,WACb,KAAK,cAAA,CAAA,CACd,WAAA,CAEF,KAAK,oBAAoB,gBAAiB,CAAE,MAAO,YAAA,CAAA,CAQpD,kBAA0B,EAAA,CACzB,IAAM,EAAO,KAAK,SAAS,MACrB,EAAY,KAAK,cAAc,MACjC,IACH,EAAK,UAAU,OAAO,kBAAmB,EAAA,CACzC,EAAK,UAAU,OAAO,cAAA,CAAgB,EAAA,EAEnC,IACH,EAAU,MAAM,QAAU,EAAW,OAAS,IA2BhD,QAAA,CACK,KAAK,KAAM,KAAK,eAAA,CACf,KAAK,cAAA,CAGX,QAAA,CACK,KAAK,MACT,KAAK,cAAA,CAGN,OAAA,CACM,KAAK,MACV,KAAK,eAAA,CAON,QAAA,CACC,IAAM,EAAW,KAAK,eAAe,WAAW,SAAA,CAE1C,GAAA,EAAA,EAAA,UAA4B,CACjC,MAAA,CAAO,EACP,KAAA,CAAM,EACN,WAAY,EACZ,mBAAA,CAAqB,EACrB,SAAA,CAAU,EACV,SAAA,CAAW,KAAK,SAChB,SAAU,KAAK,SACf,0BAA2B,KAAK,SAChC,0BAA2B,KAAK,MAAA,CAAS,KAAK,SAC9C,cAAe,KAAK,KACpB,0BAAA,CAA4B,KAAK,MAAA,CAAS,KAAK,SAC/C,iBAAA,CAAmB,KAAK,KACxB,kBAAA,CAAmB,EAAA,CAAA,CAGd,GAAA,EAAA,EAAA,UAA2B,CAChC,MAAO,KAAK,WACZ,aAAc,qBACd,iBAAkB,OAAA,CAAA,CAGb,GAAA,EAAA,EAAA,UAAsB,CAC3B,iBAAkB,KAAK,KAAO,OAAS,OAAA,CAAA,CAGlC,GAAA,EAAA,EAAA,UAAuB,CAC5B,SAAA,CAAU,EACV,OAAA,CAAQ,EACR,KAAA,CAAM,EACN,eAAA,CAAgB,EAChB,QAAA,CAAS,EACT,cAAA,CAAe,EACf,cAAA,CAAe,EAAA,CAAA,CAGhB,MAAO,GAAA,IAAI;;gBAEH,KAAK,cAAA,CAAA;;iBAEE,KAAK,UAAA;YACV,EAAA;YACA,EAAA;oBACQ,KAAK,KAAA;mBACN,KAAK,aAAA;;;;iBAIb,KAAK,SAAA,CAAA;;aAEH,EAAA;;;;OAIN,KAAK,WAAa,EAAA,IAAI,+BAAiC,EAAA,QAAA;;;;;;4BAMxC,CAAE,iBAAkB,OAAQ,OAAQ,OAAA,CAAA,CAAA;;;kBAG9C,KAAK,SAAA,CAAA;QACT,EAAA,EAAW,CAAE,OAAQ,IAAK,UAAW,GAAA,CAAA,CAAA;cAC/B,EAAA;;;;oBAIM,KAAK,KAAO,kBAAoB,gBAAA;iBACnC,KAAK,mBAAA;;;;;;;8EAOwD,KAAK,KAAO,aAAe,GAAA;;;;;;;;0BAjpB9F,CAAE,KAAM,OAAA,CAAA,CAAA,CAAS,EAAA,UAAA,KAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAEjB,CAAE,KAAM,OAAA,CAAA,CAAA,CAAS,EAAA,UAAA,gBAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAEjB,CAAE,KAAM,OAAA,CAAA,CAAA,CAAS,EAAA,UAAA,iBAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAEjB,CAAE,KAAM,QAAS,QAAA,CAAS,EAAA,CAAA,CAAA,CAAO,EAAA,UAAA,UAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAEjC,CAAE,KAAM,OAAA,CAAA,CAAA,CAAS,EAAA,UAAA,SAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAEjB,CAAE,KAAM,QAAA,CAAA,CAAA,CAAU,EAAA,UAAA,YAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAElB,CAAE,KAAM,QAAA,CAAA,CAAA,CAAU,EAAA,UAAA,eAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAElB,CAAE,KAAM,OAAQ,QAAA,CAAS,EAAA,CAAA,CAAA,CAAO,EAAA,UAAA,cAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAEhC,CAAE,KAAM,OAAA,CAAA,CAAA,CAAS,EAAA,UAAA,WAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAEjB,CAAE,KAAM,OAAA,CAAA,CAAA,CAAS,EAAA,UAAA,YAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,UAGjB,CAAE,KAAM,QAAS,QAAA,CAAS,EAAA,CAAA,CAAA,CAAO,EAAA,UAAA,OAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,QAAA,CAAA,CAKnC,EAAA,UAAA,aAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,QAAA,CAAA,CAEA,EAAA,UAAA,WAAA,IAAA,GAAA,CAAA,EAAA,EAAA,EAAA,EAAA,EAAA,QAAA,CAAA,CAIA,EAAA,UAAA,iBAAA,IAAA,GAAA,CAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,eA3CM,kBAAA,CAAA,CAAkB,EAAA,CAAA,OAAA,eAAA,QAAA,IAAA,CAAA,WAAA,CAAA,EAAA,IAAA,UAAA,CAAA,OAAA,GAAA,CAAA,CAAA,OAAA,eAAA,QAAA,IAAA,CAAA,WAAA,CAAA,EAAA,IAAA,UAAA,CAAA,OAAA,GAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"window-Czfu-i4Y.cjs","names":[],"sources":["../src/window/window-manager.ts","../src/window/window-position.ts","../src/window/window.ts"],"sourcesContent":["/**\n * Window Manager — singleton service for multi-window coordination.\n *\n * Tracks all schmancy-window instances: positions, z-indices, focus, visual states.\n * Components register on connectedCallback, unregister on disconnectedCallback.\n * Focus changes, position updates, and overlap queries all flow through here.\n *\n * Follows the ThemeService singleton pattern (theme/theme.service.ts).\n *\n * Example:\n * windowManager.register('chat-1', bounds, 'bottom-right')\n * windowManager.focus('chat-1') // bumps z-index, updates focusedId\n * const overlaps = windowManager.findOverlaps(projectedBounds, 'chat-1')\n */\n\nimport { BehaviorSubject, Observable, distinctUntilChanged, map } from 'rxjs'\nimport { overlayStack } from '../utils/overlay-stack.js'\nimport type { WindowBounds, WindowRecord, WindowRegistryState, SnapTarget } from './window-registry.js'\n\nconst STORAGE_PREFIX = 'schmancy-window-'\nconst LEGACY_STORAGE_PREFIX = 'schmancy-float-'\n\nclass WindowManagerService {\n\tprivate static instance: WindowManagerService\n\n\tprivate readonly _state$ = new BehaviorSubject<WindowRegistryState>({\n\t\twindows: new Map(),\n\t\tfocusedId: null,\n\t\tstackOrder: [],\n\t})\n\n\treadonly state$ = this._state$.asObservable()\n\n\tprivate constructor() {}\n\n\tstatic getInstance(): WindowManagerService {\n\t\tif (!WindowManagerService.instance) {\n\t\t\tWindowManagerService.instance = new WindowManagerService()\n\t\t}\n\t\treturn WindowManagerService.instance\n\t}\n\n\t// ── Synchronous accessors ──────────────────────────────────────────\n\n\tget windows(): Map<string, WindowRecord> {\n\t\treturn this._state$.value.windows\n\t}\n\n\tget focusedId(): string | null {\n\t\treturn this._state$.value.focusedId\n\t}\n\n\t// ── Registration ───────────────────────────────────────────────────\n\n\tregister(id: string, initialBounds: WindowBounds, snapTarget: SnapTarget): void {\n\t\tconst state = this._state$.value\n\t\tif (state.windows.has(id)) return\n\n\t\tconst zIndex = overlayStack.assignZIndex(id)\n\t\tconst record: WindowRecord = {\n\t\t\tid,\n\t\t\tbounds: initialBounds,\n\t\t\tvisualState: 'normal',\n\t\t\tzIndex,\n\t\t\topen: false,\n\t\t\tsnapTarget,\n\t\t}\n\n\t\tconst windows = new Map(state.windows)\n\t\twindows.set(id, record)\n\t\tconst stackOrder = overlayStack.getStackOrder()\n\n\t\tthis._state$.next({ ...state, windows, stackOrder })\n\t}\n\n\tunregister(id: string): void {\n\t\tconst state = this._state$.value\n\t\tif (!state.windows.has(id)) return\n\n\t\toverlayStack.releaseId(id)\n\t\tconst windows = new Map(state.windows)\n\t\twindows.delete(id)\n\t\tconst stackOrder = overlayStack.getStackOrder()\n\t\tconst focusedId = state.focusedId === id ? null : state.focusedId\n\n\t\tthis._state$.next({ ...state, windows, stackOrder, focusedId })\n\t}\n\n\t// ── State mutations ────────────────────────────────────────────────\n\n\tupdateBounds(id: string, bounds: WindowBounds): void {\n\t\tthis._updateRecord(id, { bounds })\n\t}\n\n\tupdateVisualState(id: string, visualState: WindowRecord['visualState']): void {\n\t\tthis._updateRecord(id, { visualState })\n\t}\n\n\tupdateOpen(id: string, open: boolean): void {\n\t\tthis._updateRecord(id, { open })\n\t}\n\n\tfocus(id: string): void {\n\t\tconst state = this._state$.value\n\t\tif (!state.windows.has(id)) return\n\t\tif (state.focusedId === id) return\n\n\t\tconst zIndex = overlayStack.bringToFront(id)\n\t\tconst windows = new Map(state.windows)\n\t\tconst record = windows.get(id)\n\t\tif (record) {\n\t\t\twindows.set(id, { ...record, zIndex })\n\t\t}\n\t\tconst stackOrder = overlayStack.getStackOrder()\n\n\t\tthis._state$.next({ ...state, windows, stackOrder, focusedId: id })\n\t}\n\n\t// ── Queries ────────────────────────────────────────────────────────\n\n\tfindOverlaps(bounds: WindowBounds, excludeId: string): WindowRecord[] {\n\t\tconst result: WindowRecord[] = []\n\t\tfor (const [id, record] of this._state$.value.windows) {\n\t\t\tif (id === excludeId) continue\n\t\t\tif (rectsOverlap(bounds, record.bounds)) {\n\t\t\t\tresult.push(record)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tgetNeighbors(id: string): WindowRecord[] {\n\t\tconst result: WindowRecord[] = []\n\t\tfor (const [otherId, record] of this._state$.value.windows) {\n\t\t\tif (otherId !== id) result.push(record)\n\t\t}\n\t\treturn result\n\t}\n\n\t// ── Selectors ──────────────────────────────────────────────────────\n\n\tselectWindow(id: string): Observable<WindowRecord | undefined> {\n\t\treturn this._state$.pipe(\n\t\t\tmap(state => state.windows.get(id)),\n\t\t\tdistinctUntilChanged(),\n\t\t)\n\t}\n\n\tselectFocused(): Observable<string | null> {\n\t\treturn this._state$.pipe(\n\t\t\tmap(state => state.focusedId),\n\t\t\tdistinctUntilChanged(),\n\t\t)\n\t}\n\n\t// ── Persistence ────────────────────────────────────────────────────\n\n\tloadPosition(id: string): { x: number; y: number; anchor: string } | null {\n\t\ttry {\n\t\t\t// Try new key first, fall back to legacy\n\t\t\tconst raw = localStorage.getItem(STORAGE_PREFIX + id) ?? localStorage.getItem(LEGACY_STORAGE_PREFIX + id)\n\t\t\tif (!raw) return null\n\t\t\treturn JSON.parse(raw) as { x: number; y: number; anchor: string }\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tsavePosition(id: string, data: { x: number; y: number; anchor: string }): void {\n\t\ttry {\n\t\t\tlocalStorage.setItem(STORAGE_PREFIX + id, JSON.stringify(data))\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\tclearPosition(id: string): void {\n\t\ttry {\n\t\t\tlocalStorage.removeItem(STORAGE_PREFIX + id)\n\t\t\tlocalStorage.removeItem(LEGACY_STORAGE_PREFIX + id)\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\t// ── Internal ───────────────────────────────────────────────────────\n\n\tprivate _updateRecord(id: string, updates: Partial<WindowRecord>): void {\n\t\tconst state = this._state$.value\n\t\tconst record = state.windows.get(id)\n\t\tif (!record) return\n\n\t\tconst windows = new Map(state.windows)\n\t\twindows.set(id, { ...record, ...updates })\n\t\tthis._state$.next({ ...state, windows })\n\t}\n}\n\n/** Simple rect overlap check (inline — no circular import with window-position) */\nfunction rectsOverlap(a: WindowBounds, b: WindowBounds): boolean {\n\treturn !(a.left >= b.left + b.width || a.left + a.width <= b.left || a.top >= b.top + b.height || a.top + a.height <= b.top)\n}\n\nexport const windowManager = WindowManagerService.getInstance()\n","/**\n * Window Position — pure functions for overlap resolution, cascade, and snapping.\n *\n * All functions are stateless: they take window bounds and viewport dimensions,\n * return new bounds. No side effects, no DOM access, no subscriptions.\n *\n * Example:\n * const projected = { left: 100, top: 400, width: 360, height: 500 }\n * const neighbors = windowManager.findOverlaps(projected, 'my-id')\n * const resolved = resolveOverlap(projected, neighbors, { width: 1440, height: 900 })\n * // → { left: 144, top: 444, width: 360, height: 500 } (cascaded away from conflict)\n */\n\nimport type { WindowBounds, WindowRecord } from './window-registry.js'\n\nconst HEAD_HEIGHT = 44\nconst CASCADE_OFFSET = HEAD_HEIGHT\nconst MAX_CASCADE_ATTEMPTS = 10\n\n/** Check if two rectangles overlap (edges touching does NOT count as overlap) */\nexport function rectsOverlap(a: WindowBounds, b: WindowBounds): boolean {\n\treturn !(a.left >= b.left + b.width || a.left + a.width <= b.left || a.top >= b.top + b.height || a.top + a.height <= b.top)\n}\n\n/**\n * Resolve overlap by cascading diagonally until no conflict.\n * Shifts by (HEAD_HEIGHT, HEAD_HEIGHT) per attempt, clamped to viewport.\n */\nexport function resolveOverlap(\n\tcandidate: WindowBounds,\n\texisting: WindowRecord[],\n\tviewport: { width: number; height: number },\n): WindowBounds {\n\tlet bounds = { ...candidate }\n\n\tfor (let attempt = 0; attempt < MAX_CASCADE_ATTEMPTS; attempt++) {\n\t\tconst hasOverlap = existing.some(w => rectsOverlap(bounds, w.bounds))\n\t\tif (!hasOverlap) break\n\n\t\tbounds = {\n\t\t\t...bounds,\n\t\t\tleft: bounds.left + CASCADE_OFFSET,\n\t\t\ttop: bounds.top + CASCADE_OFFSET,\n\t\t}\n\t}\n\n\treturn clampToViewport(bounds, viewport)\n}\n\n/**\n * Clamp bounds so the window stays fully within the viewport.\n */\nexport function clampToViewport(\n\tbounds: WindowBounds,\n\tviewport: { width: number; height: number },\n): WindowBounds {\n\treturn {\n\t\twidth: bounds.width,\n\t\theight: bounds.height,\n\t\tleft: Math.max(0, Math.min(bounds.left, viewport.width - bounds.width)),\n\t\ttop: Math.max(0, Math.min(bounds.top, viewport.height - bounds.height)),\n\t}\n}\n","import { $LitElement } from '@mixins/index'\nimport { css, html, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { styleMap } from 'lit/directives/style-map.js'\nimport {\n\tanimationFrameScheduler,\n\tauditTime,\n\tcatchError,\n\tEMPTY,\n\tfilter,\n\tfinalize,\n\tfrom,\n\tfromEvent,\n\tmap,\n\tmerge,\n\tObservable,\n\tswitchMap,\n\ttake,\n\ttakeUntil,\n\ttap,\n} from 'rxjs'\nimport { SPRING_SMOOTH, SPRING_SNAPPY } from '../utils/animation.js'\nimport { cursorGlow } from '../directives/cursor-glow'\nimport { reducedMotion$ } from '../directives/reduced-motion'\nimport { theme } from '../theme/theme.service.js'\nimport type { SnapCorner, WindowBounds, WindowVisualState } from './window-registry.js'\nimport { windowManager } from './window-manager.js'\nimport { resolveOverlap } from './window-position.js'\n\nconst HEAD_HEIGHT = 48\nconst DRAG_THRESHOLD = 5\n\ninterface Position {\n\tx: number\n\ty: number\n}\n\n@customElement('schmancy-window')\nexport default class SchmancyWindow extends $LitElement(css`\n\t:host {\n\t\tdisplay: contents;\n\t\tposition: relative;\n\t\tz-index: 1000;\n\t}\n\t:host([hidden]) {\n\t\tdisplay: none !important;\n\t}\n`) {\n\t@property({ type: String }) id: string = 'default'\n\t/** Override the expanded panel width (e.g. '320px', '24rem'). Defaults to responsive sizing. */\n\t@property({ type: String }) expandedWidth?: string\n\t/** Override the expanded panel height (e.g. '400px', '50vh'). */\n\t@property({ type: String }) expandedHeight?: string\n\t/** When true, uses a lower elevation shadow in the collapsed state. */\n\t@property({ type: Boolean, reflect: true }) lowered: boolean = false\n\t/** Corner the window is anchored to. */\n\t@property({ type: String }) corner: SnapCorner = 'bottom-right'\n\t/** When true, window can be resized by the user. */\n\t@property({ type: Boolean }) resizable = false\n\t/** When true, window stays at its dragged position instead of snapping to a corner. */\n\t@property({ type: Boolean }) freePosition = false\n\t/** Visual state of the window (minimized, normal, maximized). */\n\t@property({ type: String, reflect: true }) visualState: WindowVisualState = 'normal'\n\t/** Minimum width in pixels. */\n\t@property({ type: Number }) minWidth = 280\n\t/** Minimum height in pixels. */\n\t@property({ type: Number }) minHeight = 200\n\n\t/** Whether the body is expanded. */\n\t@property({ type: Boolean, reflect: true }) open = false\n\n\tprivate _currentAnimation?: Animation\n\n\t/** Lazy rendering: body content not in DOM until first expand. */\n\t@state() private _hasOpened = false\n\t/** Whether this window is the focused window in the manager — drives visual ring */\n\t@state() private _focused = false\n\n\t// Internal position -- plain fields, updated directly during drag\n\tprivate _position: Position = { x: 16, y: 16 }\n\t@state() private _currentCorner: SnapCorner = 'bottom-right'\n\n\t// Track applied corner to avoid unnecessary style.removeProperty calls during drag\n\tprivate _appliedCorner: string = ''\n\n\t// Refs\n\tprivate _containerRef = createRef<HTMLElement>()\n\tprivate _bodyRef = createRef<HTMLElement>()\n\tprivate _headRef = createRef<HTMLElement>()\n\n\t// ============================================\n\t// COMPUTED\n\t// ============================================\n\n\tprivate get panelWidth(): string {\n\t\treturn this.expandedWidth ?? 'min(360px, calc(100vw - 32px))'\n\t}\n\n\tprivate get isBottomCorner(): boolean {\n\t\treturn this._currentCorner.startsWith('bottom')\n\t}\n\n\tprivate get closedClipPath(): string {\n\t\treturn this.isBottomCorner\n\t\t\t? `inset(calc(100% - ${HEAD_HEIGHT}px) 0px 0px 0px round 22px)`\n\t\t\t: `inset(0px 0px calc(100% - ${HEAD_HEIGHT}px) 0px round 22px)`\n\t}\n\n\tprivate get openClipPath(): string {\n\t\treturn 'inset(0px 0px 0px 0px round 12px)'\n\t}\n\n\tprivate get elevation(): string {\n\t\tif (this.open) return '4'\n\t\treturn this.lowered ? '1' : '3'\n\t}\n\n\t// ============================================\n\t// POSITION MANAGEMENT\n\t// ============================================\n\n\tprivate _applyContainerPosition() {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\t\t// Only clear position properties when corner changes (avoids 4 style invalidations per drag frame)\n\t\tif (this._appliedCorner !== this._currentCorner) {\n\t\t\tcontainer.style.removeProperty('left')\n\t\t\tcontainer.style.removeProperty('right')\n\t\t\tcontainer.style.removeProperty('top')\n\t\t\tcontainer.style.removeProperty('bottom')\n\t\t\tthis._appliedCorner = this._currentCorner\n\t\t}\n\t\tconst { x, y } = this._position\n\t\tif (this._currentCorner.includes('right')) {\n\t\t\tcontainer.style.right = `${x}px`\n\t\t} else {\n\t\t\tcontainer.style.left = `${x}px`\n\t\t}\n\t\tif (this._currentCorner.includes('bottom')) {\n\t\t\tcontainer.style.bottom = `${y + theme.bottomOffset}px`\n\t\t} else {\n\t\t\tcontainer.style.top = `${y}px`\n\t\t}\n\t}\n\n\tprivate static readonly VALID_CORNERS = new Set<string>(['top-left', 'top-right', 'bottom-left', 'bottom-right'])\n\n\tprivate _loadPosition() {\n\t\tconst saved = windowManager.loadPosition(this.id)\n\t\tif (saved) {\n\t\t\tthis._position = { x: saved.x, y: saved.y }\n\t\t\tif (SchmancyWindow.VALID_CORNERS.has(saved.anchor)) {\n\t\t\t\tthis._currentCorner = saved.anchor as SnapCorner\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _savePosition() {\n\t\twindowManager.savePosition(this.id, { ...this._position, anchor: this._currentCorner })\n\t}\n\n\tprivate _validateBounds() {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\t\tconst rect = container.getBoundingClientRect()\n\t\tif (rect.width === 0) return\n\t\tconst vw = window.innerWidth\n\t\tconst vh = window.innerHeight\n\t\tconst isRight = this._currentCorner.includes('right')\n\t\tconst isBottom = this._currentCorner.includes('bottom')\n\t\tconst actualLeft = isRight ? vw - this._position.x - rect.width : this._position.x\n\t\tconst actualTop = isBottom ? vh - this._position.y - rect.height : this._position.y\n\t\tconst newLeft = Math.max(0, Math.min(actualLeft, vw - rect.width))\n\t\tconst newTop = Math.max(0, Math.min(actualTop, vh - rect.height))\n\t\tthis._position = {\n\t\t\tx: isRight ? vw - newLeft - rect.width : newLeft,\n\t\t\ty: isBottom ? vh - newTop - rect.height : newTop,\n\t\t}\n\t\tthis._applyContainerPosition()\n\t}\n\n\t// ============================================\n\t// CORNER SNAPPING\n\t// ============================================\n\n\tprivate _reorientToNearestCorner(skipAnimation = false): void {\n\t\t// Free position mode: skip corner snapping\n\t\tif (this.freePosition) {\n\t\t\tthis._savePosition()\n\t\t\tconst rect = this._containerRef.value?.getBoundingClientRect()\n\t\t\tif (rect) {\n\t\t\t\twindowManager.updateBounds(this.id, { left: rect.left, top: rect.top, width: rect.width, height: rect.height })\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\n\t\t// F -- record current screen position before DOM mutation\n\t\tconst rect = container.getBoundingClientRect()\n\n\t\t// L -- calculate nearest corner using head visual center\n\t\tconst currentIsBottom = this._currentCorner.includes('bottom')\n\t\tconst headCenterX = rect.left + rect.width / 2\n\t\tconst headCenterY = currentIsBottom\n\t\t\t? rect.bottom - HEAD_HEIGHT / 2\n\t\t\t: rect.top + HEAD_HEIGHT / 2\n\t\tconst side = headCenterX > window.innerWidth / 2 ? 'right' : 'left'\n\t\tconst vert = headCenterY > window.innerHeight / 2 ? 'bottom' : 'top'\n\t\tconst newCorner: SnapCorner = `${vert}-${side}` as SnapCorner\n\n\t\t// Snap corner and reset offset to standard edge gap\n\t\tthis._currentCorner = newCorner\n\t\tthis._position = { x: 16, y: 16 }\n\t\tthis._applyContainerPosition()\n\t\t// Sync clip-path to new corner\n\t\tif (!this.open) {\n\t\t\tcontainer.style.clipPath = this.closedClipPath\n\t\t}\n\n\t\tif (skipAnimation || reducedMotion$.value) {\n\t\t\tthis._savePosition()\n\t\t\tconst snapRect = container.getBoundingClientRect()\n\t\t\twindowManager.updateBounds(this.id, { left: snapRect.left, top: snapRect.top, width: snapRect.width, height: snapRect.height })\n\t\t\treturn\n\t\t}\n\n\t\t// I -- invert: shift element back to its original visual position\n\t\tconst newRect = container.getBoundingClientRect()\n\t\tconst dx = rect.left - newRect.left\n\t\tconst dy = rect.top - newRect.top\n\t\tcontainer.style.translate = `${dx}px ${dy}px`\n\n\t\t// P -- play: animate from the inverse offset to natural resting position\n\t\tconst flipKeyframes: Keyframe[] = [{ translate: `${dx}px ${dy}px` }, { translate: '0px 0px' }]\n\t\tconst anim = container.animate(\n\t\t\tflipKeyframes,\n\t\t\t{\n\t\t\t\tduration: SPRING_SMOOTH.duration,\n\t\t\t\teasing: SPRING_SMOOTH.easingFallback,\n\t\t\t\tfill: 'forwards',\n\t\t\t},\n\t\t)\n\t\tfrom(anim.finished).pipe(\n\t\t\ttake(1),\n\t\t\ttap(() => {\n\t\t\t\tif (container.isConnected) container.style.translate = ''\n\t\t\t\t// Report final resting bounds after animation completes\n\t\t\t\tconst finalRect = container.getBoundingClientRect()\n\t\t\t\twindowManager.updateBounds(this.id, { left: finalRect.left, top: finalRect.top, width: finalRect.width, height: finalRect.height })\n\t\t\t}),\n\t\t\tcatchError(() => EMPTY),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\n\t\tthis._savePosition()\n\t}\n\n\t// ============================================\n\t// DRAG PIPELINE\n\t// ============================================\n\n\tprivate _drag$(): Observable<never> {\n\t\treturn new Observable(() => {\n\t\t\tconst head = this._headRef.value\n\t\t\tconst container = this._containerRef.value\n\t\t\tif (!head || !container) return\n\n\t\t\tlet didDrag = false\n\n\t\t\tconst sub = fromEvent<PointerEvent>(head, 'pointerdown').pipe(\n\t\t\t\tfilter(e => e.button === 0),\n\t\t\t\tfilter(e => {\n\t\t\t\t\tconst tag = (e.target as HTMLElement).tagName?.toLowerCase()\n\t\t\t\t\treturn !['input', 'textarea', 'select', 'button'].includes(tag)\n\t\t\t\t\t\t&& !(e.target as HTMLElement).closest('schmancy-input, schmancy-icon-button, button, a')\n\t\t\t\t}),\n\t\t\t\ttap(e => {\n\t\t\t\t\te.preventDefault()\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t}),\n\t\t\t)\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(e => {\n\t\t\t\t\t\tconst rect = container.getBoundingClientRect()\n\t\t\t\t\t\tconst isBottom = this._currentCorner.includes('bottom')\n\t\t\t\t\t\tconst wasOpen = this.open\n\t\t\t\t\t\tdidDrag = false\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstartX: e.clientX,\n\t\t\t\t\t\t\tstartY: e.clientY,\n\t\t\t\t\t\t\toffsetX: e.clientX - rect.left,\n\t\t\t\t\t\t\toffsetY: e.clientY - rect.top,\n\t\t\t\t\t\t\trect,\n\t\t\t\t\t\t\tvw: window.innerWidth,\n\t\t\t\t\t\t\tvh: window.innerHeight,\n\t\t\t\t\t\t\tisBottom,\n\t\t\t\t\t\t\twasOpen,\n\t\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t\tswitchMap(({ startX, startY, offsetX, offsetY, rect, vw, vh, isBottom, wasOpen, pointerId }) => {\n\t\t\t\t\t\tconst move$ = fromEvent<PointerEvent>(window, 'pointermove').pipe(\n\t\t\t\t\t\t\tfilter(e => e.pointerId === pointerId),\n\t\t\t\t\t\t\tauditTime(0, animationFrameScheduler),\n\t\t\t\t\t\t\tmap(e => ({ clientX: e.clientX, clientY: e.clientY })),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst end$ = fromEvent<PointerEvent>(window, 'pointerup').pipe(\n\t\t\t\t\t\t\tfilter(e => e.pointerId === pointerId),\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\treturn move$.pipe(\n\t\t\t\t\t\t\ttap(({ clientX, clientY }) => {\n\t\t\t\t\t\t\t\tconst dx = clientX - startX\n\t\t\t\t\t\t\t\tconst dy = clientY - startY\n\t\t\t\t\t\t\t\tif (Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD && !didDrag) {\n\t\t\t\t\t\t\t\t\tdidDrag = true\n\t\t\t\t\t\t\t\t\tthis._applyDragVisuals(true)\n\t\t\t\t\t\t\t\t\t// Collapse on first confirmed drag move\n\t\t\t\t\t\t\t\t\tif (wasOpen) {\n\t\t\t\t\t\t\t\t\t\tthis.open = false\n\t\t\t\t\t\t\t\t\t\tcontainer.style.clipPath = this.closedClipPath\n\t\t\t\t\t\t\t\t\t\tcontainer.style.overflow = 'hidden'\n\t\t\t\t\t\t\t\t\t\tconst body = this._bodyRef.value\n\t\t\t\t\t\t\t\t\t\tif (body) {\n\t\t\t\t\t\t\t\t\t\t\tbody.inert = true\n\t\t\t\t\t\t\t\t\t\t\tbody.style.visibility = 'hidden'\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (!didDrag) return\n\n\t\t\t\t\t\t\t\tconst left = Math.max(0, Math.min(clientX - offsetX, vw - rect.width))\n\t\t\t\t\t\t\t\tconst minTop = isBottom ? HEAD_HEIGHT - rect.height : 0\n\t\t\t\t\t\t\t\tconst maxTop = isBottom ? vh - rect.height : vh - HEAD_HEIGHT\n\t\t\t\t\t\t\t\tconst top = Math.max(minTop, Math.min(clientY - offsetY, maxTop))\n\n\t\t\t\t\t\t\t\tthis._position = {\n\t\t\t\t\t\t\t\t\tx: this._currentCorner.includes('right') ? vw - left - rect.width : left,\n\t\t\t\t\t\t\t\t\ty: isBottom ? vh - top - rect.height : top,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis._applyContainerPosition()\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\ttakeUntil(end$),\n\t\t\t\t\t\t\tfinalize(() => {\n\t\t\t\t\t\t\t\tif (didDrag) {\n\t\t\t\t\t\t\t\t\tthis._reorientToNearestCorner()\n\t\t\t\t\t\t\t\t\tthis._applyDragVisuals(false)\n\t\t\t\t\t\t\t\t\tdidDrag = false\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tdidDrag = false\n\t\t\t\t\t\t\t\t\tthis.toggle()\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.subscribe()\n\n\t\t\treturn () => sub.unsubscribe()\n\t\t})\n\t}\n\n\t// ============================================\n\t// LIFECYCLE\n\t// ============================================\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\n\t\t// Pipeline 1: DOM setup + manager registration + drag + z-index sync\n\t\tfrom(this.updateComplete).pipe(\n\t\t\ttake(1),\n\t\t\ttap(() => {\n\t\t\t\tthis._currentCorner = this.corner\n\t\t\t\tthis._loadPosition()\n\t\t\t\tthis._applyContainerPosition()\n\t\t\t\tthis._initDOMState()\n\t\t\t\t// Register with window manager\n\t\t\t\tconst container = this._containerRef.value\n\t\t\t\tif (container) {\n\t\t\t\t\tconst rect = container.getBoundingClientRect()\n\t\t\t\t\tconst bounds: WindowBounds = { left: rect.left, top: rect.top, width: rect.width, height: rect.height }\n\t\t\t\t\twindowManager.register(this.id, bounds, this.freePosition ? 'free' : this._currentCorner)\n\t\t\t\t}\n\t\t\t}),\n\t\t\tswitchMap(() => merge(\n\t\t\t\tthis._drag$(),\n\t\t\t\twindowManager.selectWindow(this.id).pipe(\n\t\t\t\t\ttap(record => {\n\t\t\t\t\t\tif (!record) return\n\t\t\t\t\t\tconst container = this._containerRef.value\n\t\t\t\t\t\tif (container) container.style.zIndex = String(record.zIndex)\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\twindowManager.selectFocused().pipe(\n\t\t\t\t\ttap(focusedId => {\n\t\t\t\t\t\tthis._focused = focusedId === this.id\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t)),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\n\n\t\t// Pipeline 3: Environment -- one subscription\n\t\tmerge(\n\t\t\tfromEvent(window, 'resize').pipe(\n\t\t\t\tauditTime(0, animationFrameScheduler),\n\t\t\t\ttap(() => this._validateBounds()),\n\t\t\t),\n\t\t\ttheme.bottomOffset$.pipe(\n\t\t\t\ttap(() => this._applyContainerPosition()),\n\t\t\t),\n\t\t).pipe(takeUntil(this.disconnecting)).subscribe()\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\twindowManager.unregister(this.id)\n\t}\n\n\tprivate _initDOMState() {\n\t\tconst container = this._containerRef.value\n\t\tconst body = this._bodyRef.value\n\t\tif (!container) return\n\n\t\tthis._applyContainerPosition()\n\n\t\tif (this.open) {\n\t\t\tthis._hasOpened = true\n\t\t\tcontainer.style.overflow = ''\n\t\t\tif (body) {\n\t\t\t\tbody.inert = false\n\t\t\t\tbody.style.visibility = 'visible'\n\t\t\t}\n\t\t} else {\n\t\t\tcontainer.style.clipPath = this.closedClipPath\n\t\t\tcontainer.style.overflow = 'hidden'\n\t\t\tif (body) {\n\t\t\t\tbody.inert = true\n\t\t\t\tbody.style.visibility = 'hidden'\n\t\t\t}\n\t\t}\n\t}\n\n\t// ============================================\n\t// ANIMATION\n\t// ============================================\n\n\tprivate _animateOpen() {\n\t\tconst container = this._containerRef.value\n\t\tconst body = this._bodyRef.value\n\t\tif (!container) return\n\n\t\tthis._hasOpened = true\n\t\tthis.open = true\n\n\t\t// Overlap avoidance\n\t\tconst rect = container.getBoundingClientRect()\n\t\tconst projectedBounds: WindowBounds = {\n\t\t\tleft: rect.left,\n\t\t\ttop: this.isBottomCorner ? rect.top - 400 : rect.top,\n\t\t\twidth: rect.width,\n\t\t\theight: 400 + HEAD_HEIGHT,\n\t\t}\n\t\tconst overlaps = windowManager.findOverlaps(projectedBounds, this.id)\n\t\tif (overlaps.length > 0) {\n\t\t\tconst resolved = resolveOverlap(projectedBounds, overlaps, { width: window.innerWidth, height: window.innerHeight })\n\t\t\tif (Math.abs(resolved.left - projectedBounds.left) > 10 || Math.abs(resolved.top - projectedBounds.top) > 10) {\n\t\t\t\tconst isRight = this._currentCorner.includes('right')\n\t\t\t\tconst isBottom = this._currentCorner.includes('bottom')\n\t\t\t\tthis._position = {\n\t\t\t\t\tx: isRight ? window.innerWidth - resolved.left - resolved.width : resolved.left,\n\t\t\t\t\ty: isBottom ? window.innerHeight - resolved.top - resolved.height : resolved.top,\n\t\t\t\t}\n\t\t\t\tthis._applyContainerPosition()\n\t\t\t}\n\t\t}\n\n\t\tif (body) {\n\t\t\tbody.style.visibility = 'visible'\n\t\t\tbody.inert = false\n\t\t}\n\n\t\tif (reducedMotion$.value) {\n\t\t\tcontainer.style.clipPath = ''\n\t\t\tcontainer.style.overflow = ''\n\t\t\tthis.dispatchScopedEvent('window-toggle', { state: 'expanded' })\n\t\t\treturn\n\t\t}\n\n\t\tthis._currentAnimation?.cancel()\n\t\tcontainer.style.overflow = 'hidden'\n\t\tcontainer.style.willChange = 'opacity'\n\t\tconst openKeyframes: Keyframe[] = [\n\t\t\t{ clipPath: this.closedClipPath, opacity: 0.95 },\n\t\t\t{ clipPath: this.openClipPath, opacity: 1 },\n\t\t]\n\t\tconst anim = container.animate(openKeyframes, {\n\t\t\tduration: SPRING_SNAPPY.duration,\n\t\t\teasing: SPRING_SNAPPY.easingFallback,\n\t\t\tfill: 'forwards',\n\t\t})\n\t\tthis._currentAnimation = anim\n\n\t\tfrom(anim.finished).pipe(\n\t\t\ttake(1),\n\t\t\ttap(() => {\n\t\t\t\tif (container.isConnected) {\n\t\t\t\t\tcontainer.style.clipPath = ''\n\t\t\t\t\tcontainer.style.overflow = ''\n\t\t\t\t\tcontainer.style.willChange = ''\n\t\t\t\t}\n\t\t\t}),\n\t\t\tcatchError(() => EMPTY),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\n\t\tthis.dispatchScopedEvent('window-toggle', { state: 'expanded' })\n\t}\n\n\tprivate _animateClose() {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\n\t\tif (reducedMotion$.value) {\n\t\t\tcontainer.style.clipPath = this.closedClipPath\n\t\t\tcontainer.style.overflow = 'hidden'\n\t\t\tthis.open = false\n\t\t\tconst body = this._bodyRef.value\n\t\t\tif (body) { body.inert = true; body.style.visibility = 'hidden' }\n\t\t\tthis.dispatchScopedEvent('window-toggle', { state: 'collapsed' })\n\t\t\treturn\n\t\t}\n\n\t\tthis._currentAnimation?.cancel()\n\t\tcontainer.style.overflow = 'hidden'\n\t\tcontainer.style.willChange = 'opacity'\n\t\tconst closeKeyframes: Keyframe[] = [\n\t\t\t{ clipPath: this.openClipPath, opacity: 1 },\n\t\t\t{ clipPath: this.closedClipPath, opacity: 0.95 },\n\t\t]\n\t\tconst anim = container.animate(closeKeyframes, {\n\t\t\tduration: Math.round(SPRING_SNAPPY.duration * 0.7),\n\t\t\teasing: 'cubic-bezier(0.4, 0, 0.8, 0.15)',\n\t\t\tfill: 'forwards',\n\t\t})\n\t\tthis._currentAnimation = anim\n\n\t\tfrom(anim.finished).pipe(\n\t\t\ttake(1),\n\t\t\ttap(() => {\n\t\t\t\tthis.open = false\n\t\t\t\tcontainer.style.willChange = ''\n\t\t\t\tconst body = this._bodyRef.value\n\t\t\t\tif (body) { body.inert = true; body.style.visibility = 'hidden' }\n\t\t\t}),\n\t\t\tcatchError(() => EMPTY),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\n\t\tthis.dispatchScopedEvent('window-toggle', { state: 'collapsed' })\n\t}\n\n\t// ============================================\n\t// VISUAL STATE HELPERS\n\t// ============================================\n\n\t/** Apply drag visuals directly on DOM refs — avoids full Lit re-render for cursor + opacity */\n\tprivate _applyDragVisuals(dragging: boolean) {\n\t\tconst head = this._headRef.value\n\t\tconst container = this._containerRef.value\n\t\tif (head) {\n\t\t\thead.classList.toggle('cursor-grabbing', dragging)\n\t\t\thead.classList.toggle('cursor-move', !dragging)\n\t\t}\n\t\tif (container) {\n\t\t\tcontainer.style.opacity = dragging ? '0.95' : ''\n\t\t}\n\t}\n\n\tprivate _handleFocus = () => windowManager.focus(this.id)\n\n\tprivate _handleHeadKeydown = (e: KeyboardEvent) => {\n\t\tif (e.key === 'Enter' || e.key === ' ') {\n\t\t\te.preventDefault()\n\t\t\tthis.toggle()\n\t\t\treturn\n\t\t}\n\t\tif (e.key === 'ArrowUp' || e.key === 'ArrowDown' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n\t\t\te.preventDefault()\n\t\t\tconst step = e.shiftKey ? 20 : 5\n\t\t\tconst dx = e.key === 'ArrowRight' ? step : e.key === 'ArrowLeft' ? -step : 0\n\t\t\tconst dy = e.key === 'ArrowDown' ? step : e.key === 'ArrowUp' ? -step : 0\n\t\t\tthis._position = { x: this._position.x + dx, y: this._position.y + dy }\n\t\t\tthis._applyContainerPosition()\n\t\t\tthis._savePosition()\n\t\t}\n\t}\n\n\t// ============================================\n\t// PUBLIC API\n\t// ============================================\n\n\ttoggle() {\n\t\tif (this.open) this._animateClose()\n\t\telse this._animateOpen()\n\t}\n\n\texpand() {\n\t\tif (this.open) return\n\t\tthis._animateOpen()\n\t}\n\n\tclose() {\n\t\tif (!this.open) return\n\t\tthis._animateClose()\n\t}\n\n\t// ============================================\n\t// RENDER\n\t// ============================================\n\n\tprotected render(): unknown {\n\t\tconst isBottom = this._currentCorner.startsWith('bottom')\n\n\t\tconst containerClasses = classMap({\n\t\t\tfixed: true,\n\t\t\tflex: true,\n\t\t\t'flex-col': isBottom,\n\t\t\t'flex-col-reverse': !isBottom,\n\t\t\t'z-1000': true,\n\t\t\t'ring-1': !this._focused,\n\t\t\t'ring-2': this._focused,\n\t\t\t'ring-primary-default/30': this._focused,\n\t\t\t'ring-primary-default/15': this.open && !this._focused,\n\t\t\t'rounded-2xl': this.open,\n\t\t\t'ring-outline-variant/40': !this.open && !this._focused,\n\t\t\t'rounded-[22px]': !this.open,\n\t\t\t'overflow-hidden': true,\n\t\t})\n\n\t\tconst containerStyles = styleMap({\n\t\t\twidth: this.panelWidth,\n\t\t\t'max-height': 'calc(100vh - 32px)',\n\t\t\t'pointer-events': 'none',\n\t\t})\n\n\t\tconst bodyStyles = styleMap({\n\t\t\t'pointer-events': this.open ? 'auto' : 'none',\n\t\t})\n\n\t\tconst headClasses = classMap({\n\t\t\t'h-full': true,\n\t\t\t'px-3': true,\n\t\t\tflex: true,\n\t\t\t'items-center': true,\n\t\t\t'gap-2': true,\n\t\t\t'select-none': true,\n\t\t\t'cursor-move': true,\n\t\t})\n\n\t\treturn html`\n\t\t\t<schmancy-surface\n\t\t\t\t${ref(this._containerRef)}\n\t\t\t\ttype=\"glass\"\n\t\t\t\televation=\"${this.elevation}\"\n\t\t\t\tclass=${containerClasses}\n\t\t\t\tstyle=${containerStyles}\n\t\t\t\taria-expanded=${this.open}\n\t\t\t\t@pointerdown=${this._handleFocus}\n\t\t\t>\n\t\t\t\t<!-- Details section (visually above summary for bottom corners) -->\n\t\t\t\t<section\n\t\t\t\t\t${ref(this._bodyRef)}\n\t\t\t\t\tclass=\"flex-1 min-h-0 overflow-hidden flex flex-col\"\n\t\t\t\t\tstyle=${bodyStyles}\n\t\t\t\t\trole=\"region\"\n\t\t\t\t\taria-label=\"Expandable content\"\n\t\t\t\t>\n\t\t\t\t\t${this._hasOpened ? html`<slot name=\"details\"></slot>` : nothing}\n\t\t\t\t</section>\n\n\t\t\t\t<!-- Summary section -- always interactive, always visible -->\n\t\t\t\t<section\n\t\t\t\t\tclass=\"shrink-0 bg-surface-lowest\"\n\t\t\t\t\tstyle=${styleMap({ 'pointer-events': 'auto', height: `${HEAD_HEIGHT}px` })}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\t${ref(this._headRef)}\n\t\t\t\t\t\t${cursorGlow({ radius: 200, intensity: 0.10 })}\n\t\t\t\t\t\tclass=${headClasses}\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\ttabindex=\"0\"\n\t\t\t\t\t\ttitle=\"Drag to move, click to expand\"\n\t\t\t\t\t\taria-label=\"${this.open ? 'Collapse window' : 'Expand window'}\"\n\t\t\t\t\t\t@keydown=${this._handleHeadKeydown}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"flex-1 min-w-0\">\n\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\twidth=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"\n\t\t\t\t\t\t\tclass=\"shrink-0 text-surface-on/40 transition-transform duration-200 ${this.open ? 'rotate-180' : ''}\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<path d=\"M6 9L12 15L18 9\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t</schmancy-surface>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-window': SchmancyWindow\n\t}\n}\n"],"mappings":"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"}
|
package/dist/window.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./window-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./window-Czfu-i4Y.cjs`);exports.SchmancyWindow=e.t,exports.windowManager=e.n;
|
package/dist/window.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as e, t } from "./window-
|
|
1
|
+
import { n as e, t } from "./window-ChDgkb97.js";
|
|
2
2
|
export { t as SchmancyWindow, e as windowManager };
|
package/package.json
CHANGED
package/skills/schmancy/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: schmancy
|
|
3
|
-
description: UI patterns, component APIs, and conventions for the @mhmo91/schmancy web-component library (Lit + RxJS + Tailwind).
|
|
3
|
+
description: UI patterns, component APIs, and conventions for the @mhmo91/schmancy web-component library (Lit + RxJS + Tailwind) — the UI stack for any consumer app that installs this plugin. Fire this skill on ANY web-UI work, even when the user doesn't name schmancy explicitly — including adding or editing a component, building a form, showing a dialog / toast / side drawer / bottom sheet, wiring routing, reading or writing a context, styling with theme tokens, adding a drop zone / file input / date picker / autocomplete, working with `$LitElement`, or touching any `<schmancy-*>` tag. Also fire on prompts like "build a page", "add a modal", "wire a route", "save user prefs in storage", "animate this", "style with our theme", "make a notification", "how do I do X in Lit", "my drag-and-drop", "dark mode toggle".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Schmancy
|
package/src/button/button.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { $LitElement } from '@mixins/index'
|
|
2
|
+
import { provide } from '@lit/context'
|
|
2
3
|
import { css, html, LitElement } from 'lit'
|
|
3
4
|
import { customElement, property, query, queryAssignedElements } from 'lit/decorators.js'
|
|
4
5
|
import { ifDefined } from 'lit/directives/if-defined.js'
|
|
5
6
|
import { when } from 'lit/directives/when.js'
|
|
6
7
|
import { magnetic } from '../directives/magnetic'
|
|
8
|
+
import { SchmancyButtonSizeContext, type SchmancyButtonSize } from './context'
|
|
7
9
|
|
|
8
10
|
export interface SchmancyButtonEventMap {
|
|
9
11
|
SchmancyFocus: CustomEvent<void>
|
|
@@ -132,13 +134,16 @@ export class SchmancyButton extends $LitElement(
|
|
|
132
134
|
|
|
133
135
|
/**
|
|
134
136
|
* The size of the button.
|
|
137
|
+
* Provided as `SchmancyButtonSizeContext` to descendant elements so children
|
|
138
|
+
* (e.g. `<schmancy-icon>`) can auto-size against the enclosing button.
|
|
135
139
|
* @attr
|
|
136
140
|
* @type {'xxs' | 'xs' | 'sm' | 'md' | 'lg'}
|
|
137
141
|
* @default 'md'
|
|
138
142
|
* @public
|
|
139
143
|
*/
|
|
144
|
+
@provide({ context: SchmancyButtonSizeContext })
|
|
140
145
|
@property({ type: String })
|
|
141
|
-
public size:
|
|
146
|
+
public size: SchmancyButtonSize = 'md'
|
|
142
147
|
|
|
143
148
|
/**
|
|
144
149
|
* The type of the button.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createContext } from '@lit/context'
|
|
2
|
+
|
|
3
|
+
export type SchmancyButtonSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Provided by `<schmancy-button>` to its descendants so children
|
|
7
|
+
* (e.g. `<schmancy-icon>`) can auto-size against the enclosing button.
|
|
8
|
+
*/
|
|
9
|
+
export const SchmancyButtonSizeContext = createContext<SchmancyButtonSize>('schmancy-button-size')
|
package/src/icons/icon.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { TailwindElement } from '@mixins/index'
|
|
2
|
+
import { consume } from '@lit/context'
|
|
2
3
|
import { css, html } from 'lit'
|
|
3
4
|
import { customElement, property, state } from 'lit/decorators.js'
|
|
4
5
|
import { BehaviorSubject, combineLatest, takeUntil } from 'rxjs'
|
|
5
6
|
import { tap } from 'rxjs/operators'
|
|
7
|
+
import { SchmancyButtonSizeContext, type SchmancyButtonSize } from '../button/context'
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Icon size tokens - M3 aligned with optical size optimization
|
|
@@ -127,10 +129,22 @@ export default class SchmancyIcon extends TailwindElement(css`
|
|
|
127
129
|
* Size of the icon - M3 aligned tokens or custom string
|
|
128
130
|
* Tokens: 'xxs' (12px), 'xs' (16px), 'sm' (20px), 'md' (24px), 'lg' (32px)
|
|
129
131
|
* Custom: any CSS size string like '48px', '2rem'
|
|
132
|
+
*
|
|
133
|
+
* When this icon is a descendant of `<schmancy-button>`, the button's
|
|
134
|
+
* `size` wins (via `SchmancyButtonSizeContext`). The local `size` only
|
|
135
|
+
* applies when there is no ancestor button.
|
|
130
136
|
*/
|
|
131
137
|
@property({ type: String, reflect: true })
|
|
132
138
|
size: IconSize = 'md'
|
|
133
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Size inherited from an ancestor `<schmancy-button>` via context.
|
|
142
|
+
* Undefined when the icon is not nested in a button.
|
|
143
|
+
*/
|
|
144
|
+
@consume({ context: SchmancyButtonSizeContext, subscribe: true })
|
|
145
|
+
@state()
|
|
146
|
+
private _buttonSize?: SchmancyButtonSize
|
|
147
|
+
|
|
134
148
|
/**
|
|
135
149
|
* Icon name - use this instead of slot content to prevent translation breaking icons.
|
|
136
150
|
* When set, this takes precedence over slot content.
|
|
@@ -259,10 +273,12 @@ export default class SchmancyIcon extends TailwindElement(css`
|
|
|
259
273
|
'sharp': 'Material Symbols Sharp'
|
|
260
274
|
}[this.variant] || 'Material Symbols Outlined'
|
|
261
275
|
|
|
276
|
+
// Effective size: ancestor `<schmancy-button>` wins via context, else local `size`.
|
|
277
|
+
const effectiveSize: IconSize = this._buttonSize ?? this.size
|
|
262
278
|
// Resolve size: token → px, bare number → px, or pass through as-is
|
|
263
|
-
const sizeConfig = SchmancyIcon.tokenSizes[
|
|
264
|
-
const isNumeric = !sizeConfig && /^\d+(\.\d+)?$/.test(
|
|
265
|
-
const iconSize = sizeConfig?.size || (isNumeric ? `${
|
|
279
|
+
const sizeConfig = SchmancyIcon.tokenSizes[effectiveSize]
|
|
280
|
+
const isNumeric = !sizeConfig && /^\d+(\.\d+)?$/.test(effectiveSize)
|
|
281
|
+
const iconSize = sizeConfig?.size || (isNumeric ? `${effectiveSize}px` : effectiveSize)
|
|
266
282
|
const opticalSize = sizeConfig?.opsz || SchmancyIcon.computeOpticalSize(iconSize)
|
|
267
283
|
|
|
268
284
|
// Set size on HOST so :host CSS picks it up
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
|
+
import { type SchmancyButtonSize } from './context';
|
|
2
3
|
export interface SchmancyButtonEventMap {
|
|
3
4
|
SchmancyFocus: CustomEvent<void>;
|
|
4
5
|
SchmancyBlur: CustomEvent<void>;
|
|
@@ -55,12 +56,14 @@ export declare class SchmancyButton extends SchmancyButton_base {
|
|
|
55
56
|
width: 'full' | 'auto';
|
|
56
57
|
/**
|
|
57
58
|
* The size of the button.
|
|
59
|
+
* Provided as `SchmancyButtonSizeContext` to descendant elements so children
|
|
60
|
+
* (e.g. `<schmancy-icon>`) can auto-size against the enclosing button.
|
|
58
61
|
* @attr
|
|
59
62
|
* @type {'xxs' | 'xs' | 'sm' | 'md' | 'lg'}
|
|
60
63
|
* @default 'md'
|
|
61
64
|
* @public
|
|
62
65
|
*/
|
|
63
|
-
size:
|
|
66
|
+
size: SchmancyButtonSize;
|
|
64
67
|
/**
|
|
65
68
|
* The type of the button.
|
|
66
69
|
* Defaults to 'button' (preventing accidental form submissions).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type SchmancyButtonSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg';
|
|
2
|
+
/**
|
|
3
|
+
* Provided by `<schmancy-button>` to its descendants so children
|
|
4
|
+
* (e.g. `<schmancy-icon>`) can auto-size against the enclosing button.
|
|
5
|
+
*/
|
|
6
|
+
export declare const SchmancyButtonSizeContext: {
|
|
7
|
+
__context__: SchmancyButtonSize;
|
|
8
|
+
};
|
|
@@ -50,8 +50,17 @@ export default class SchmancyIcon extends SchmancyIcon_base {
|
|
|
50
50
|
* Size of the icon - M3 aligned tokens or custom string
|
|
51
51
|
* Tokens: 'xxs' (12px), 'xs' (16px), 'sm' (20px), 'md' (24px), 'lg' (32px)
|
|
52
52
|
* Custom: any CSS size string like '48px', '2rem'
|
|
53
|
+
*
|
|
54
|
+
* When this icon is a descendant of `<schmancy-button>`, the button's
|
|
55
|
+
* `size` wins (via `SchmancyButtonSizeContext`). The local `size` only
|
|
56
|
+
* applies when there is no ancestor button.
|
|
53
57
|
*/
|
|
54
58
|
size: IconSize;
|
|
59
|
+
/**
|
|
60
|
+
* Size inherited from an ancestor `<schmancy-button>` via context.
|
|
61
|
+
* Undefined when the icon is not nested in a button.
|
|
62
|
+
*/
|
|
63
|
+
private _buttonSize?;
|
|
55
64
|
/**
|
|
56
65
|
* Icon name - use this instead of slot content to prevent translation breaking icons.
|
|
57
66
|
* When set, this takes precedence over slot content.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"icons-1AkKNd7O.cjs","names":[],"sources":["../src/icons/icon.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { BehaviorSubject, combineLatest, takeUntil } from 'rxjs'\nimport { tap } from 'rxjs/operators'\n\n/**\n * Icon size tokens - M3 aligned with optical size optimization\n * - xxs: 12px (opsz: 20) - fits in 24px buttons (ultra-compact)\n * - xs: 16px (opsz: 20) - fits in 32px buttons\n * - sm: 20px (opsz: 20) - fits in 40px buttons\n * - md: 24px (opsz: 24) - fits in 48px buttons (default)\n * - lg: 32px (opsz: 40) - fits in 56px buttons\n * - Or custom string like '48px'\n */\nexport type IconSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | string\n\n/**\n * @element schmancy-icon\n * Material Symbols icon component with flexible font variation properties\n *\n * @cssprop --schmancy-icon-size - The size of the icon (default: 24px)\n * @cssprop --schmancy-icon-fill - Fill value for icon (0-1)\n * @cssprop --schmancy-icon-weight - Weight value for icon (100-700)\n * @cssprop --schmancy-icon-grade - Grade value for icon (-50-200)\n * @cssprop --schmancy-icon-opsz - Optical size (default: 24)\n * @csspart icon - The inner `<span>` carrying the Material Symbols glyph.\n */\n@customElement('schmancy-icon')\nexport default class SchmancyIcon extends TailwindElement(css`\n\t:host {\n\t\t--schmancy-icon-size: 24px;\n\t\t--schmancy-icon-fill: 0;\n\t\t--schmancy-icon-weight: 400;\n\t\t--schmancy-icon-grade: 0;\n\t\t--schmancy-icon-opsz: 24;\n\n\t\tdisplay: inline-flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\twidth: var(--schmancy-icon-size);\n\t\theight: var(--schmancy-icon-size);\n\t\tfont-size: var(--schmancy-icon-size);\n\t\tcolor: inherit;\n\t\ttransition: font-variation-settings 0.2s ease;\n\t}\n\n\t.material-symbols {\n\t\tfont-family: var(--schmancy-icon-font, 'Material Symbols Outlined');\n\t\tfont-weight: normal;\n\t\tfont-style: normal;\n\t\tline-height: 1;\n\t\tletter-spacing: normal;\n\t\ttext-transform: none;\n\t\tdisplay: inline-block;\n\t\twhite-space: nowrap;\n\t\tword-wrap: normal;\n\t\tdirection: ltr;\n\t\t-webkit-font-smoothing: antialiased;\n\t\t-webkit-font-feature-settings: 'liga';\n\t\tfont-feature-settings: 'liga';\n\t\tfont-variation-settings:\n\t\t\t'FILL' var(--schmancy-icon-fill),\n\t\t\t'wght' var(--schmancy-icon-weight),\n\t\t\t'GRAD' var(--schmancy-icon-grade),\n\t\t\t'opsz' var(--schmancy-icon-opsz);\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t}\n\n\t/* CSS-generated content is NOT translated by Google Translate */\n\t.material-symbols[data-icon]::before {\n\t\tcontent: attr(data-icon);\n\t}\n`) {\n\t// Static flag to track if Google Fonts have been loaded\n\tprivate static fontsLoaded = false\n\n\t/**\n\t * Load Material Symbols fonts from Google Fonts CDN\n\t */\n\tprivate static loadFonts(): void {\n\t\tif (SchmancyIcon.fontsLoaded) {\n\t\t\treturn\n\t\t}\n\n\t\tconst link = document.createElement('link')\n\t\tlink.rel = 'stylesheet'\n\t\tlink.href = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&family=Material+Symbols+Sharp:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap'\n\t\tdocument.head.appendChild(link)\n\n\t\tSchmancyIcon.fontsLoaded = true\n\t}\n\n\t/**\n\t * Fill value for the icon (0-1)\n\t * 0 = outlined, 1 = filled\n\t */\n\t@property({ type: Number, reflect: true })\n\tfill = 0\n\n\t/**\n\t * Weight value for the icon (100-700)\n\t * Controls the thickness of the icon strokes\n\t */\n\t@property({ type: Number, reflect: true })\n\tweight = 400\n\n\t/**\n\t * Grade value for the icon (-50-200)\n\t * Adjusts the visual weight/grade\n\t */\n\t@property({ type: Number, reflect: true })\n\tgrade = 0\n\n\t/**\n\t * Icon variant style\n\t * @values outlined | rounded | sharp\n\t */\n\t@property({ type: String, reflect: true })\n\tvariant: 'outlined' | 'rounded' | 'sharp' = 'outlined'\n\n\t/**\n\t * Size of the icon - M3 aligned tokens or custom string\n\t * Tokens: 'xxs' (12px), 'xs' (16px), 'sm' (20px), 'md' (24px), 'lg' (32px)\n\t * Custom: any CSS size string like '48px', '2rem'\n\t */\n\t@property({ type: String, reflect: true })\n\tsize: IconSize = 'md'\n\n\t/**\n\t * Icon name - use this instead of slot content to prevent translation breaking icons.\n\t * When set, this takes precedence over slot content.\n\t * Example: <schmancy-icon icon=\"delete\"></schmancy-icon>\n\t */\n\t@property({ type: String })\n\ticon?: string\n\n\t// M3 aligned token sizes with optimal optical sizes\n\tprivate static readonly tokenSizes: Record<string, { size: string; opsz: number }> = {\n\t\txxs: { size: '12px', opsz: 20 }, // fits in 24px buttons (ultra-compact)\n\t\txs: { size: '16px', opsz: 20 }, // fits in 32px buttons\n\t\tsm: { size: '20px', opsz: 20 }, // fits in 40px buttons\n\t\tmd: { size: '24px', opsz: 24 }, // fits in 48px buttons (default)\n\t\tlg: { size: '32px', opsz: 40 }, // fits in 56px buttons\n\t}\n\n\t/** Extract pixel value from a custom size string for optical size */\n\tprivate static computeOpticalSize(size: string): number {\n\t\tconst px = parseFloat(size)\n\t\treturn isNaN(px) ? 24 : Math.max(20, Math.min(48, Math.round(px)))\n\t}\n\n\t// RxJS subjects for reactive property updates\n\tprivate fill$ = new BehaviorSubject(this.fill)\n\tprivate weight$ = new BehaviorSubject(this.weight)\n\tprivate grade$ = new BehaviorSubject(this.grade)\n\tprivate variant$ = new BehaviorSubject(this.variant)\n\n\t// Captured icon name from slot content (translation-proof)\n\t@state()\n\tprivate _capturedIcon?: string\n\n\t// Observer for text content changes (ternaries update text nodes, not DOM structure)\n\tprivate _observer?: MutationObserver\n\n\tconnectedCallback(): void {\n\t\tsuper.connectedCallback()\n\n\t\t// Capture initial icon name\n\t\tthis._updateCapturedIcon()\n\n\t\t// Watch for text content changes (characterData) for dynamic icon updates\n\t\tthis._observer = new MutationObserver(() => this._updateCapturedIcon())\n\t\tthis._observer.observe(this, { childList: true, characterData: true, subtree: true })\n\n\t\t// Load Google Fonts if not already loaded\n\t\tSchmancyIcon.loadFonts()\n\n\t\t// Prevent browser translation from breaking icon ligatures\n\t\t// Using multiple methods for maximum compatibility:\n\t\t// - translate=\"no\" (HTML5 standard)\n\t\t// - class=\"notranslate\" (Google Translate specific)\n\t\tthis.setAttribute('translate', 'no')\n\t\tthis.classList.add('notranslate')\n\n\t\t// Set accessibility attributes for decorative icons\n\t\tif (!this.hasAttribute('aria-label') &&\n\t\t !this.hasAttribute('aria-labelledby') &&\n\t\t !this.hasAttribute('aria-hidden') &&\n\t\t !this.hasAttribute('role')) {\n\t\t\tthis.setAttribute('aria-hidden', 'true')\n\t\t}\n\n\t\t// Setup reactive CSS variable updates\n\t\tcombineLatest([\n\t\t\tthis.fill$,\n\t\t\tthis.weight$,\n\t\t\tthis.grade$,\n\t\t\tthis.variant$\n\t\t]).pipe(\n\t\t\ttap(([fill, weight, grade, variant]) => {\n\t\t\t\t// Update CSS custom properties for smooth transitions\n\t\t\t\tthis.style.setProperty('--schmancy-icon-fill', String(fill))\n\t\t\t\tthis.style.setProperty('--schmancy-icon-weight', String(weight))\n\t\t\t\tthis.style.setProperty('--schmancy-icon-grade', String(grade))\n\n\t\t\t\t// Update font family based on variant\n\t\t\t\tconst fontFamily = {\n\t\t\t\t\t'outlined': 'Material Symbols Outlined',\n\t\t\t\t\t'rounded': 'Material Symbols Rounded',\n\t\t\t\t\t'sharp': 'Material Symbols Sharp'\n\t\t\t\t}[variant] || 'Material Symbols Outlined'\n\n\t\t\t\tthis.style.setProperty('--schmancy-icon-font', fontFamily)\n\t\t\t}),\n\t\t\ttakeUntil(this.disconnecting)\n\t\t).subscribe()\n\n\t}\n\n\t/**\n\t * Update captured icon from current text content\n\t */\n\tprivate _updateCapturedIcon(): void {\n\t\tif (!this.icon) {\n\t\t\tconst textContent = this.textContent?.trim()\n\t\t\tif (textContent && textContent !== this._capturedIcon) {\n\t\t\t\tthis._capturedIcon = textContent\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected updated(changedProperties: Map<string | number | symbol, unknown>): void {\n\t\tsuper.updated(changedProperties)\n\n\t\t// Update BehaviorSubjects when properties change\n\t\tif (changedProperties.has('fill')) {\n\t\t\tthis.fill$.next(this.fill)\n\t\t}\n\t\tif (changedProperties.has('weight')) {\n\t\t\tthis.weight$.next(this.weight)\n\t\t}\n\t\tif (changedProperties.has('grade')) {\n\t\t\tthis.grade$.next(this.grade)\n\t\t}\n\t\tif (changedProperties.has('variant')) {\n\t\t\tthis.variant$.next(this.variant)\n\t\t}\n\t}\n\n\tprotected render(): unknown {\n\t\tconst fontFamily = {\n\t\t\t'outlined': 'Material Symbols Outlined',\n\t\t\t'rounded': 'Material Symbols Rounded',\n\t\t\t'sharp': 'Material Symbols Sharp'\n\t\t}[this.variant] || 'Material Symbols Outlined'\n\n\t\t// Resolve size: token → px, bare number → px, or pass through as-is\n\t\tconst sizeConfig = SchmancyIcon.tokenSizes[this.size]\n\t\tconst isNumeric = !sizeConfig && /^\\d+(\\.\\d+)?$/.test(this.size)\n\t\tconst iconSize = sizeConfig?.size || (isNumeric ? `${this.size}px` : this.size)\n\t\tconst opticalSize = sizeConfig?.opsz || SchmancyIcon.computeOpticalSize(iconSize)\n\n\t\t// Set size on HOST so :host CSS picks it up\n\t\tthis.style.setProperty('--schmancy-icon-size', iconSize)\n\t\tthis.style.setProperty('--schmancy-icon-opsz', String(opticalSize))\n\n\t\tconst style = {\n\t\t\t'--schmancy-icon-fill': this.fill,\n\t\t\t'--schmancy-icon-weight': this.weight,\n\t\t\t'--schmancy-icon-grade': this.grade,\n\t\t\t'--schmancy-icon-font': fontFamily,\n\t\t}\n\n\t\t// Priority: icon property > captured icon (for dynamic content)\n\t\tconst iconName = this.icon || this._capturedIcon\n\n\t\t// Always render slot (hidden) to observe content changes, display via data-icon\n\t\treturn html`\n\t\t\t<span class=\"material-symbols notranslate\" part=\"icon\" translate=\"no\" data-icon=${iconName || ''} style=${this.styleMap(style)}></span>\n\t\t\t<slot style=\"display:none\"></slot>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-icon': SchmancyIcon\n\t}\n}"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"icons-DqIVrIIK.js","names":[],"sources":["../src/icons/icon.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { BehaviorSubject, combineLatest, takeUntil } from 'rxjs'\nimport { tap } from 'rxjs/operators'\n\n/**\n * Icon size tokens - M3 aligned with optical size optimization\n * - xxs: 12px (opsz: 20) - fits in 24px buttons (ultra-compact)\n * - xs: 16px (opsz: 20) - fits in 32px buttons\n * - sm: 20px (opsz: 20) - fits in 40px buttons\n * - md: 24px (opsz: 24) - fits in 48px buttons (default)\n * - lg: 32px (opsz: 40) - fits in 56px buttons\n * - Or custom string like '48px'\n */\nexport type IconSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | string\n\n/**\n * @element schmancy-icon\n * Material Symbols icon component with flexible font variation properties\n *\n * @cssprop --schmancy-icon-size - The size of the icon (default: 24px)\n * @cssprop --schmancy-icon-fill - Fill value for icon (0-1)\n * @cssprop --schmancy-icon-weight - Weight value for icon (100-700)\n * @cssprop --schmancy-icon-grade - Grade value for icon (-50-200)\n * @cssprop --schmancy-icon-opsz - Optical size (default: 24)\n * @csspart icon - The inner `<span>` carrying the Material Symbols glyph.\n */\n@customElement('schmancy-icon')\nexport default class SchmancyIcon extends TailwindElement(css`\n\t:host {\n\t\t--schmancy-icon-size: 24px;\n\t\t--schmancy-icon-fill: 0;\n\t\t--schmancy-icon-weight: 400;\n\t\t--schmancy-icon-grade: 0;\n\t\t--schmancy-icon-opsz: 24;\n\n\t\tdisplay: inline-flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\twidth: var(--schmancy-icon-size);\n\t\theight: var(--schmancy-icon-size);\n\t\tfont-size: var(--schmancy-icon-size);\n\t\tcolor: inherit;\n\t\ttransition: font-variation-settings 0.2s ease;\n\t}\n\n\t.material-symbols {\n\t\tfont-family: var(--schmancy-icon-font, 'Material Symbols Outlined');\n\t\tfont-weight: normal;\n\t\tfont-style: normal;\n\t\tline-height: 1;\n\t\tletter-spacing: normal;\n\t\ttext-transform: none;\n\t\tdisplay: inline-block;\n\t\twhite-space: nowrap;\n\t\tword-wrap: normal;\n\t\tdirection: ltr;\n\t\t-webkit-font-smoothing: antialiased;\n\t\t-webkit-font-feature-settings: 'liga';\n\t\tfont-feature-settings: 'liga';\n\t\tfont-variation-settings:\n\t\t\t'FILL' var(--schmancy-icon-fill),\n\t\t\t'wght' var(--schmancy-icon-weight),\n\t\t\t'GRAD' var(--schmancy-icon-grade),\n\t\t\t'opsz' var(--schmancy-icon-opsz);\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t}\n\n\t/* CSS-generated content is NOT translated by Google Translate */\n\t.material-symbols[data-icon]::before {\n\t\tcontent: attr(data-icon);\n\t}\n`) {\n\t// Static flag to track if Google Fonts have been loaded\n\tprivate static fontsLoaded = false\n\n\t/**\n\t * Load Material Symbols fonts from Google Fonts CDN\n\t */\n\tprivate static loadFonts(): void {\n\t\tif (SchmancyIcon.fontsLoaded) {\n\t\t\treturn\n\t\t}\n\n\t\tconst link = document.createElement('link')\n\t\tlink.rel = 'stylesheet'\n\t\tlink.href = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&family=Material+Symbols+Sharp:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap'\n\t\tdocument.head.appendChild(link)\n\n\t\tSchmancyIcon.fontsLoaded = true\n\t}\n\n\t/**\n\t * Fill value for the icon (0-1)\n\t * 0 = outlined, 1 = filled\n\t */\n\t@property({ type: Number, reflect: true })\n\tfill = 0\n\n\t/**\n\t * Weight value for the icon (100-700)\n\t * Controls the thickness of the icon strokes\n\t */\n\t@property({ type: Number, reflect: true })\n\tweight = 400\n\n\t/**\n\t * Grade value for the icon (-50-200)\n\t * Adjusts the visual weight/grade\n\t */\n\t@property({ type: Number, reflect: true })\n\tgrade = 0\n\n\t/**\n\t * Icon variant style\n\t * @values outlined | rounded | sharp\n\t */\n\t@property({ type: String, reflect: true })\n\tvariant: 'outlined' | 'rounded' | 'sharp' = 'outlined'\n\n\t/**\n\t * Size of the icon - M3 aligned tokens or custom string\n\t * Tokens: 'xxs' (12px), 'xs' (16px), 'sm' (20px), 'md' (24px), 'lg' (32px)\n\t * Custom: any CSS size string like '48px', '2rem'\n\t */\n\t@property({ type: String, reflect: true })\n\tsize: IconSize = 'md'\n\n\t/**\n\t * Icon name - use this instead of slot content to prevent translation breaking icons.\n\t * When set, this takes precedence over slot content.\n\t * Example: <schmancy-icon icon=\"delete\"></schmancy-icon>\n\t */\n\t@property({ type: String })\n\ticon?: string\n\n\t// M3 aligned token sizes with optimal optical sizes\n\tprivate static readonly tokenSizes: Record<string, { size: string; opsz: number }> = {\n\t\txxs: { size: '12px', opsz: 20 }, // fits in 24px buttons (ultra-compact)\n\t\txs: { size: '16px', opsz: 20 }, // fits in 32px buttons\n\t\tsm: { size: '20px', opsz: 20 }, // fits in 40px buttons\n\t\tmd: { size: '24px', opsz: 24 }, // fits in 48px buttons (default)\n\t\tlg: { size: '32px', opsz: 40 }, // fits in 56px buttons\n\t}\n\n\t/** Extract pixel value from a custom size string for optical size */\n\tprivate static computeOpticalSize(size: string): number {\n\t\tconst px = parseFloat(size)\n\t\treturn isNaN(px) ? 24 : Math.max(20, Math.min(48, Math.round(px)))\n\t}\n\n\t// RxJS subjects for reactive property updates\n\tprivate fill$ = new BehaviorSubject(this.fill)\n\tprivate weight$ = new BehaviorSubject(this.weight)\n\tprivate grade$ = new BehaviorSubject(this.grade)\n\tprivate variant$ = new BehaviorSubject(this.variant)\n\n\t// Captured icon name from slot content (translation-proof)\n\t@state()\n\tprivate _capturedIcon?: string\n\n\t// Observer for text content changes (ternaries update text nodes, not DOM structure)\n\tprivate _observer?: MutationObserver\n\n\tconnectedCallback(): void {\n\t\tsuper.connectedCallback()\n\n\t\t// Capture initial icon name\n\t\tthis._updateCapturedIcon()\n\n\t\t// Watch for text content changes (characterData) for dynamic icon updates\n\t\tthis._observer = new MutationObserver(() => this._updateCapturedIcon())\n\t\tthis._observer.observe(this, { childList: true, characterData: true, subtree: true })\n\n\t\t// Load Google Fonts if not already loaded\n\t\tSchmancyIcon.loadFonts()\n\n\t\t// Prevent browser translation from breaking icon ligatures\n\t\t// Using multiple methods for maximum compatibility:\n\t\t// - translate=\"no\" (HTML5 standard)\n\t\t// - class=\"notranslate\" (Google Translate specific)\n\t\tthis.setAttribute('translate', 'no')\n\t\tthis.classList.add('notranslate')\n\n\t\t// Set accessibility attributes for decorative icons\n\t\tif (!this.hasAttribute('aria-label') &&\n\t\t !this.hasAttribute('aria-labelledby') &&\n\t\t !this.hasAttribute('aria-hidden') &&\n\t\t !this.hasAttribute('role')) {\n\t\t\tthis.setAttribute('aria-hidden', 'true')\n\t\t}\n\n\t\t// Setup reactive CSS variable updates\n\t\tcombineLatest([\n\t\t\tthis.fill$,\n\t\t\tthis.weight$,\n\t\t\tthis.grade$,\n\t\t\tthis.variant$\n\t\t]).pipe(\n\t\t\ttap(([fill, weight, grade, variant]) => {\n\t\t\t\t// Update CSS custom properties for smooth transitions\n\t\t\t\tthis.style.setProperty('--schmancy-icon-fill', String(fill))\n\t\t\t\tthis.style.setProperty('--schmancy-icon-weight', String(weight))\n\t\t\t\tthis.style.setProperty('--schmancy-icon-grade', String(grade))\n\n\t\t\t\t// Update font family based on variant\n\t\t\t\tconst fontFamily = {\n\t\t\t\t\t'outlined': 'Material Symbols Outlined',\n\t\t\t\t\t'rounded': 'Material Symbols Rounded',\n\t\t\t\t\t'sharp': 'Material Symbols Sharp'\n\t\t\t\t}[variant] || 'Material Symbols Outlined'\n\n\t\t\t\tthis.style.setProperty('--schmancy-icon-font', fontFamily)\n\t\t\t}),\n\t\t\ttakeUntil(this.disconnecting)\n\t\t).subscribe()\n\n\t}\n\n\t/**\n\t * Update captured icon from current text content\n\t */\n\tprivate _updateCapturedIcon(): void {\n\t\tif (!this.icon) {\n\t\t\tconst textContent = this.textContent?.trim()\n\t\t\tif (textContent && textContent !== this._capturedIcon) {\n\t\t\t\tthis._capturedIcon = textContent\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected updated(changedProperties: Map<string | number | symbol, unknown>): void {\n\t\tsuper.updated(changedProperties)\n\n\t\t// Update BehaviorSubjects when properties change\n\t\tif (changedProperties.has('fill')) {\n\t\t\tthis.fill$.next(this.fill)\n\t\t}\n\t\tif (changedProperties.has('weight')) {\n\t\t\tthis.weight$.next(this.weight)\n\t\t}\n\t\tif (changedProperties.has('grade')) {\n\t\t\tthis.grade$.next(this.grade)\n\t\t}\n\t\tif (changedProperties.has('variant')) {\n\t\t\tthis.variant$.next(this.variant)\n\t\t}\n\t}\n\n\tprotected render(): unknown {\n\t\tconst fontFamily = {\n\t\t\t'outlined': 'Material Symbols Outlined',\n\t\t\t'rounded': 'Material Symbols Rounded',\n\t\t\t'sharp': 'Material Symbols Sharp'\n\t\t}[this.variant] || 'Material Symbols Outlined'\n\n\t\t// Resolve size: token → px, bare number → px, or pass through as-is\n\t\tconst sizeConfig = SchmancyIcon.tokenSizes[this.size]\n\t\tconst isNumeric = !sizeConfig && /^\\d+(\\.\\d+)?$/.test(this.size)\n\t\tconst iconSize = sizeConfig?.size || (isNumeric ? `${this.size}px` : this.size)\n\t\tconst opticalSize = sizeConfig?.opsz || SchmancyIcon.computeOpticalSize(iconSize)\n\n\t\t// Set size on HOST so :host CSS picks it up\n\t\tthis.style.setProperty('--schmancy-icon-size', iconSize)\n\t\tthis.style.setProperty('--schmancy-icon-opsz', String(opticalSize))\n\n\t\tconst style = {\n\t\t\t'--schmancy-icon-fill': this.fill,\n\t\t\t'--schmancy-icon-weight': this.weight,\n\t\t\t'--schmancy-icon-grade': this.grade,\n\t\t\t'--schmancy-icon-font': fontFamily,\n\t\t}\n\n\t\t// Priority: icon property > captured icon (for dynamic content)\n\t\tconst iconName = this.icon || this._capturedIcon\n\n\t\t// Always render slot (hidden) to observe content changes, display via data-icon\n\t\treturn html`\n\t\t\t<span class=\"material-symbols notranslate\" part=\"icon\" translate=\"no\" data-icon=${iconName || ''} style=${this.styleMap(style)}></span>\n\t\t\t<slot style=\"display:none\"></slot>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-icon': SchmancyIcon\n\t}\n}"],"mappings":"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"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|