@mhmo91/schmancy 0.10.16 → 0.10.18
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/dist/active-host-BP0zy_Y9.js.map +1 -1
- package/dist/agent/flow-CvG1fLW5.js.map +1 -1
- package/dist/agent/schmancy.agent.js +3730 -3804
- package/dist/agent/schmancy.agent.js.map +1 -1
- package/dist/agent/vendor-material-color-DcL7ZPxx.js.map +1 -1
- package/dist/animation-DCznELuT.js.map +1 -1
- package/dist/{area-ChxsDTu_.js → area-BIipuSyO.js} +1 -1
- package/dist/{area-ChxsDTu_.js.map → area-BIipuSyO.js.map} +1 -1
- package/dist/{area-Qt6yUnuA.cjs → area-C-EMiNEE.cjs} +1 -1
- package/dist/{area-Qt6yUnuA.cjs.map → area-C-EMiNEE.cjs.map} +1 -1
- package/dist/area.cjs +1 -1
- package/dist/area.js +1 -1
- package/dist/audio-DS43uoRA.js.map +1 -1
- package/dist/{autocomplete-Ck2zbdF9.cjs → autocomplete-B8CE5vGw.cjs} +1 -1
- package/dist/{autocomplete-Ck2zbdF9.cjs.map → autocomplete-B8CE5vGw.cjs.map} +1 -1
- package/dist/{autocomplete-CXvUjMD-.js → autocomplete-Mrb3koUN.js} +2 -2
- package/dist/{autocomplete-CXvUjMD-.js.map → autocomplete-Mrb3koUN.js.map} +1 -1
- package/dist/autocomplete.cjs +1 -1
- package/dist/autocomplete.js +1 -1
- package/dist/avatar.cjs +1 -1
- package/dist/avatar.js +2 -2
- package/dist/avatar.js.map +1 -1
- package/dist/badge.cjs +1 -1
- package/dist/badge.js +1 -1
- package/dist/{boat-DpFkILFF.cjs → boat-DN1_tyvx.cjs} +2 -2
- package/dist/{boat-DpFkILFF.cjs.map → boat-DN1_tyvx.cjs.map} +1 -1
- package/dist/{boat-Bj0wVcZi.js → boat-cuoSkhGI.js} +1 -4
- package/dist/{boat-Bj0wVcZi.js.map → boat-cuoSkhGI.js.map} +1 -1
- package/dist/boat.cjs +1 -1
- package/dist/boat.js +1 -1
- package/dist/breadcrumb.cjs +2 -1
- package/dist/breadcrumb.cjs.map +1 -1
- package/dist/breadcrumb.js +2 -1
- package/dist/breadcrumb.js.map +1 -1
- package/dist/{busy-CtcnclA3.cjs → busy-CMKX4oQf.cjs} +1 -1
- package/dist/{busy-CtcnclA3.cjs.map → busy-CMKX4oQf.cjs.map} +1 -1
- package/dist/{busy-CyZSBnZP.js → busy-Cetzws-m.js} +1 -1
- package/dist/{busy-CyZSBnZP.js.map → busy-Cetzws-m.js.map} +1 -1
- package/dist/busy.cjs +1 -1
- package/dist/busy.js +1 -1
- package/dist/button.cjs +4 -3
- package/dist/button.cjs.map +1 -1
- package/dist/button.js +4 -3
- package/dist/button.js.map +1 -1
- package/dist/{card-Cl6jp1yX.cjs → card-8VXoo2C_.cjs} +1 -1
- package/dist/{card-Cl6jp1yX.cjs.map → card-8VXoo2C_.cjs.map} +1 -1
- package/dist/{card-nYZCKmOO.js → card-D2k3dRL0.js} +1 -1
- package/dist/{card-nYZCKmOO.js.map → card-D2k3dRL0.js.map} +1 -1
- package/dist/card.cjs +1 -1
- package/dist/card.js +1 -1
- package/dist/{checkbox-DiUrZiyc.js → checkbox-8hNsBejz.js} +1 -1
- package/dist/{checkbox-DiUrZiyc.js.map → checkbox-8hNsBejz.js.map} +1 -1
- package/dist/{checkbox-BeNo0ZGt.cjs → checkbox-Cq5wzeaY.cjs} +1 -1
- package/dist/{checkbox-BeNo0ZGt.cjs.map → checkbox-Cq5wzeaY.cjs.map} +1 -1
- package/dist/checkbox.cjs +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/{chips-DK6m-VCM.cjs → chips-DSdvCpmi.cjs} +9 -18
- package/dist/chips-DSdvCpmi.cjs.map +1 -0
- package/dist/{chips-CfPFXv7Z.js → chips-m2NPN480.js} +8 -22
- package/dist/chips-m2NPN480.js.map +1 -0
- package/dist/chips.cjs +1 -1
- package/dist/chips.js +2 -2
- package/dist/connectivity.cjs +1 -1
- package/dist/connectivity.js +1 -1
- package/dist/connectivity.js.map +1 -1
- package/dist/content-drawer.cjs +1 -1
- package/dist/content-drawer.js +1 -1
- package/dist/cursor-glow-Cs2XLDB9.js.map +1 -1
- package/dist/{date-range-DjlF2u7o.js → date-range-D98QcCHl.js} +2 -2
- package/dist/{date-range-DjlF2u7o.js.map → date-range-D98QcCHl.js.map} +1 -1
- package/dist/{date-range-DA6anfcF.cjs → date-range-DxS3Agbj.cjs} +1 -1
- package/dist/{date-range-DA6anfcF.cjs.map → date-range-DxS3Agbj.cjs.map} +1 -1
- package/dist/{date-range-inline-BfYK795W.cjs → date-range-inline-Bvs2ZvEY.cjs} +1 -1
- package/dist/{date-range-inline-BfYK795W.cjs.map → date-range-inline-Bvs2ZvEY.cjs.map} +1 -1
- package/dist/{date-range-inline-n7y_H6PJ.js → date-range-inline-TWWnTZlw.js} +1 -1
- package/dist/{date-range-inline-n7y_H6PJ.js.map → date-range-inline-TWWnTZlw.js.map} +1 -1
- package/dist/date-range-inline.cjs +1 -1
- package/dist/date-range-inline.js +1 -1
- package/dist/date-range.cjs +1 -1
- package/dist/date-range.js +1 -1
- package/dist/delay.cjs +1 -1
- package/dist/delay.js +1 -1
- package/dist/delay.js.map +1 -1
- package/dist/{details-CS_ToAOj.js → details-Cpg8sH2F.js} +3 -8
- package/dist/details-Cpg8sH2F.js.map +1 -0
- package/dist/{details-BdAVsLl-.cjs → details-CwSDur6j.cjs} +2 -6
- package/dist/details-CwSDur6j.cjs.map +1 -0
- package/dist/details.cjs +1 -1
- package/dist/details.js +1 -1
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.js.map +1 -1
- package/dist/discovery.js.map +1 -1
- package/dist/{divider-CvWAnvdO.cjs → divider-BNdVLE0H.cjs} +1 -1
- package/dist/{divider-CvWAnvdO.cjs.map → divider-BNdVLE0H.cjs.map} +1 -1
- package/dist/{divider-COLK0RbT.js → divider-Be833gGZ.js} +1 -1
- package/dist/{divider-COLK0RbT.js.map → divider-Be833gGZ.js.map} +1 -1
- package/dist/divider.cjs +1 -1
- package/dist/divider.js +1 -1
- package/dist/dropdown.cjs +1 -1
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.js.map +1 -1
- package/dist/{expand-r2sATPUJ.cjs → expand-BP6RLzHw.cjs} +1 -1
- package/dist/{expand-r2sATPUJ.cjs.map → expand-BP6RLzHw.cjs.map} +1 -1
- package/dist/{expand-D9LzmpoV.js → expand-CtoffNNj.js} +2 -2
- package/dist/{expand-D9LzmpoV.js.map → expand-CtoffNNj.js.map} +1 -1
- package/dist/expand.cjs +1 -1
- package/dist/expand.js +1 -1
- package/dist/{float-2nHYuBx-.cjs → float-B8NcSE3a.cjs} +1 -1
- package/dist/{float-2nHYuBx-.cjs.map → float-B8NcSE3a.cjs.map} +1 -1
- package/dist/{float-BWy39CXr.js → float-C-glc-3u.js} +1 -1
- package/dist/{float-BWy39CXr.js.map → float-C-glc-3u.js.map} +1 -1
- package/dist/float.cjs +1 -1
- package/dist/float.js +1 -1
- package/dist/{form-DhjedCWm.js → form-DJvxIyfW.js} +10 -1
- package/dist/{form-DhjedCWm.js.map → form-DJvxIyfW.js.map} +1 -1
- package/dist/form-St_IwR7y.cjs +42 -0
- package/dist/{form-g5c70rac.cjs.map → form-St_IwR7y.cjs.map} +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.js +9 -2
- package/dist/handover/agent-runtime-followups.md +1 -1
- package/dist/handover/agent-runtime-v1.md +3 -3
- package/dist/hashContent-dJrI-9sc.js.map +1 -1
- package/dist/{icons-1HIENBco.cjs → icons-BJld4JHp.cjs} +1 -1
- package/dist/{icons-1HIENBco.cjs.map → icons-BJld4JHp.cjs.map} +1 -1
- package/dist/{icons-3y0kr1aB.js → icons-D7df1ysG.js} +1 -1
- package/dist/{icons-3y0kr1aB.js.map → icons-D7df1ysG.js.map} +1 -1
- package/dist/icons.cjs +1 -1
- package/dist/icons.js +1 -1
- package/dist/{iframe-Z5gTK-gd.js → iframe-DAbgW9tT.js} +1 -1
- package/dist/{iframe-Z5gTK-gd.js.map → iframe-DAbgW9tT.js.map} +1 -1
- package/dist/{iframe-CjqYuZG5.cjs → iframe-GT6D8l5Z.cjs} +1 -1
- package/dist/{iframe-CjqYuZG5.cjs.map → iframe-GT6D8l5Z.cjs.map} +1 -1
- package/dist/iframe.cjs +1 -1
- package/dist/iframe.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +45 -45
- package/dist/{input-BtcIhu0Q.cjs → input-BE9wEEw4.cjs} +1 -1
- package/dist/{input-BtcIhu0Q.cjs.map → input-BE9wEEw4.cjs.map} +1 -1
- package/dist/{input-B-fw6f_r.js → input-DC6ap_uN.js} +1 -1
- package/dist/{input-B-fw6f_r.js.map → input-DC6ap_uN.js.map} +1 -1
- package/dist/{input-chip-DZktYohr.cjs → input-chip-MsiMu-b5.cjs} +4 -4
- package/dist/input-chip-MsiMu-b5.cjs.map +1 -0
- package/dist/{input-chip-CtQ0pH5b.js → input-chip-c5n547tg.js} +3 -6
- package/dist/input-chip-c5n547tg.js.map +1 -0
- package/dist/input.cjs +1 -1
- package/dist/input.js +1 -1
- package/dist/json.cjs +1 -1
- package/dist/json.js +2 -2
- package/dist/json.js.map +1 -1
- package/dist/kbd.cjs +1 -1
- package/dist/kbd.js +1 -1
- package/dist/kbd.js.map +1 -1
- package/dist/layout-BH28sKGc.js.map +1 -1
- package/dist/layout.cjs +1 -1
- package/dist/layout.js +1 -1
- package/dist/lazy-D-bO2r4m.js.map +1 -1
- package/dist/{lightbox-BL3LWp-P.js → lightbox-CNX9Eg3U.js} +4 -4
- package/dist/lightbox-CNX9Eg3U.js.map +1 -0
- package/dist/{lightbox-BHTZOn8K.cjs → lightbox-HqJBBjAT.cjs} +4 -4
- package/dist/lightbox-HqJBBjAT.cjs.map +1 -0
- package/dist/lightbox.cjs +1 -1
- package/dist/lightbox.js +1 -1
- package/dist/{list-DLJL1JQj.js → list-C76Pb-c1.js} +1 -1
- package/dist/{list-DLJL1JQj.js.map → list-C76Pb-c1.js.map} +1 -1
- package/dist/{list-CHYa5VGY.cjs → list-bhyuQSyO.cjs} +1 -1
- package/dist/{list-CHYa5VGY.cjs.map → list-bhyuQSyO.cjs.map} +1 -1
- package/dist/list.cjs +1 -1
- package/dist/list.js +1 -1
- package/dist/magnetic-DxvoEz8_.js.map +1 -1
- package/dist/{menu-BNq93w6X.js → menu-B_-weNpZ.js} +2 -2
- package/dist/{menu-BNq93w6X.js.map → menu-B_-weNpZ.js.map} +1 -1
- package/dist/{menu-DAikvkeV.cjs → menu-Dag0cuWV.cjs} +1 -1
- package/dist/{menu-DAikvkeV.cjs.map → menu-Dag0cuWV.cjs.map} +1 -1
- package/dist/menu.cjs +1 -1
- package/dist/menu.js +1 -1
- package/dist/mixins-DCVXqL1Q.js +636 -0
- package/dist/{mixins-BWb9_e1s.js.map → mixins-DCVXqL1Q.js.map} +1 -1
- package/dist/mixins-Du9HMrIG.cjs +254 -0
- package/dist/{mixins-BOOu6q2n.cjs.map → mixins-Du9HMrIG.cjs.map} +1 -1
- package/dist/mixins.cjs +1 -1
- package/dist/mixins.js +1 -1
- package/dist/nav-drawer.cjs +1 -1
- package/dist/nav-drawer.js +1 -1
- package/dist/navigation-bar.cjs +1 -1
- package/dist/navigation-bar.js +1 -1
- package/dist/navigation-rail.cjs +1 -1
- package/dist/navigation-rail.js +1 -1
- package/dist/navigation-rail.js.map +1 -1
- package/dist/{notification-CUmb9c3Y.js → notification-DySnvQeO.js} +3 -3
- package/dist/notification-DySnvQeO.js.map +1 -0
- package/dist/{notification-Dy2azMyt.cjs → notification-yd2KeHjd.cjs} +1 -1
- package/dist/notification-yd2KeHjd.cjs.map +1 -0
- package/dist/notification.cjs +1 -1
- package/dist/notification.js +1 -1
- package/dist/{option-CDgIKifG.cjs → option-BDOKUqTy.cjs} +1 -1
- package/dist/{option-CDgIKifG.cjs.map → option-BDOKUqTy.cjs.map} +1 -1
- package/dist/{option-DFvQ551b.js → option-CBEHYG4U.js} +1 -1
- package/dist/{option-DFvQ551b.js.map → option-CBEHYG4U.js.map} +1 -1
- package/dist/option.cjs +1 -1
- package/dist/option.js +1 -1
- package/dist/overlay-stack-BR4iYivO.js.map +1 -1
- package/dist/overlay.cjs +1 -1
- package/dist/overlay.cjs.map +1 -1
- package/dist/{overlay.confirm-body-uFp-0Zfh.js → overlay.confirm-body-DESGpbru.js} +2 -2
- package/dist/{overlay.confirm-body-uFp-0Zfh.js.map → overlay.confirm-body-DESGpbru.js.map} +1 -1
- package/dist/{overlay.confirm-body-BkhNvr0c.cjs → overlay.confirm-body-sUmd_zVy.cjs} +2 -2
- package/dist/{overlay.confirm-body-BkhNvr0c.cjs.map → overlay.confirm-body-sUmd_zVy.cjs.map} +1 -1
- package/dist/overlay.js +3 -3
- package/dist/overlay.js.map +1 -1
- package/dist/{overlay.service-1YWfUD2S.cjs → overlay.service-BxtEFFSH.cjs} +1 -1
- package/dist/{overlay.service-1YWfUD2S.cjs.map → overlay.service-BxtEFFSH.cjs.map} +1 -1
- package/dist/{overlay.service-BcF12kGb.js → overlay.service-DV_o_xQ0.js} +2 -2
- package/dist/{overlay.service-BcF12kGb.js.map → overlay.service-DV_o_xQ0.js.map} +1 -1
- package/dist/page.cjs +1 -1
- package/dist/page.js +2 -2
- package/dist/page.js.map +1 -1
- package/dist/{progress-bLbGRuQ1.js → progress-C4kDZfb7.js} +1 -1
- package/dist/{progress-bLbGRuQ1.js.map → progress-C4kDZfb7.js.map} +1 -1
- package/dist/{progress-C02sWkmE.cjs → progress-CMSst_2U.cjs} +1 -1
- package/dist/{progress-C02sWkmE.cjs.map → progress-CMSst_2U.cjs.map} +1 -1
- package/dist/progress.cjs +1 -1
- package/dist/progress.js +1 -1
- package/dist/{radio-group-DA4eIGCj.js → radio-group-DB9D2ZkA.js} +1 -1
- package/dist/{radio-group-DA4eIGCj.js.map → radio-group-DB9D2ZkA.js.map} +1 -1
- package/dist/{radio-group-BA-jRct5.cjs → radio-group-dVUvYFq7.cjs} +1 -1
- package/dist/{radio-group-BA-jRct5.cjs.map → radio-group-dVUvYFq7.cjs.map} +1 -1
- package/dist/radio-group.cjs +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/range.cjs +1 -1
- package/dist/range.js +1 -1
- package/dist/range.js.map +1 -1
- package/dist/reduced-motion-D7LqTUMn.js.map +1 -1
- package/dist/{rxjs-utils-kWPShgKu.cjs.map → rxjs-utils-BKB2UM_j.cjs.map} +1 -1
- package/dist/{rxjs-utils-D9U4MW0Q.js.map → rxjs-utils-Dv9T9IpA.js.map} +1 -1
- package/dist/rxjs-utils.cjs +1 -1
- package/dist/rxjs-utils.js +1 -1
- package/dist/{scroll-CG5up5oy.js → scroll-C1klVgSQ.js} +1 -1
- package/dist/{scroll-CG5up5oy.js.map → scroll-C1klVgSQ.js.map} +1 -1
- package/dist/{scroll-D8vBF_gY.cjs → scroll-S-bXF2u6.cjs} +1 -1
- package/dist/{scroll-D8vBF_gY.cjs.map → scroll-S-bXF2u6.cjs.map} +1 -1
- package/dist/search-MvIBA93K.js.map +1 -1
- package/dist/{select-BrK1BJoU.js → select-UU2pB67h.js} +2 -2
- package/dist/{select-BrK1BJoU.js.map → select-UU2pB67h.js.map} +1 -1
- package/dist/{select-Dh2j7Qc-.cjs → select-fu_-rZyn.cjs} +1 -1
- package/dist/{select-Dh2j7Qc-.cjs.map → select-fu_-rZyn.cjs.map} +1 -1
- package/dist/select.cjs +1 -1
- package/dist/select.js +1 -1
- package/dist/skeleton.cjs +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/skeleton.js.map +1 -1
- package/dist/skills/SKILL.md +3 -0
- package/dist/skills/schmancy/SKILL.md +3 -0
- package/dist/slider.cjs +1 -1
- package/dist/slider.js +1 -1
- package/dist/slider.js.map +1 -1
- package/dist/sound.service-BIN2W7Rv.js.map +1 -1
- package/dist/{splash-screen-Kr1sPtME.cjs → splash-screen-25PTDqnp.cjs} +1 -1
- package/dist/{splash-screen-Kr1sPtME.cjs.map → splash-screen-25PTDqnp.cjs.map} +1 -1
- package/dist/{splash-screen-BcjjJSlK.js → splash-screen-bGW_sS4i.js} +1 -1
- package/dist/{splash-screen-BcjjJSlK.js.map → splash-screen-bGW_sS4i.js.map} +1 -1
- package/dist/splash-screen.cjs +1 -1
- package/dist/splash-screen.js +1 -1
- package/dist/{src-B2-CU8fu.cjs → src-Blm9PNcf.cjs} +1 -1
- package/dist/{src-B2-CU8fu.cjs.map → src-Blm9PNcf.cjs.map} +1 -1
- package/dist/{src-DvywUq7l.js → src-olrlFt4e.js} +35 -35
- package/dist/{src-DvywUq7l.js.map → src-olrlFt4e.js.map} +1 -1
- package/dist/state-avic94Ft.cjs.map +1 -1
- package/dist/state-nm8yzMPp.js.map +1 -1
- package/dist/steps.cjs +1 -1
- package/dist/steps.js +1 -1
- package/dist/steps.js.map +1 -1
- package/dist/{surface-BtMMHKol.js → surface-DCRy-EyT.js} +1 -1
- package/dist/{surface-BtMMHKol.js.map → surface-DCRy-EyT.js.map} +1 -1
- package/dist/{surface-CgXeKdGL.cjs → surface-DWwQDX9r.cjs} +1 -1
- package/dist/{surface-CgXeKdGL.cjs.map → surface-DWwQDX9r.cjs.map} +1 -1
- package/dist/surface.cjs +1 -1
- package/dist/surface.js +1 -1
- package/dist/switch.cjs +1 -1
- package/dist/switch.js +1 -1
- package/dist/switch.js.map +1 -1
- package/dist/table.cjs +1 -1
- package/dist/table.js +1 -1
- package/dist/table.js.map +1 -1
- package/dist/{tabs-CikPr7by.js → tabs-BVC_qn8S.js} +1 -1
- package/dist/{tabs-CikPr7by.js.map → tabs-BVC_qn8S.js.map} +1 -1
- package/dist/{tabs-CitVls3_.cjs → tabs-Dc3_Ox2B.cjs} +1 -1
- package/dist/{tabs-CitVls3_.cjs.map → tabs-Dc3_Ox2B.cjs.map} +1 -1
- package/dist/tabs.cjs +1 -1
- package/dist/tabs.js +1 -1
- package/dist/teleport.cjs +1 -1
- package/dist/teleport.js +1 -1
- package/dist/{textarea-CqV1wvmB.cjs → textarea-CNa4dSvF.cjs} +1 -1
- package/dist/{textarea-CqV1wvmB.cjs.map → textarea-CNa4dSvF.cjs.map} +1 -1
- package/dist/{textarea-DVkwQSis.js → textarea-DkfGmRSI.js} +1 -1
- package/dist/{textarea-DVkwQSis.js.map → textarea-DkfGmRSI.js.map} +1 -1
- package/dist/textarea.cjs +1 -1
- package/dist/textarea.js +1 -1
- package/dist/{theme-BIWS4TOW.js → theme-BiCwFfCf.js} +2 -2
- package/dist/{theme-BIWS4TOW.js.map → theme-BiCwFfCf.js.map} +1 -1
- package/dist/{theme-DMgjiKda.cjs → theme-DCybsrfv.cjs} +1 -1
- package/dist/{theme-DMgjiKda.cjs.map → theme-DCybsrfv.cjs.map} +1 -1
- package/dist/{theme-button-DC_shZ_7.js → theme-button-DqiA0rJg.js} +1 -1
- package/dist/{theme-button-DC_shZ_7.js.map → theme-button-DqiA0rJg.js.map} +1 -1
- package/dist/{theme-button-ENKa3TPT.cjs → theme-button-cZGRyQRK.cjs} +1 -1
- package/dist/{theme-button-ENKa3TPT.cjs.map → theme-button-cZGRyQRK.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-C8OHheXg.js.map → theme.interface-C2XNgsLB.js.map} +1 -1
- package/dist/{theme.interface-CYo4UpWK.cjs.map → theme.interface-D4NeufQA.cjs.map} +1 -1
- package/dist/theme.js +3 -3
- package/dist/theme.service-BOWIT_5k.js.map +1 -1
- package/dist/tooltip.js.map +1 -1
- package/dist/tree.cjs +1 -1
- package/dist/tree.js +1 -1
- package/dist/tree.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/typewriter.cjs.map +1 -1
- package/dist/typewriter.js.map +1 -1
- package/dist/typography.cjs +1 -1
- package/dist/typography.js +1 -1
- package/dist/typography.js.map +1 -1
- package/dist/utils-Cj_nRRyx.js.map +1 -1
- package/dist/visually-hidden.cjs +1 -1
- package/dist/visually-hidden.js +1 -1
- package/dist/visually-hidden.js.map +1 -1
- package/dist/{window-DGydMS0g.cjs → window-BMecbTzs.cjs} +3 -3
- package/dist/window-BMecbTzs.cjs.map +1 -0
- package/dist/{window-BTecgE_U.js → window-DMy5Gsgu.js} +3 -10
- package/dist/window-DMy5Gsgu.js.map +1 -0
- package/dist/window.cjs +1 -1
- package/dist/window.js +1 -1
- package/package.json +1 -1
- package/skills/schmancy/SKILL.md +3 -0
- package/src/boat/boat.ts +0 -3
- package/src/breadcrumb/breadcrumb.ts +1 -0
- package/src/button/button.ts +1 -1
- package/src/button/icon-button.ts +2 -1
- package/src/chips/assist-chip.ts +2 -1
- package/src/chips/filter-chip.ts +2 -16
- package/src/chips/input-chip.ts +2 -5
- package/src/chips/suggestion-chip.ts +2 -3
- package/src/details/details.ts +2 -7
- package/src/form/fields/index.ts +9 -0
- package/src/form/index.ts +1 -0
- package/src/lightbox/lightbox.ts +3 -3
- package/src/notification/notification.scss +0 -1
- package/src/overlay/overlay.confirm-body.ts +1 -1
- package/src/surface/surface.styles.ts +1 -45
- package/src/window/window.ts +0 -12
- package/types/src/form/fields/index.d.ts +9 -0
- package/types/src/form/index.d.ts +1 -0
- package/types/src/window/window.d.ts +0 -2
- package/dist/chips-CfPFXv7Z.js.map +0 -1
- package/dist/chips-DK6m-VCM.cjs.map +0 -1
- package/dist/details-BdAVsLl-.cjs.map +0 -1
- package/dist/details-CS_ToAOj.js.map +0 -1
- package/dist/form-g5c70rac.cjs +0 -42
- package/dist/input-chip-CtQ0pH5b.js.map +0 -1
- package/dist/input-chip-DZktYohr.cjs.map +0 -1
- package/dist/lightbox-BHTZOn8K.cjs.map +0 -1
- package/dist/lightbox-BL3LWp-P.js.map +0 -1
- package/dist/mixins-BOOu6q2n.cjs +0 -298
- package/dist/mixins-BWb9_e1s.js +0 -680
- package/dist/notification-CUmb9c3Y.js.map +0 -1
- package/dist/notification-Dy2azMyt.cjs.map +0 -1
- package/dist/window-BTecgE_U.js.map +0 -1
- package/dist/window-DGydMS0g.cjs.map +0 -1
- /package/dist/{rxjs-utils-kWPShgKu.cjs → rxjs-utils-BKB2UM_j.cjs} +0 -0
- /package/dist/{rxjs-utils-D9U4MW0Q.js → rxjs-utils-Dv9T9IpA.js} +0 -0
- /package/dist/{theme.interface-C8OHheXg.js → theme.interface-C2XNgsLB.js} +0 -0
- /package/dist/{theme.interface-CYo4UpWK.cjs → theme.interface-D4NeufQA.cjs} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require(`./chunk-CncqDLb2.cjs`);const e=require(`./mixins-
|
|
1
|
+
require(`./chunk-CncqDLb2.cjs`);const e=require(`./mixins-Du9HMrIG.cjs`),t=require(`./active-host-jH3iloCR.cjs`),n=require(`./search-DPKoC-dT.cjs`);require(`./input-chip-MsiMu-b5.cjs`);let r=require(`rxjs`),i=require(`rxjs/operators`),a=require(`lit/directives/class-map.js`),o=require(`lit/decorators.js`),s=require(`lit`),c=require(`lit/directives/if-defined.js`),l=require(`lit/directives/ref.js`),u=require(`lit/directives/repeat.js`),d=require(`lit/directives/when.js`);var f=class extends e.o((0,s.unsafeCSS)(`:host{display:block;border:unset!important;line-height:unset!important;background:unset!important;padding:unset!important;font-size:unset!important;box-shadow:unset!important}:host:focus{box-shadow:unset!important}@keyframes onAutoFillStart{0%{}to{}}:-webkit-any(sch-input::part(input):-webkit-autofill,sch-input input:-webkit-autofill){animation-name:onAutoFillStart;animation-duration:1ms}:is(sch-input::part(input):autofill,sch-input input:autofill){animation-name:onAutoFillStart;animation-duration:1ms}`)){constructor(...e){super(...e),this._valueSet=!1,this._valuesSet=!1,this.placeholder=``,this.maxHeight=`300px`,this.multi=!1,this.description=``,this.size=`md`,this.autocomplete=`off`,this.debounceMs=200,this.similarityThreshold=.3,this._a11yId=`schmancy-autocomplete-${Math.random().toString(36).slice(2,10)}`,this._open=!1,this._inputValue=``,this._visibleOptionsCount=0,this._hasResults=!0,this._inputElementRef=(0,l.createRef)(),this._selectedValue$=new r.BehaviorSubject(``),this._selectedValues$=new r.BehaviorSubject([]),this._inputValue$=new r.BehaviorSubject(``)}resetForm(){this.multi?this._selectedValues$.next([]):this._selectedValue$.next(``),this._inputValue=``,this._inputValue$.next(``),super.resetForm()}get values(){return[...this._selectedValues$.value]}set values(e){this._valuesSet=!0,this._selectedValues$.next(Array.isArray(e)?[...e]:[])}get value(){return this.multi?this._selectedValues$.value.join(`,`):this._selectedValue$.value}set value(e){if(this._valueSet=!0,this.multi){let t=e?e.split(`,`).map(e=>e.trim()).filter(Boolean):[],n=this._selectedValues$.value;JSON.stringify(t)!==JSON.stringify(n)&&this._selectedValues$.next(t)}else e!==this._selectedValue$.value&&(this._selectedValue$.next(e),this._updateInputDisplay())}connectedCallback(){super.connectedCallback(),this._setupAutocompleteLogic(),this._setupDocumentClickHandler()}_setupAutocompleteLogic(){(0,r.combineLatest)([this._selectedValue$,this._selectedValues$]).pipe((0,i.tap)(([e,t])=>{this._updateOptionSelection(e,t);let n=this.multi?t.join(`,`):e;if(this.internals?.setFormValue(n||null),this.required){let n=this.multi?t.length===0:!e;this.internals?.setValidity(n?{valueMissing:!0}:{},n?this.validationMessage||`Please select an option.`:void 0)}}),(0,i.takeUntil)(this.disconnecting)).subscribe(),this._inputValue$.pipe((0,i.distinctUntilChanged)(),(0,i.debounceTime)(this.debounceMs),(0,i.tap)(e=>{this._open&&this._filterOptions(e)}),(0,i.takeUntil)(this.disconnecting)).subscribe()}_setupOptionHandlers(){this._options.forEach((e,t)=>{e.setAttribute(`role`,`option`),e.tabIndex=-1,e.id||=`${this.id}-option-${t}`,e.dataset.schmancyAutocompleteHandlers!==`attached`&&(e.dataset.schmancyAutocompleteHandlers=`attached`,(0,r.fromEvent)(e,`mousedown`).pipe((0,i.takeUntil)(this.disconnecting)).subscribe(e=>e.preventDefault()),(0,r.fromEvent)(e,`click`).pipe((0,i.takeUntil)(this.disconnecting)).subscribe(t=>{t.stopPropagation(),this._selectOption(e)}))})}_updateOptionSelection(e,t){this._options.forEach(n=>{n.selected=this.multi?t.includes(n.value):n.value===e,n.setAttribute(`aria-selected`,String(n.selected))})}_filterOptions(e){let t=e.trim();if(t){let e=this._options.map(e=>{let r=e.label||e.textContent||``,i=e.value,a=n.t(t,r),o=n.t(t,i);return{option:e,score:Math.max(1.1*a,o)}});e.sort((e,t)=>t.score-e.score);let r=0;e.forEach((e,t)=>{let{option:n,score:i}=e;i<this.similarityThreshold?n.hidden=!0:(n.hidden=!1,r++,n.style.order=String(t))}),this._visibleOptionsCount=r,this._hasResults=r>0}else this._options.forEach(e=>{e.hidden=!1,e.style.order=`0`}),this._visibleOptionsCount=this._options.length,this._hasResults=!0;this._announceToScreenReader(this._visibleOptionsCount>0?`${this._visibleOptionsCount} option${this._visibleOptionsCount===1?``:`s`} available.`:`No results found.`)}_openDropdown(){this._open=!0,this._filterOptions(this._inputValue)}_selectOption(e){if(this.multi){let t=this._selectedValues$.value,n=t.indexOf(e.value)>-1?t.filter(t=>t!==e.value):[...t,e.value];this._selectedValues$.next(n),this._announceToScreenReader(n.length>0?`Selected: ${this._getSelectedLabels().join(`, `)}`:`No options selected`),this._fireChangeEvent()}else this._selectedValue$.next(e.value),this._open=!1,this._fireChangeEvent(),this._inputValue=e.label||e.textContent||``,this._inputValue$.next(this._inputValue),this._announceToScreenReader(`Selected: ${e.label||e.textContent}`)}_setupDocumentClickHandler(){(0,r.fromEvent)(document,`click`).pipe((0,i.takeUntil)(this.disconnecting)).subscribe(e=>{if(!this._open)return;let t=e.composedPath();t.includes(this)||this._options.some(e=>t.includes(e))||(this._open=!1,this._updateInputDisplay())})}_updateInputDisplay(){if(this.multi)return;let e=this._selectedValue$.value,t=this._options.find(t=>t.value===e);this._inputValue=t&&(t.label||t.textContent)||``,this._inputValue$.next(this._inputValue),this._inputElementRef.value&&(this._inputElementRef.value.value=this._inputValue)}_getSelectedLabels(){return this._options.filter(e=>this.multi?this._selectedValues$.value.includes(e.value):e.value===this._selectedValue$.value).map(e=>e.label||e.textContent||``)}_announceToScreenReader(e){let t=this.shadowRoot?.querySelector(`#live-status`);t&&(t.textContent=e)}_fireChangeEvent(){let e={value:this.value};this.multi&&(e.values=[...this._selectedValues$.value]),this.dispatchEvent(new CustomEvent(`change`,{detail:e,bubbles:!0,composed:!0}))}checkValidity(){return!this.required||(this.multi?this._selectedValues$.value.length>0:!!this._selectedValue$.value)}reportValidity(){return this._inputElementRef.value?this._inputElementRef.value.reportValidity():this.checkValidity()}firstUpdated(){this._setupOptionHandlers(),this._updateInputDisplay(),(this.shadowRoot?.querySelector(`slot`))?.addEventListener(`slotchange`,()=>{this._setupOptionHandlers(),this._updateOptionSelection(this._selectedValue$.value,this._selectedValues$.value)})}handleChipRemove(e){let t=this._selectedValues$.value.filter(t=>t!==e);this._selectedValues$.next(t),this._fireChangeEvent(),this._announceToScreenReader(`Removed: ${this._getChipLabel(e)}`)}_getChipLabel(e){let t=this._options.find(t=>t.value===e);return t&&(t.label||t.textContent)||e}_focusTextInput(){this._inputElementRef.value&&this._inputElementRef.value.focus()}render(){let e=`${this.id}-desc`,{height:t,padding:n,fontSize:r,labelSize:i}=(()=>{switch(this.size){case`sm`:return{height:`min-h-[40px]`,padding:`px-2`,fontSize:`text-sm`,labelSize:`text-sm`};case`lg`:return{height:`min-h-[60px]`,padding:`px-5`,fontSize:`text-lg`,labelSize:`text-lg`};default:return{height:`min-h-[50px]`,padding:`px-4`,fontSize:`text-base`,labelSize:`text-base`}}})();return s.html`
|
|
2
2
|
<div class="relative">
|
|
3
3
|
<!-- Screen reader live region -->
|
|
4
4
|
<div id="live-status" role="status" aria-live="polite" class="sr-only"></div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete-Ck2zbdF9.cjs","names":[],"sources":["../src/form/fields/autocomplete/autocomplete.scss?inline","../src/form/fields/autocomplete/autocomplete.ts"],"sourcesContent":[":host {\n\tdisplay: block;\n\tborder: unset !important;\n\tline-height: unset !important;\n\tbackground: unset !important;\n\tpadding: unset !important;\n\tfont-size: unset !important;\n\tbox-shadow: unset !important;\n}\n\n:host:focus {\n\tbox-shadow: unset !important;\n}\n\n@keyframes onAutoFillStart {\n\tfrom {/**/}\n\tto {/**/}\n}\n\nsch-input::part(input):-webkit-autofill,\nsch-input input:-webkit-autofill {\n\tanimation-name: onAutoFillStart;\n\tanimation-duration: 1ms;\n}\n","import { SchmancyFormField } from '@mixins/index'\nimport { InputSize, SchmancyInput } from '@schmancy/input'\nimport SchmancyOption from '@schmancy/option/option'\nimport { html, nothing, unsafeCSS } from 'lit'\nimport { customElement, property, query, queryAssignedElements, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { when } from 'lit/directives/when.js'\nimport {\n BehaviorSubject,\n combineLatest,\n fromEvent,\n timer\n} from 'rxjs'\nimport {\n debounceTime,\n distinctUntilChanged,\n takeUntil,\n tap\n} from 'rxjs/operators'\nimport style from './autocomplete.scss?inline'\n\n// Import the similarity function (or include it inline)\nimport { similarity } from '../../../utils/search'\n// Import chip component for multi-select display\nimport '../../../chips/input-chip'\n\nexport type SchmancyAutocompleteChangeEvent = CustomEvent<{\n value: string | string[]\n values?: string[]\n}>\n\ninterface FilteredOption {\n option: SchmancyOption\n score: number\n}\n\n/**\n * Autocomplete input component with filtering and multi-select support.\n *\n * @prop {string} name - Name attribute for form submission\n * @prop {string} label - Label text displayed above the input\n * @prop {string} placeholder - Placeholder text for the input\n * @prop {boolean} required - Whether the field is required\n * @prop {boolean} multi - Enable multi-select mode\n * @prop {string} value - Selected value (single select mode)\n * @prop {string[]} values - Selected values (multi-select mode)\n */\n@customElement('schmancy-autocomplete')\nexport default class SchmancyAutocomplete extends SchmancyFormField(unsafeCSS(style)) {\n\n // `formAssociated`, `internals`, `attachInternals`, `name`, `label`,\n // `required`, `disabled`, `error`, `validationMessage`, `hint`, `id`,\n // `validateOn`, `touched/dirty/submitted`, `markTouched/markSubmitted`,\n // `setCustomValidity`, `formDisabledCallback`, FIELD_CONNECT_EVENT dispatch\n // — all from the mixin.\n\n /** Override mixin's resetForm with autocomplete-specific subject reset. */\n override resetForm(): void {\n if (this.multi) {\n this._selectedValues$.next([])\n } else {\n this._selectedValue$.next('')\n }\n this._inputValue = ''\n this._inputValue$.next('')\n super.resetForm()\n }\n\n // Track whether value/values have been explicitly set\n _valueSet: boolean = false\n _valuesSet: boolean = false\n\n // Autocomplete-specific properties only — `name`, `label`, `required`,\n // `error`, `validationMessage` come from the mixin.\n @property({ type: String }) placeholder = ''\n @property({ type: String }) maxHeight = '300px'\n @property({ type: Boolean }) multi = false\n @property({ type: String }) description = ''\n @property({ type: String, reflect: true }) size: InputSize = 'md'\n @property({ type: String }) autocomplete = 'off'\n @property({ type: Number }) debounceMs = 200\n @property({ type: Number }) similarityThreshold = 0.3 // Minimum similarity score to show option\n\n private readonly _a11yId = `schmancy-autocomplete-${Math.random().toString(36).slice(2, 10)}`\n\n // Values property for multi-select mode\n @property({ type: Array })\n get values() {\n return [...this._selectedValues$.value]\n }\n set values(vals: string[]) {\n this._valuesSet = true\n this._selectedValues$.next(Array.isArray(vals) ? [...vals] : [])\n }\n\n // Value property — narrowed override of the mixin's wide value union.\n @property({ type: String, reflect: true })\n override get value(): string {\n return this.multi\n ? this._selectedValues$.value.join(',')\n : this._selectedValue$.value\n }\n override set value(val: string) {\n this._valueSet = true\n if (this.multi) {\n const newValues = val ? val.split(',').map(v => v.trim()).filter(Boolean) : []\n const currentValues = this._selectedValues$.value\n // Only update if values actually changed\n if (JSON.stringify(newValues) !== JSON.stringify(currentValues)) {\n this._selectedValues$.next(newValues)\n }\n } else {\n // Only update if value actually changed\n if (val !== this._selectedValue$.value) {\n this._selectedValue$.next(val)\n // Update the input display when value is set\n this._updateInputDisplay()\n }\n }\n }\n\n // State\n @state() private _open = false\n @state() private _inputValue = ''\n @state() private _visibleOptionsCount = 0\n @state() private _hasResults = true\n\n // DOM references\n @query('#options') _listbox!: HTMLUListElement\n @query('sch-input') _input!: SchmancyInput\n @queryAssignedElements({ flatten: true }) private _options!: SchmancyOption[]\n private _inputElementRef = createRef<HTMLInputElement>()\n\n // RxJS Subjects - only what we actually need\n private _selectedValue$ = new BehaviorSubject<string>('')\n private _selectedValues$ = new BehaviorSubject<string[]>([])\n private _inputValue$ = new BehaviorSubject<string>('')\n\n override connectedCallback() {\n // FIELD_CONNECT_EVENT is dispatched by the mixin's connectedCallback.\n super.connectedCallback()\n this._setupAutocompleteLogic()\n this._setupDocumentClickHandler()\n }\n\n private _setupAutocompleteLogic() {\n // Sync selection state\n combineLatest([\n this._selectedValue$,\n this._selectedValues$\n ]).pipe(\n tap(([selectedValue, selectedValues]) => {\n this._updateOptionSelection(selectedValue, selectedValues)\n // Keep ElementInternals form value in sync with selection (single and multi).\n const formValue = this.multi ? selectedValues.join(',') : selectedValue\n this.internals?.setFormValue(formValue || null)\n if (this.required) {\n const missing = this.multi ? selectedValues.length === 0 : !selectedValue\n this.internals?.setValidity(\n missing ? { valueMissing: true } : {},\n missing ? this.validationMessage || 'Please select an option.' : undefined,\n )\n }\n }),\n takeUntil(this.disconnecting)\n ).subscribe()\n\n // Filter options based on input\n this._inputValue$.pipe(\n distinctUntilChanged(),\n debounceTime(this.debounceMs),\n tap(searchTerm => {\n if (this._open) {\n this._filterOptions(searchTerm)\n }\n }),\n takeUntil(this.disconnecting)\n ).subscribe()\n }\n\n private _setupOptionHandlers() {\n this._options.forEach((option, index) => {\n option.setAttribute('role', 'option')\n option.tabIndex = -1\n if (!option.id) {\n option.id = `${this.id}-option-${index}`\n }\n // Idempotent: slotchange may fire repeatedly for the same option nodes,\n // and addEventListener doesn't replace prior handlers like onfoo= did.\n if (option.dataset.schmancyAutocompleteHandlers === 'attached') return\n option.dataset.schmancyAutocompleteHandlers = 'attached'\n\n // Prevent blur handler from interfering with option selection\n fromEvent<MouseEvent>(option, 'mousedown')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => e.preventDefault())\n\n // Handle the actual selection\n fromEvent<MouseEvent>(option, 'click')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => {\n e.stopPropagation()\n this._selectOption(option)\n })\n })\n }\n\n private _updateOptionSelection(selectedValue: string, selectedValues: string[]) {\n this._options.forEach(option => {\n option.selected = this.multi\n ? selectedValues.includes(option.value)\n : option.value === selectedValue\n option.setAttribute('aria-selected', String(option.selected))\n })\n }\n\n private _filterOptions(searchTerm: string) {\n const term = searchTerm.trim()\n\n if (!term) {\n // Show all options if no search term\n this._options.forEach(option => {\n option.hidden = false\n option.style.order = '0'\n })\n this._visibleOptionsCount = this._options.length\n this._hasResults = true\n } else {\n // Calculate similarity scores for all options\n const scoredOptions: FilteredOption[] = this._options.map(option => {\n const optionLabel = option.label || option.textContent || ''\n const optionValue = option.value\n\n const labelScore = similarity(term, optionLabel)\n const valueScore = similarity(term, optionValue)\n const score = Math.max(labelScore * 1.1, valueScore)\n\n return { option, score }\n })\n\n // Sort by score (highest first)\n scoredOptions.sort((a, b) => b.score - a.score)\n\n // Apply visibility and ordering\n let visibleCount = 0\n scoredOptions.forEach((item, index) => {\n const { option, score } = item\n\n if (score < this.similarityThreshold) {\n option.hidden = true\n } else {\n option.hidden = false\n visibleCount++\n option.style.order = String(index)\n }\n })\n\n this._visibleOptionsCount = visibleCount\n this._hasResults = visibleCount > 0\n }\n\n this._announceToScreenReader(\n this._visibleOptionsCount > 0\n ? `${this._visibleOptionsCount} option${this._visibleOptionsCount === 1 ? '' : 's'} available.`\n : 'No results found.'\n )\n }\n\n private _openDropdown() {\n this._open = true\n // Reset filters based on current input value when dropdown opens\n this._filterOptions(this._inputValue)\n }\n\n private _selectOption(option: SchmancyOption) {\n if (this.multi) {\n const currentValues = this._selectedValues$.value\n const index = currentValues.indexOf(option.value)\n const newValues = index > -1\n ? currentValues.filter(v => v !== option.value)\n : [...currentValues, option.value]\n\n this._selectedValues$.next(newValues)\n this._announceToScreenReader(\n newValues.length > 0\n ? `Selected: ${this._getSelectedLabels().join(', ')}`\n : 'No options selected'\n )\n this._fireChangeEvent()\n } else {\n // Update value first\n this._selectedValue$.next(option.value)\n\n // Close dropdown IMMEDIATELY to prevent blur handler from firing\n this._open = false\n\n // Now fire event with the NEW value\n this._fireChangeEvent()\n\n // Update UI\n this._inputValue = option.label || option.textContent || ''\n this._inputValue$.next(this._inputValue)\n\n this._announceToScreenReader(`Selected: ${option.label || option.textContent}`)\n }\n }\n\n private _setupDocumentClickHandler() {\n fromEvent<MouseEvent>(document, 'click')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => {\n if (!this._open) return\n const path = e.composedPath()\n if (!path.includes(this) && !this._options.some(opt => path.includes(opt))) {\n this._open = false\n this._updateInputDisplay()\n }\n })\n }\n\n\n private _updateInputDisplay() {\n // For multi-select, we don't update input display since chips show the selections\n if (this.multi) return\n\n const selectedValue = this._selectedValue$.value\n const option = this._options.find(opt => opt.value === selectedValue)\n this._inputValue = option ? option.label || option.textContent || '' : ''\n this._inputValue$.next(this._inputValue)\n\n if (this._inputElementRef.value) {\n this._inputElementRef.value.value = this._inputValue\n }\n }\n\n private _getSelectedLabels(): string[] {\n return this._options\n .filter(option => \n this.multi \n ? this._selectedValues$.value.includes(option.value)\n : option.value === this._selectedValue$.value\n )\n .map(option => option.label || option.textContent || '')\n }\n\n private _announceToScreenReader(message: string) {\n const liveRegion = this.shadowRoot?.querySelector('#live-status')\n if (liveRegion) {\n liveRegion.textContent = message\n }\n }\n\n private _fireChangeEvent() {\n const detail: SchmancyAutocompleteChangeEvent['detail'] = {\n value: this.value,\n }\n\n if (this.multi) {\n detail.values = [...this._selectedValues$.value]\n }\n\n this.dispatchEvent(\n new CustomEvent<SchmancyAutocompleteChangeEvent['detail']>('change', {\n detail,\n bubbles: true,\n composed: true,\n })\n )\n }\n\n public checkValidity(): boolean {\n if (!this.required) return true\n return this.multi \n ? this._selectedValues$.value.length > 0 \n : Boolean(this._selectedValue$.value)\n }\n\n public reportValidity(): boolean {\n if (this._inputElementRef.value) {\n return this._inputElementRef.value.reportValidity()\n }\n return this.checkValidity()\n }\n\n firstUpdated() {\n this._setupOptionHandlers()\n\n // Sync initial value with display after options are available\n this._updateInputDisplay()\n\n // Update options when slot changes\n const slot = this.shadowRoot?.querySelector('slot')\n slot?.addEventListener('slotchange', () => {\n this._setupOptionHandlers()\n this._updateOptionSelection(this._selectedValue$.value, this._selectedValues$.value)\n })\n }\n\n private handleChipRemove(value: string) {\n const currentValues = this._selectedValues$.value\n const newValues = currentValues.filter(v => v !== value)\n this._selectedValues$.next(newValues)\n this._fireChangeEvent()\n this._announceToScreenReader(`Removed: ${this._getChipLabel(value)}`)\n }\n\n private _getChipLabel(value: string): string {\n const option = this._options.find(opt => opt.value === value)\n return option ? option.label || option.textContent || value : value\n }\n\n private _focusTextInput() {\n if (this._inputElementRef.value) {\n this._inputElementRef.value.focus()\n }\n }\n\n render() {\n const descriptionId = `${this.id}-desc`\n\n // Get size-based styling to match Schmancy input\n const getSizeStyles = () => {\n switch (this.size) {\n case 'sm':\n return {\n height: 'min-h-[40px]',\n padding: 'px-2',\n fontSize: 'text-sm', // 14px\n labelSize: 'text-sm'\n }\n case 'lg':\n return {\n height: 'min-h-[60px]',\n padding: 'px-5',\n fontSize: 'text-lg', // 18px\n labelSize: 'text-lg'\n }\n case 'md':\n default:\n return {\n height: 'min-h-[50px]',\n padding: 'px-4',\n fontSize: 'text-base', // 16px\n labelSize: 'text-base'\n }\n }\n }\n\n const { height, padding, fontSize, labelSize } = getSizeStyles()\n\n return html`\n <div class=\"relative\">\n <!-- Screen reader live region -->\n <div id=\"live-status\" role=\"status\" aria-live=\"polite\" class=\"sr-only\"></div>\n\n <!-- Description -->\n ${this.description ? html`<div id=\"${descriptionId}\" class=\"sr-only\">${this.description}</div>` : ''}\n\n <!-- Custom input wrapper for Gmail-style chip input -->\n <slot name=\"trigger\">\n ${when(this.multi,\n () => html`\n <!-- Custom multi-select input with inline chips -->\n <div class=\"relative\">\n ${when(this.label, () => html`\n <label class=\"${classMap({\n 'block mb-1 font-medium': true,\n 'text-primary-default': !this.error,\n 'text-error-default': this.error,\n [labelSize]: true\n })}\">\n ${this.label}${this.required ? html`<span class=\"text-error-default ml-1\">*</span>` : ''}\n </label>\n `)}\n <div\n class=\"${classMap({\n 'flex flex-wrap items-center gap-1': true,\n [height]: true,\n [padding]: true,\n 'block w-full min-w-0 rounded-[8px] border-0': true,\n 'bg-surface-highest text-surface-on': true,\n 'ring-0 ring-inset focus-within:ring-1 focus-within:ring-inset': true,\n 'ring-secondary-default focus-within:ring-secondary-default': !this.error,\n 'ring-error-default focus-within:ring-error-default': this.error,\n 'cursor-text transition-colors duration-200': true\n })}\"\n @click=${() => this._focusTextInput()}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls=\"options\"\n aria-expanded=${this._open}\n >\n <!-- Render chips inline -->\n ${repeat(\n this._selectedValues$.value,\n value => value,\n value => html`\n <schmancy-input-chip\n .value=${value}\n @remove=${(e: CustomEvent) => this.handleChipRemove(e.detail.value)}\n class=\"shrink-0 my-0.5\"\n >\n ${this._getChipLabel(value)}\n </schmancy-input-chip>\n `\n )}\n\n <!-- Text input for typing -->\n <input\n ${ref(this._inputElementRef)}\n id=\"autocomplete-input\"\n type=\"text\"\n class=\"flex-1 min-w-[120px] py-1 bg-transparent border-none outline-none ${fontSize} font-medium text-surface-on placeholder:text-muted\"\n name=${this.name || this.label?.toLowerCase().replace(/\\s+/g, '-') || ''}\n .placeholder=${this._selectedValues$.value.length > 0 ? 'Add more...' : this.placeholder}\n .value=${this._inputValue}\n .autocomplete=${this.autocomplete}\n aria-invalid=${this.error ? 'true' : 'false'}\n aria-required=${this.required ? 'true' : 'false'}\n aria-describedby=${this.error && this.validationMessage ? `${this._a11yId}-err` : nothing}\n aria-label=${!this.label && this.placeholder ? this.placeholder : nothing}\n @input=${(e: Event) => {\n const value = (e.target as HTMLInputElement).value\n this._inputValue = value\n this._inputValue$.next(value)\n }}\n @focus=${(e: FocusEvent) => {\n e.stopPropagation()\n // Clear input on focus for new searches\n this._inputValue = ''\n this._inputValue$.next('')\n this._openDropdown()\n }}\n @keydown=${(e: KeyboardEvent) => {\n this._handleKeyDown(e)\n }}\n @blur=${() => {\n this._handleAutoSelectOnBlur()\n }}\n />\n </div>\n\n <!-- Validation message -->\n ${when(this.error && this.validationMessage, () => html`\n <div id=\"${this._a11yId}-err\" class=\"mt-1 text-sm text-error-default\" role=\"alert\">\n ${this.validationMessage}\n </div>\n `)}\n </div>\n `,\n () => html`\n <!-- Regular single-select input -->\n <schmancy-input\n .size=${this.size}\n ${ref(this._inputElementRef)}\n id=\"autocomplete-input\"\n class=\"w-full\"\n .name=${this.name || this.label?.toLowerCase().replace(/\\s+/g, '-') || ''}\n .label=${this.label}\n .placeholder=${this.placeholder}\n .required=${this.required}\n .value=${this._inputValue}\n type=\"text\"\n autocomplete=${this.autocomplete}\n clickable\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls=\"options\"\n aria-expanded=${this._open}\n aria-describedby=${ifDefined(this.description ? descriptionId : undefined)}\n @input=${(e: Event) => {\n const value = (e.target as HTMLInputElement).value\n this._inputValue = value\n this._inputValue$.next(value)\n }}\n @focus=${(e: FocusEvent) => {\n e.stopPropagation()\n this._openDropdown()\n }}\n @click=${(e: MouseEvent) => {\n e.stopPropagation()\n this._openDropdown()\n }}\n @keydown=${(e: KeyboardEvent) => {\n this._handleKeyDown(e)\n }}\n @blur=${() => {\n this._handleAutoSelectOnBlur()\n }}\n >\n </schmancy-input>\n `\n )}\n </slot>\n\n <!-- Options dropdown -->\n <ul\n id=\"options\"\n class=${classMap({\n 'absolute': true,\n 'z-[1000]': true,\n 'mt-1': true,\n 'w-full': true,\n 'rounded-md': true,\n 'shadow-md': true,\n 'overflow-auto': true,\n 'min-w-full': true,\n 'bg-surface-low': true,\n 'flex': true,\n 'flex-col': true, // Enable flexbox for ordering\n })}\n role=\"listbox\"\n aria-multiselectable=${this.multi ? 'true' : 'false'}\n aria-label=${`${this.label || 'Options'} dropdown`}\n ?hidden=${!this._open}\n style=\"max-height: ${this.maxHeight}; display: ${this._open ? 'flex' : 'none'};\"\n @slotchange=${() => {\n this._setupOptionHandlers()\n }}\n >\n <slot></slot>\n ${!this._hasResults ? html`\n <li class=\"px-3 py-2 text-sm text-muted\">No results found</li>\n ` : ''}\n </ul>\n </div>\n `\n }\n\n private _handleAutoSelectOnBlur() {\n // Only auto-select in single-select mode and when dropdown is open with a search term\n if (this.multi || !this._open || !this._inputValue.trim()) {\n return\n }\n \n const searchTerm = this._inputValue.trim()\n \n // Find the best matching option using the same similarity logic as filtering\n let bestMatch: SchmancyOption | null = null\n let bestScore = 0\n \n this._options.forEach(option => {\n // Skip hidden options\n if (option.hidden) return\n \n // Get text to search in (prioritize label, then textContent, then value)\n const optionLabel = option.label || option.textContent || ''\n const optionValue = option.value\n \n // Calculate similarity scores for both label and value\n const labelScore = similarity(searchTerm, optionLabel)\n const valueScore = similarity(searchTerm, optionValue)\n \n // Use the higher score (prioritizing label matches)\n const score = Math.max(labelScore * 1.1, valueScore) // Slight boost for label matches\n \n // Keep track of best match that meets threshold\n if (score > bestScore && score >= this.similarityThreshold) {\n bestScore = score\n bestMatch = option\n }\n })\n \n // Auto-select the best match if found\n if (bestMatch) {\n // Silently update the selected value without firing change event\n this._selectedValue$.next(bestMatch.value)\n this._inputValue = bestMatch.label || bestMatch.textContent || ''\n this._inputValue$.next(this._inputValue)\n this._open = false\n }\n }\n\n private _handleKeyDown(event: KeyboardEvent) {\n const isOpen = this._open\n const selectedValues = this._selectedValues$.value\n\n // Handle backspace to remove last chip in multi-select when input is empty\n if (this.multi && event.key === 'Backspace' && !this._inputValue && selectedValues.length > 0 && !isOpen) {\n event.preventDefault()\n const lastValue = selectedValues[selectedValues.length - 1]\n this.handleChipRemove(lastValue)\n return\n }\n\n if (!isOpen && (event.key === 'ArrowDown' || event.key === 'Enter')) {\n event.preventDefault()\n this._openDropdown()\n\n timer(10)\n .pipe(takeUntil(this.disconnecting))\n .subscribe(() => {\n const firstVisible = this._options.find(opt => !opt.hidden)\n firstVisible?.focus()\n })\n return\n }\n\n if (!isOpen) return\n\n const visibleOptions = this._options.filter(opt => !opt.hidden)\n .toSorted((a, b) => parseInt(a.style.order || '0') - parseInt(b.style.order || '0'))\n\n const focusedOption = visibleOptions.find(opt => opt === document.activeElement)\n const currentIndex = focusedOption ? visibleOptions.indexOf(focusedOption) : -1\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault()\n this._open = false\n this._updateInputDisplay()\n this._inputElementRef.value?.focus()\n break\n\n case 'Tab':\n this._open = false\n this._updateInputDisplay()\n break\n\n case 'ArrowDown':\n event.preventDefault()\n const nextIndex = currentIndex < visibleOptions.length - 1 ? currentIndex + 1 : 0\n visibleOptions[nextIndex]?.focus()\n break\n\n case 'ArrowUp':\n event.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : visibleOptions.length - 1\n visibleOptions[prevIndex]?.focus()\n break\n\n case 'Home':\n event.preventDefault()\n visibleOptions[0]?.focus()\n break\n\n case 'End':\n event.preventDefault()\n visibleOptions[visibleOptions.length - 1]?.focus()\n break\n\n case 'Enter':\n case ' ':\n if (focusedOption) {\n event.preventDefault()\n this._selectOption(focusedOption)\n }\n break\n }\n }\n}\n\n\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'schmancy-autocomplete': SchmancyAutocomplete\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"autocomplete-B8CE5vGw.cjs","names":[],"sources":["../src/form/fields/autocomplete/autocomplete.scss?inline","../src/form/fields/autocomplete/autocomplete.ts"],"sourcesContent":[":host {\n\tdisplay: block;\n\tborder: unset !important;\n\tline-height: unset !important;\n\tbackground: unset !important;\n\tpadding: unset !important;\n\tfont-size: unset !important;\n\tbox-shadow: unset !important;\n}\n\n:host:focus {\n\tbox-shadow: unset !important;\n}\n\n@keyframes onAutoFillStart {\n\tfrom {/**/}\n\tto {/**/}\n}\n\nsch-input::part(input):-webkit-autofill,\nsch-input input:-webkit-autofill {\n\tanimation-name: onAutoFillStart;\n\tanimation-duration: 1ms;\n}\n","import { SchmancyFormField } from '@mixins/index'\nimport { InputSize, SchmancyInput } from '@schmancy/input'\nimport SchmancyOption from '@schmancy/option/option'\nimport { html, nothing, unsafeCSS } from 'lit'\nimport { customElement, property, query, queryAssignedElements, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { when } from 'lit/directives/when.js'\nimport {\n BehaviorSubject,\n combineLatest,\n fromEvent,\n timer\n} from 'rxjs'\nimport {\n debounceTime,\n distinctUntilChanged,\n takeUntil,\n tap\n} from 'rxjs/operators'\nimport style from './autocomplete.scss?inline'\n\n// Import the similarity function (or include it inline)\nimport { similarity } from '../../../utils/search'\n// Import chip component for multi-select display\nimport '../../../chips/input-chip'\n\nexport type SchmancyAutocompleteChangeEvent = CustomEvent<{\n value: string | string[]\n values?: string[]\n}>\n\ninterface FilteredOption {\n option: SchmancyOption\n score: number\n}\n\n/**\n * Autocomplete input component with filtering and multi-select support.\n *\n * @prop {string} name - Name attribute for form submission\n * @prop {string} label - Label text displayed above the input\n * @prop {string} placeholder - Placeholder text for the input\n * @prop {boolean} required - Whether the field is required\n * @prop {boolean} multi - Enable multi-select mode\n * @prop {string} value - Selected value (single select mode)\n * @prop {string[]} values - Selected values (multi-select mode)\n */\n@customElement('schmancy-autocomplete')\nexport default class SchmancyAutocomplete extends SchmancyFormField(unsafeCSS(style)) {\n\n // `formAssociated`, `internals`, `attachInternals`, `name`, `label`,\n // `required`, `disabled`, `error`, `validationMessage`, `hint`, `id`,\n // `validateOn`, `touched/dirty/submitted`, `markTouched/markSubmitted`,\n // `setCustomValidity`, `formDisabledCallback`, FIELD_CONNECT_EVENT dispatch\n // — all from the mixin.\n\n /** Override mixin's resetForm with autocomplete-specific subject reset. */\n override resetForm(): void {\n if (this.multi) {\n this._selectedValues$.next([])\n } else {\n this._selectedValue$.next('')\n }\n this._inputValue = ''\n this._inputValue$.next('')\n super.resetForm()\n }\n\n // Track whether value/values have been explicitly set\n _valueSet: boolean = false\n _valuesSet: boolean = false\n\n // Autocomplete-specific properties only — `name`, `label`, `required`,\n // `error`, `validationMessage` come from the mixin.\n @property({ type: String }) placeholder = ''\n @property({ type: String }) maxHeight = '300px'\n @property({ type: Boolean }) multi = false\n @property({ type: String }) description = ''\n @property({ type: String, reflect: true }) size: InputSize = 'md'\n @property({ type: String }) autocomplete = 'off'\n @property({ type: Number }) debounceMs = 200\n @property({ type: Number }) similarityThreshold = 0.3 // Minimum similarity score to show option\n\n private readonly _a11yId = `schmancy-autocomplete-${Math.random().toString(36).slice(2, 10)}`\n\n // Values property for multi-select mode\n @property({ type: Array })\n get values() {\n return [...this._selectedValues$.value]\n }\n set values(vals: string[]) {\n this._valuesSet = true\n this._selectedValues$.next(Array.isArray(vals) ? [...vals] : [])\n }\n\n // Value property — narrowed override of the mixin's wide value union.\n @property({ type: String, reflect: true })\n override get value(): string {\n return this.multi\n ? this._selectedValues$.value.join(',')\n : this._selectedValue$.value\n }\n override set value(val: string) {\n this._valueSet = true\n if (this.multi) {\n const newValues = val ? val.split(',').map(v => v.trim()).filter(Boolean) : []\n const currentValues = this._selectedValues$.value\n // Only update if values actually changed\n if (JSON.stringify(newValues) !== JSON.stringify(currentValues)) {\n this._selectedValues$.next(newValues)\n }\n } else {\n // Only update if value actually changed\n if (val !== this._selectedValue$.value) {\n this._selectedValue$.next(val)\n // Update the input display when value is set\n this._updateInputDisplay()\n }\n }\n }\n\n // State\n @state() private _open = false\n @state() private _inputValue = ''\n @state() private _visibleOptionsCount = 0\n @state() private _hasResults = true\n\n // DOM references\n @query('#options') _listbox!: HTMLUListElement\n @query('sch-input') _input!: SchmancyInput\n @queryAssignedElements({ flatten: true }) private _options!: SchmancyOption[]\n private _inputElementRef = createRef<HTMLInputElement>()\n\n // RxJS Subjects - only what we actually need\n private _selectedValue$ = new BehaviorSubject<string>('')\n private _selectedValues$ = new BehaviorSubject<string[]>([])\n private _inputValue$ = new BehaviorSubject<string>('')\n\n override connectedCallback() {\n // FIELD_CONNECT_EVENT is dispatched by the mixin's connectedCallback.\n super.connectedCallback()\n this._setupAutocompleteLogic()\n this._setupDocumentClickHandler()\n }\n\n private _setupAutocompleteLogic() {\n // Sync selection state\n combineLatest([\n this._selectedValue$,\n this._selectedValues$\n ]).pipe(\n tap(([selectedValue, selectedValues]) => {\n this._updateOptionSelection(selectedValue, selectedValues)\n // Keep ElementInternals form value in sync with selection (single and multi).\n const formValue = this.multi ? selectedValues.join(',') : selectedValue\n this.internals?.setFormValue(formValue || null)\n if (this.required) {\n const missing = this.multi ? selectedValues.length === 0 : !selectedValue\n this.internals?.setValidity(\n missing ? { valueMissing: true } : {},\n missing ? this.validationMessage || 'Please select an option.' : undefined,\n )\n }\n }),\n takeUntil(this.disconnecting)\n ).subscribe()\n\n // Filter options based on input\n this._inputValue$.pipe(\n distinctUntilChanged(),\n debounceTime(this.debounceMs),\n tap(searchTerm => {\n if (this._open) {\n this._filterOptions(searchTerm)\n }\n }),\n takeUntil(this.disconnecting)\n ).subscribe()\n }\n\n private _setupOptionHandlers() {\n this._options.forEach((option, index) => {\n option.setAttribute('role', 'option')\n option.tabIndex = -1\n if (!option.id) {\n option.id = `${this.id}-option-${index}`\n }\n // Idempotent: slotchange may fire repeatedly for the same option nodes,\n // and addEventListener doesn't replace prior handlers like onfoo= did.\n if (option.dataset.schmancyAutocompleteHandlers === 'attached') return\n option.dataset.schmancyAutocompleteHandlers = 'attached'\n\n // Prevent blur handler from interfering with option selection\n fromEvent<MouseEvent>(option, 'mousedown')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => e.preventDefault())\n\n // Handle the actual selection\n fromEvent<MouseEvent>(option, 'click')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => {\n e.stopPropagation()\n this._selectOption(option)\n })\n })\n }\n\n private _updateOptionSelection(selectedValue: string, selectedValues: string[]) {\n this._options.forEach(option => {\n option.selected = this.multi\n ? selectedValues.includes(option.value)\n : option.value === selectedValue\n option.setAttribute('aria-selected', String(option.selected))\n })\n }\n\n private _filterOptions(searchTerm: string) {\n const term = searchTerm.trim()\n\n if (!term) {\n // Show all options if no search term\n this._options.forEach(option => {\n option.hidden = false\n option.style.order = '0'\n })\n this._visibleOptionsCount = this._options.length\n this._hasResults = true\n } else {\n // Calculate similarity scores for all options\n const scoredOptions: FilteredOption[] = this._options.map(option => {\n const optionLabel = option.label || option.textContent || ''\n const optionValue = option.value\n\n const labelScore = similarity(term, optionLabel)\n const valueScore = similarity(term, optionValue)\n const score = Math.max(labelScore * 1.1, valueScore)\n\n return { option, score }\n })\n\n // Sort by score (highest first)\n scoredOptions.sort((a, b) => b.score - a.score)\n\n // Apply visibility and ordering\n let visibleCount = 0\n scoredOptions.forEach((item, index) => {\n const { option, score } = item\n\n if (score < this.similarityThreshold) {\n option.hidden = true\n } else {\n option.hidden = false\n visibleCount++\n option.style.order = String(index)\n }\n })\n\n this._visibleOptionsCount = visibleCount\n this._hasResults = visibleCount > 0\n }\n\n this._announceToScreenReader(\n this._visibleOptionsCount > 0\n ? `${this._visibleOptionsCount} option${this._visibleOptionsCount === 1 ? '' : 's'} available.`\n : 'No results found.'\n )\n }\n\n private _openDropdown() {\n this._open = true\n // Reset filters based on current input value when dropdown opens\n this._filterOptions(this._inputValue)\n }\n\n private _selectOption(option: SchmancyOption) {\n if (this.multi) {\n const currentValues = this._selectedValues$.value\n const index = currentValues.indexOf(option.value)\n const newValues = index > -1\n ? currentValues.filter(v => v !== option.value)\n : [...currentValues, option.value]\n\n this._selectedValues$.next(newValues)\n this._announceToScreenReader(\n newValues.length > 0\n ? `Selected: ${this._getSelectedLabels().join(', ')}`\n : 'No options selected'\n )\n this._fireChangeEvent()\n } else {\n // Update value first\n this._selectedValue$.next(option.value)\n\n // Close dropdown IMMEDIATELY to prevent blur handler from firing\n this._open = false\n\n // Now fire event with the NEW value\n this._fireChangeEvent()\n\n // Update UI\n this._inputValue = option.label || option.textContent || ''\n this._inputValue$.next(this._inputValue)\n\n this._announceToScreenReader(`Selected: ${option.label || option.textContent}`)\n }\n }\n\n private _setupDocumentClickHandler() {\n fromEvent<MouseEvent>(document, 'click')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => {\n if (!this._open) return\n const path = e.composedPath()\n if (!path.includes(this) && !this._options.some(opt => path.includes(opt))) {\n this._open = false\n this._updateInputDisplay()\n }\n })\n }\n\n\n private _updateInputDisplay() {\n // For multi-select, we don't update input display since chips show the selections\n if (this.multi) return\n\n const selectedValue = this._selectedValue$.value\n const option = this._options.find(opt => opt.value === selectedValue)\n this._inputValue = option ? option.label || option.textContent || '' : ''\n this._inputValue$.next(this._inputValue)\n\n if (this._inputElementRef.value) {\n this._inputElementRef.value.value = this._inputValue\n }\n }\n\n private _getSelectedLabels(): string[] {\n return this._options\n .filter(option => \n this.multi \n ? this._selectedValues$.value.includes(option.value)\n : option.value === this._selectedValue$.value\n )\n .map(option => option.label || option.textContent || '')\n }\n\n private _announceToScreenReader(message: string) {\n const liveRegion = this.shadowRoot?.querySelector('#live-status')\n if (liveRegion) {\n liveRegion.textContent = message\n }\n }\n\n private _fireChangeEvent() {\n const detail: SchmancyAutocompleteChangeEvent['detail'] = {\n value: this.value,\n }\n\n if (this.multi) {\n detail.values = [...this._selectedValues$.value]\n }\n\n this.dispatchEvent(\n new CustomEvent<SchmancyAutocompleteChangeEvent['detail']>('change', {\n detail,\n bubbles: true,\n composed: true,\n })\n )\n }\n\n public checkValidity(): boolean {\n if (!this.required) return true\n return this.multi \n ? this._selectedValues$.value.length > 0 \n : Boolean(this._selectedValue$.value)\n }\n\n public reportValidity(): boolean {\n if (this._inputElementRef.value) {\n return this._inputElementRef.value.reportValidity()\n }\n return this.checkValidity()\n }\n\n firstUpdated() {\n this._setupOptionHandlers()\n\n // Sync initial value with display after options are available\n this._updateInputDisplay()\n\n // Update options when slot changes\n const slot = this.shadowRoot?.querySelector('slot')\n slot?.addEventListener('slotchange', () => {\n this._setupOptionHandlers()\n this._updateOptionSelection(this._selectedValue$.value, this._selectedValues$.value)\n })\n }\n\n private handleChipRemove(value: string) {\n const currentValues = this._selectedValues$.value\n const newValues = currentValues.filter(v => v !== value)\n this._selectedValues$.next(newValues)\n this._fireChangeEvent()\n this._announceToScreenReader(`Removed: ${this._getChipLabel(value)}`)\n }\n\n private _getChipLabel(value: string): string {\n const option = this._options.find(opt => opt.value === value)\n return option ? option.label || option.textContent || value : value\n }\n\n private _focusTextInput() {\n if (this._inputElementRef.value) {\n this._inputElementRef.value.focus()\n }\n }\n\n render() {\n const descriptionId = `${this.id}-desc`\n\n // Get size-based styling to match Schmancy input\n const getSizeStyles = () => {\n switch (this.size) {\n case 'sm':\n return {\n height: 'min-h-[40px]',\n padding: 'px-2',\n fontSize: 'text-sm', // 14px\n labelSize: 'text-sm'\n }\n case 'lg':\n return {\n height: 'min-h-[60px]',\n padding: 'px-5',\n fontSize: 'text-lg', // 18px\n labelSize: 'text-lg'\n }\n case 'md':\n default:\n return {\n height: 'min-h-[50px]',\n padding: 'px-4',\n fontSize: 'text-base', // 16px\n labelSize: 'text-base'\n }\n }\n }\n\n const { height, padding, fontSize, labelSize } = getSizeStyles()\n\n return html`\n <div class=\"relative\">\n <!-- Screen reader live region -->\n <div id=\"live-status\" role=\"status\" aria-live=\"polite\" class=\"sr-only\"></div>\n\n <!-- Description -->\n ${this.description ? html`<div id=\"${descriptionId}\" class=\"sr-only\">${this.description}</div>` : ''}\n\n <!-- Custom input wrapper for Gmail-style chip input -->\n <slot name=\"trigger\">\n ${when(this.multi,\n () => html`\n <!-- Custom multi-select input with inline chips -->\n <div class=\"relative\">\n ${when(this.label, () => html`\n <label class=\"${classMap({\n 'block mb-1 font-medium': true,\n 'text-primary-default': !this.error,\n 'text-error-default': this.error,\n [labelSize]: true\n })}\">\n ${this.label}${this.required ? html`<span class=\"text-error-default ml-1\">*</span>` : ''}\n </label>\n `)}\n <div\n class=\"${classMap({\n 'flex flex-wrap items-center gap-1': true,\n [height]: true,\n [padding]: true,\n 'block w-full min-w-0 rounded-[8px] border-0': true,\n 'bg-surface-highest text-surface-on': true,\n 'ring-0 ring-inset focus-within:ring-1 focus-within:ring-inset': true,\n 'ring-secondary-default focus-within:ring-secondary-default': !this.error,\n 'ring-error-default focus-within:ring-error-default': this.error,\n 'cursor-text transition-colors duration-200': true\n })}\"\n @click=${() => this._focusTextInput()}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls=\"options\"\n aria-expanded=${this._open}\n >\n <!-- Render chips inline -->\n ${repeat(\n this._selectedValues$.value,\n value => value,\n value => html`\n <schmancy-input-chip\n .value=${value}\n @remove=${(e: CustomEvent) => this.handleChipRemove(e.detail.value)}\n class=\"shrink-0 my-0.5\"\n >\n ${this._getChipLabel(value)}\n </schmancy-input-chip>\n `\n )}\n\n <!-- Text input for typing -->\n <input\n ${ref(this._inputElementRef)}\n id=\"autocomplete-input\"\n type=\"text\"\n class=\"flex-1 min-w-[120px] py-1 bg-transparent border-none outline-none ${fontSize} font-medium text-surface-on placeholder:text-muted\"\n name=${this.name || this.label?.toLowerCase().replace(/\\s+/g, '-') || ''}\n .placeholder=${this._selectedValues$.value.length > 0 ? 'Add more...' : this.placeholder}\n .value=${this._inputValue}\n .autocomplete=${this.autocomplete}\n aria-invalid=${this.error ? 'true' : 'false'}\n aria-required=${this.required ? 'true' : 'false'}\n aria-describedby=${this.error && this.validationMessage ? `${this._a11yId}-err` : nothing}\n aria-label=${!this.label && this.placeholder ? this.placeholder : nothing}\n @input=${(e: Event) => {\n const value = (e.target as HTMLInputElement).value\n this._inputValue = value\n this._inputValue$.next(value)\n }}\n @focus=${(e: FocusEvent) => {\n e.stopPropagation()\n // Clear input on focus for new searches\n this._inputValue = ''\n this._inputValue$.next('')\n this._openDropdown()\n }}\n @keydown=${(e: KeyboardEvent) => {\n this._handleKeyDown(e)\n }}\n @blur=${() => {\n this._handleAutoSelectOnBlur()\n }}\n />\n </div>\n\n <!-- Validation message -->\n ${when(this.error && this.validationMessage, () => html`\n <div id=\"${this._a11yId}-err\" class=\"mt-1 text-sm text-error-default\" role=\"alert\">\n ${this.validationMessage}\n </div>\n `)}\n </div>\n `,\n () => html`\n <!-- Regular single-select input -->\n <schmancy-input\n .size=${this.size}\n ${ref(this._inputElementRef)}\n id=\"autocomplete-input\"\n class=\"w-full\"\n .name=${this.name || this.label?.toLowerCase().replace(/\\s+/g, '-') || ''}\n .label=${this.label}\n .placeholder=${this.placeholder}\n .required=${this.required}\n .value=${this._inputValue}\n type=\"text\"\n autocomplete=${this.autocomplete}\n clickable\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls=\"options\"\n aria-expanded=${this._open}\n aria-describedby=${ifDefined(this.description ? descriptionId : undefined)}\n @input=${(e: Event) => {\n const value = (e.target as HTMLInputElement).value\n this._inputValue = value\n this._inputValue$.next(value)\n }}\n @focus=${(e: FocusEvent) => {\n e.stopPropagation()\n this._openDropdown()\n }}\n @click=${(e: MouseEvent) => {\n e.stopPropagation()\n this._openDropdown()\n }}\n @keydown=${(e: KeyboardEvent) => {\n this._handleKeyDown(e)\n }}\n @blur=${() => {\n this._handleAutoSelectOnBlur()\n }}\n >\n </schmancy-input>\n `\n )}\n </slot>\n\n <!-- Options dropdown -->\n <ul\n id=\"options\"\n class=${classMap({\n 'absolute': true,\n 'z-[1000]': true,\n 'mt-1': true,\n 'w-full': true,\n 'rounded-md': true,\n 'shadow-md': true,\n 'overflow-auto': true,\n 'min-w-full': true,\n 'bg-surface-low': true,\n 'flex': true,\n 'flex-col': true, // Enable flexbox for ordering\n })}\n role=\"listbox\"\n aria-multiselectable=${this.multi ? 'true' : 'false'}\n aria-label=${`${this.label || 'Options'} dropdown`}\n ?hidden=${!this._open}\n style=\"max-height: ${this.maxHeight}; display: ${this._open ? 'flex' : 'none'};\"\n @slotchange=${() => {\n this._setupOptionHandlers()\n }}\n >\n <slot></slot>\n ${!this._hasResults ? html`\n <li class=\"px-3 py-2 text-sm text-muted\">No results found</li>\n ` : ''}\n </ul>\n </div>\n `\n }\n\n private _handleAutoSelectOnBlur() {\n // Only auto-select in single-select mode and when dropdown is open with a search term\n if (this.multi || !this._open || !this._inputValue.trim()) {\n return\n }\n \n const searchTerm = this._inputValue.trim()\n \n // Find the best matching option using the same similarity logic as filtering\n let bestMatch: SchmancyOption | null = null\n let bestScore = 0\n \n this._options.forEach(option => {\n // Skip hidden options\n if (option.hidden) return\n \n // Get text to search in (prioritize label, then textContent, then value)\n const optionLabel = option.label || option.textContent || ''\n const optionValue = option.value\n \n // Calculate similarity scores for both label and value\n const labelScore = similarity(searchTerm, optionLabel)\n const valueScore = similarity(searchTerm, optionValue)\n \n // Use the higher score (prioritizing label matches)\n const score = Math.max(labelScore * 1.1, valueScore) // Slight boost for label matches\n \n // Keep track of best match that meets threshold\n if (score > bestScore && score >= this.similarityThreshold) {\n bestScore = score\n bestMatch = option\n }\n })\n \n // Auto-select the best match if found\n if (bestMatch) {\n // Silently update the selected value without firing change event\n this._selectedValue$.next(bestMatch.value)\n this._inputValue = bestMatch.label || bestMatch.textContent || ''\n this._inputValue$.next(this._inputValue)\n this._open = false\n }\n }\n\n private _handleKeyDown(event: KeyboardEvent) {\n const isOpen = this._open\n const selectedValues = this._selectedValues$.value\n\n // Handle backspace to remove last chip in multi-select when input is empty\n if (this.multi && event.key === 'Backspace' && !this._inputValue && selectedValues.length > 0 && !isOpen) {\n event.preventDefault()\n const lastValue = selectedValues[selectedValues.length - 1]\n this.handleChipRemove(lastValue)\n return\n }\n\n if (!isOpen && (event.key === 'ArrowDown' || event.key === 'Enter')) {\n event.preventDefault()\n this._openDropdown()\n\n timer(10)\n .pipe(takeUntil(this.disconnecting))\n .subscribe(() => {\n const firstVisible = this._options.find(opt => !opt.hidden)\n firstVisible?.focus()\n })\n return\n }\n\n if (!isOpen) return\n\n const visibleOptions = this._options.filter(opt => !opt.hidden)\n .toSorted((a, b) => parseInt(a.style.order || '0') - parseInt(b.style.order || '0'))\n\n const focusedOption = visibleOptions.find(opt => opt === document.activeElement)\n const currentIndex = focusedOption ? visibleOptions.indexOf(focusedOption) : -1\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault()\n this._open = false\n this._updateInputDisplay()\n this._inputElementRef.value?.focus()\n break\n\n case 'Tab':\n this._open = false\n this._updateInputDisplay()\n break\n\n case 'ArrowDown':\n event.preventDefault()\n const nextIndex = currentIndex < visibleOptions.length - 1 ? currentIndex + 1 : 0\n visibleOptions[nextIndex]?.focus()\n break\n\n case 'ArrowUp':\n event.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : visibleOptions.length - 1\n visibleOptions[prevIndex]?.focus()\n break\n\n case 'Home':\n event.preventDefault()\n visibleOptions[0]?.focus()\n break\n\n case 'End':\n event.preventDefault()\n visibleOptions[visibleOptions.length - 1]?.focus()\n break\n\n case 'Enter':\n case ' ':\n if (focusedOption) {\n event.preventDefault()\n this._selectOption(focusedOption)\n }\n break\n }\n }\n}\n\n\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'schmancy-autocomplete': SchmancyAutocomplete\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { o as e } from "./mixins-
|
|
1
|
+
import { o as e } from "./mixins-DCVXqL1Q.js";
|
|
2
2
|
import { a as t } from "./active-host-BP0zy_Y9.js";
|
|
3
3
|
import { t as n } from "./search-MvIBA93K.js";
|
|
4
|
-
import "./input-chip-
|
|
4
|
+
import "./input-chip-c5n547tg.js";
|
|
5
5
|
import { BehaviorSubject as r, combineLatest as i, fromEvent as a, timer as o } from "rxjs";
|
|
6
6
|
import { debounceTime as s, distinctUntilChanged as c, takeUntil as l, tap as u } from "rxjs/operators";
|
|
7
7
|
import { classMap as d } from "lit/directives/class-map.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete-CXvUjMD-.js","names":[],"sources":["../src/form/fields/autocomplete/autocomplete.scss?inline","../src/form/fields/autocomplete/autocomplete.ts"],"sourcesContent":[":host {\n\tdisplay: block;\n\tborder: unset !important;\n\tline-height: unset !important;\n\tbackground: unset !important;\n\tpadding: unset !important;\n\tfont-size: unset !important;\n\tbox-shadow: unset !important;\n}\n\n:host:focus {\n\tbox-shadow: unset !important;\n}\n\n@keyframes onAutoFillStart {\n\tfrom {/**/}\n\tto {/**/}\n}\n\nsch-input::part(input):-webkit-autofill,\nsch-input input:-webkit-autofill {\n\tanimation-name: onAutoFillStart;\n\tanimation-duration: 1ms;\n}\n","import { SchmancyFormField } from '@mixins/index'\nimport { InputSize, SchmancyInput } from '@schmancy/input'\nimport SchmancyOption from '@schmancy/option/option'\nimport { html, nothing, unsafeCSS } from 'lit'\nimport { customElement, property, query, queryAssignedElements, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { when } from 'lit/directives/when.js'\nimport {\n BehaviorSubject,\n combineLatest,\n fromEvent,\n timer\n} from 'rxjs'\nimport {\n debounceTime,\n distinctUntilChanged,\n takeUntil,\n tap\n} from 'rxjs/operators'\nimport style from './autocomplete.scss?inline'\n\n// Import the similarity function (or include it inline)\nimport { similarity } from '../../../utils/search'\n// Import chip component for multi-select display\nimport '../../../chips/input-chip'\n\nexport type SchmancyAutocompleteChangeEvent = CustomEvent<{\n value: string | string[]\n values?: string[]\n}>\n\ninterface FilteredOption {\n option: SchmancyOption\n score: number\n}\n\n/**\n * Autocomplete input component with filtering and multi-select support.\n *\n * @prop {string} name - Name attribute for form submission\n * @prop {string} label - Label text displayed above the input\n * @prop {string} placeholder - Placeholder text for the input\n * @prop {boolean} required - Whether the field is required\n * @prop {boolean} multi - Enable multi-select mode\n * @prop {string} value - Selected value (single select mode)\n * @prop {string[]} values - Selected values (multi-select mode)\n */\n@customElement('schmancy-autocomplete')\nexport default class SchmancyAutocomplete extends SchmancyFormField(unsafeCSS(style)) {\n\n // `formAssociated`, `internals`, `attachInternals`, `name`, `label`,\n // `required`, `disabled`, `error`, `validationMessage`, `hint`, `id`,\n // `validateOn`, `touched/dirty/submitted`, `markTouched/markSubmitted`,\n // `setCustomValidity`, `formDisabledCallback`, FIELD_CONNECT_EVENT dispatch\n // — all from the mixin.\n\n /** Override mixin's resetForm with autocomplete-specific subject reset. */\n override resetForm(): void {\n if (this.multi) {\n this._selectedValues$.next([])\n } else {\n this._selectedValue$.next('')\n }\n this._inputValue = ''\n this._inputValue$.next('')\n super.resetForm()\n }\n\n // Track whether value/values have been explicitly set\n _valueSet: boolean = false\n _valuesSet: boolean = false\n\n // Autocomplete-specific properties only — `name`, `label`, `required`,\n // `error`, `validationMessage` come from the mixin.\n @property({ type: String }) placeholder = ''\n @property({ type: String }) maxHeight = '300px'\n @property({ type: Boolean }) multi = false\n @property({ type: String }) description = ''\n @property({ type: String, reflect: true }) size: InputSize = 'md'\n @property({ type: String }) autocomplete = 'off'\n @property({ type: Number }) debounceMs = 200\n @property({ type: Number }) similarityThreshold = 0.3 // Minimum similarity score to show option\n\n private readonly _a11yId = `schmancy-autocomplete-${Math.random().toString(36).slice(2, 10)}`\n\n // Values property for multi-select mode\n @property({ type: Array })\n get values() {\n return [...this._selectedValues$.value]\n }\n set values(vals: string[]) {\n this._valuesSet = true\n this._selectedValues$.next(Array.isArray(vals) ? [...vals] : [])\n }\n\n // Value property — narrowed override of the mixin's wide value union.\n @property({ type: String, reflect: true })\n override get value(): string {\n return this.multi\n ? this._selectedValues$.value.join(',')\n : this._selectedValue$.value\n }\n override set value(val: string) {\n this._valueSet = true\n if (this.multi) {\n const newValues = val ? val.split(',').map(v => v.trim()).filter(Boolean) : []\n const currentValues = this._selectedValues$.value\n // Only update if values actually changed\n if (JSON.stringify(newValues) !== JSON.stringify(currentValues)) {\n this._selectedValues$.next(newValues)\n }\n } else {\n // Only update if value actually changed\n if (val !== this._selectedValue$.value) {\n this._selectedValue$.next(val)\n // Update the input display when value is set\n this._updateInputDisplay()\n }\n }\n }\n\n // State\n @state() private _open = false\n @state() private _inputValue = ''\n @state() private _visibleOptionsCount = 0\n @state() private _hasResults = true\n\n // DOM references\n @query('#options') _listbox!: HTMLUListElement\n @query('sch-input') _input!: SchmancyInput\n @queryAssignedElements({ flatten: true }) private _options!: SchmancyOption[]\n private _inputElementRef = createRef<HTMLInputElement>()\n\n // RxJS Subjects - only what we actually need\n private _selectedValue$ = new BehaviorSubject<string>('')\n private _selectedValues$ = new BehaviorSubject<string[]>([])\n private _inputValue$ = new BehaviorSubject<string>('')\n\n override connectedCallback() {\n // FIELD_CONNECT_EVENT is dispatched by the mixin's connectedCallback.\n super.connectedCallback()\n this._setupAutocompleteLogic()\n this._setupDocumentClickHandler()\n }\n\n private _setupAutocompleteLogic() {\n // Sync selection state\n combineLatest([\n this._selectedValue$,\n this._selectedValues$\n ]).pipe(\n tap(([selectedValue, selectedValues]) => {\n this._updateOptionSelection(selectedValue, selectedValues)\n // Keep ElementInternals form value in sync with selection (single and multi).\n const formValue = this.multi ? selectedValues.join(',') : selectedValue\n this.internals?.setFormValue(formValue || null)\n if (this.required) {\n const missing = this.multi ? selectedValues.length === 0 : !selectedValue\n this.internals?.setValidity(\n missing ? { valueMissing: true } : {},\n missing ? this.validationMessage || 'Please select an option.' : undefined,\n )\n }\n }),\n takeUntil(this.disconnecting)\n ).subscribe()\n\n // Filter options based on input\n this._inputValue$.pipe(\n distinctUntilChanged(),\n debounceTime(this.debounceMs),\n tap(searchTerm => {\n if (this._open) {\n this._filterOptions(searchTerm)\n }\n }),\n takeUntil(this.disconnecting)\n ).subscribe()\n }\n\n private _setupOptionHandlers() {\n this._options.forEach((option, index) => {\n option.setAttribute('role', 'option')\n option.tabIndex = -1\n if (!option.id) {\n option.id = `${this.id}-option-${index}`\n }\n // Idempotent: slotchange may fire repeatedly for the same option nodes,\n // and addEventListener doesn't replace prior handlers like onfoo= did.\n if (option.dataset.schmancyAutocompleteHandlers === 'attached') return\n option.dataset.schmancyAutocompleteHandlers = 'attached'\n\n // Prevent blur handler from interfering with option selection\n fromEvent<MouseEvent>(option, 'mousedown')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => e.preventDefault())\n\n // Handle the actual selection\n fromEvent<MouseEvent>(option, 'click')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => {\n e.stopPropagation()\n this._selectOption(option)\n })\n })\n }\n\n private _updateOptionSelection(selectedValue: string, selectedValues: string[]) {\n this._options.forEach(option => {\n option.selected = this.multi\n ? selectedValues.includes(option.value)\n : option.value === selectedValue\n option.setAttribute('aria-selected', String(option.selected))\n })\n }\n\n private _filterOptions(searchTerm: string) {\n const term = searchTerm.trim()\n\n if (!term) {\n // Show all options if no search term\n this._options.forEach(option => {\n option.hidden = false\n option.style.order = '0'\n })\n this._visibleOptionsCount = this._options.length\n this._hasResults = true\n } else {\n // Calculate similarity scores for all options\n const scoredOptions: FilteredOption[] = this._options.map(option => {\n const optionLabel = option.label || option.textContent || ''\n const optionValue = option.value\n\n const labelScore = similarity(term, optionLabel)\n const valueScore = similarity(term, optionValue)\n const score = Math.max(labelScore * 1.1, valueScore)\n\n return { option, score }\n })\n\n // Sort by score (highest first)\n scoredOptions.sort((a, b) => b.score - a.score)\n\n // Apply visibility and ordering\n let visibleCount = 0\n scoredOptions.forEach((item, index) => {\n const { option, score } = item\n\n if (score < this.similarityThreshold) {\n option.hidden = true\n } else {\n option.hidden = false\n visibleCount++\n option.style.order = String(index)\n }\n })\n\n this._visibleOptionsCount = visibleCount\n this._hasResults = visibleCount > 0\n }\n\n this._announceToScreenReader(\n this._visibleOptionsCount > 0\n ? `${this._visibleOptionsCount} option${this._visibleOptionsCount === 1 ? '' : 's'} available.`\n : 'No results found.'\n )\n }\n\n private _openDropdown() {\n this._open = true\n // Reset filters based on current input value when dropdown opens\n this._filterOptions(this._inputValue)\n }\n\n private _selectOption(option: SchmancyOption) {\n if (this.multi) {\n const currentValues = this._selectedValues$.value\n const index = currentValues.indexOf(option.value)\n const newValues = index > -1\n ? currentValues.filter(v => v !== option.value)\n : [...currentValues, option.value]\n\n this._selectedValues$.next(newValues)\n this._announceToScreenReader(\n newValues.length > 0\n ? `Selected: ${this._getSelectedLabels().join(', ')}`\n : 'No options selected'\n )\n this._fireChangeEvent()\n } else {\n // Update value first\n this._selectedValue$.next(option.value)\n\n // Close dropdown IMMEDIATELY to prevent blur handler from firing\n this._open = false\n\n // Now fire event with the NEW value\n this._fireChangeEvent()\n\n // Update UI\n this._inputValue = option.label || option.textContent || ''\n this._inputValue$.next(this._inputValue)\n\n this._announceToScreenReader(`Selected: ${option.label || option.textContent}`)\n }\n }\n\n private _setupDocumentClickHandler() {\n fromEvent<MouseEvent>(document, 'click')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => {\n if (!this._open) return\n const path = e.composedPath()\n if (!path.includes(this) && !this._options.some(opt => path.includes(opt))) {\n this._open = false\n this._updateInputDisplay()\n }\n })\n }\n\n\n private _updateInputDisplay() {\n // For multi-select, we don't update input display since chips show the selections\n if (this.multi) return\n\n const selectedValue = this._selectedValue$.value\n const option = this._options.find(opt => opt.value === selectedValue)\n this._inputValue = option ? option.label || option.textContent || '' : ''\n this._inputValue$.next(this._inputValue)\n\n if (this._inputElementRef.value) {\n this._inputElementRef.value.value = this._inputValue\n }\n }\n\n private _getSelectedLabels(): string[] {\n return this._options\n .filter(option => \n this.multi \n ? this._selectedValues$.value.includes(option.value)\n : option.value === this._selectedValue$.value\n )\n .map(option => option.label || option.textContent || '')\n }\n\n private _announceToScreenReader(message: string) {\n const liveRegion = this.shadowRoot?.querySelector('#live-status')\n if (liveRegion) {\n liveRegion.textContent = message\n }\n }\n\n private _fireChangeEvent() {\n const detail: SchmancyAutocompleteChangeEvent['detail'] = {\n value: this.value,\n }\n\n if (this.multi) {\n detail.values = [...this._selectedValues$.value]\n }\n\n this.dispatchEvent(\n new CustomEvent<SchmancyAutocompleteChangeEvent['detail']>('change', {\n detail,\n bubbles: true,\n composed: true,\n })\n )\n }\n\n public checkValidity(): boolean {\n if (!this.required) return true\n return this.multi \n ? this._selectedValues$.value.length > 0 \n : Boolean(this._selectedValue$.value)\n }\n\n public reportValidity(): boolean {\n if (this._inputElementRef.value) {\n return this._inputElementRef.value.reportValidity()\n }\n return this.checkValidity()\n }\n\n firstUpdated() {\n this._setupOptionHandlers()\n\n // Sync initial value with display after options are available\n this._updateInputDisplay()\n\n // Update options when slot changes\n const slot = this.shadowRoot?.querySelector('slot')\n slot?.addEventListener('slotchange', () => {\n this._setupOptionHandlers()\n this._updateOptionSelection(this._selectedValue$.value, this._selectedValues$.value)\n })\n }\n\n private handleChipRemove(value: string) {\n const currentValues = this._selectedValues$.value\n const newValues = currentValues.filter(v => v !== value)\n this._selectedValues$.next(newValues)\n this._fireChangeEvent()\n this._announceToScreenReader(`Removed: ${this._getChipLabel(value)}`)\n }\n\n private _getChipLabel(value: string): string {\n const option = this._options.find(opt => opt.value === value)\n return option ? option.label || option.textContent || value : value\n }\n\n private _focusTextInput() {\n if (this._inputElementRef.value) {\n this._inputElementRef.value.focus()\n }\n }\n\n render() {\n const descriptionId = `${this.id}-desc`\n\n // Get size-based styling to match Schmancy input\n const getSizeStyles = () => {\n switch (this.size) {\n case 'sm':\n return {\n height: 'min-h-[40px]',\n padding: 'px-2',\n fontSize: 'text-sm', // 14px\n labelSize: 'text-sm'\n }\n case 'lg':\n return {\n height: 'min-h-[60px]',\n padding: 'px-5',\n fontSize: 'text-lg', // 18px\n labelSize: 'text-lg'\n }\n case 'md':\n default:\n return {\n height: 'min-h-[50px]',\n padding: 'px-4',\n fontSize: 'text-base', // 16px\n labelSize: 'text-base'\n }\n }\n }\n\n const { height, padding, fontSize, labelSize } = getSizeStyles()\n\n return html`\n <div class=\"relative\">\n <!-- Screen reader live region -->\n <div id=\"live-status\" role=\"status\" aria-live=\"polite\" class=\"sr-only\"></div>\n\n <!-- Description -->\n ${this.description ? html`<div id=\"${descriptionId}\" class=\"sr-only\">${this.description}</div>` : ''}\n\n <!-- Custom input wrapper for Gmail-style chip input -->\n <slot name=\"trigger\">\n ${when(this.multi,\n () => html`\n <!-- Custom multi-select input with inline chips -->\n <div class=\"relative\">\n ${when(this.label, () => html`\n <label class=\"${classMap({\n 'block mb-1 font-medium': true,\n 'text-primary-default': !this.error,\n 'text-error-default': this.error,\n [labelSize]: true\n })}\">\n ${this.label}${this.required ? html`<span class=\"text-error-default ml-1\">*</span>` : ''}\n </label>\n `)}\n <div\n class=\"${classMap({\n 'flex flex-wrap items-center gap-1': true,\n [height]: true,\n [padding]: true,\n 'block w-full min-w-0 rounded-[8px] border-0': true,\n 'bg-surface-highest text-surface-on': true,\n 'ring-0 ring-inset focus-within:ring-1 focus-within:ring-inset': true,\n 'ring-secondary-default focus-within:ring-secondary-default': !this.error,\n 'ring-error-default focus-within:ring-error-default': this.error,\n 'cursor-text transition-colors duration-200': true\n })}\"\n @click=${() => this._focusTextInput()}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls=\"options\"\n aria-expanded=${this._open}\n >\n <!-- Render chips inline -->\n ${repeat(\n this._selectedValues$.value,\n value => value,\n value => html`\n <schmancy-input-chip\n .value=${value}\n @remove=${(e: CustomEvent) => this.handleChipRemove(e.detail.value)}\n class=\"shrink-0 my-0.5\"\n >\n ${this._getChipLabel(value)}\n </schmancy-input-chip>\n `\n )}\n\n <!-- Text input for typing -->\n <input\n ${ref(this._inputElementRef)}\n id=\"autocomplete-input\"\n type=\"text\"\n class=\"flex-1 min-w-[120px] py-1 bg-transparent border-none outline-none ${fontSize} font-medium text-surface-on placeholder:text-muted\"\n name=${this.name || this.label?.toLowerCase().replace(/\\s+/g, '-') || ''}\n .placeholder=${this._selectedValues$.value.length > 0 ? 'Add more...' : this.placeholder}\n .value=${this._inputValue}\n .autocomplete=${this.autocomplete}\n aria-invalid=${this.error ? 'true' : 'false'}\n aria-required=${this.required ? 'true' : 'false'}\n aria-describedby=${this.error && this.validationMessage ? `${this._a11yId}-err` : nothing}\n aria-label=${!this.label && this.placeholder ? this.placeholder : nothing}\n @input=${(e: Event) => {\n const value = (e.target as HTMLInputElement).value\n this._inputValue = value\n this._inputValue$.next(value)\n }}\n @focus=${(e: FocusEvent) => {\n e.stopPropagation()\n // Clear input on focus for new searches\n this._inputValue = ''\n this._inputValue$.next('')\n this._openDropdown()\n }}\n @keydown=${(e: KeyboardEvent) => {\n this._handleKeyDown(e)\n }}\n @blur=${() => {\n this._handleAutoSelectOnBlur()\n }}\n />\n </div>\n\n <!-- Validation message -->\n ${when(this.error && this.validationMessage, () => html`\n <div id=\"${this._a11yId}-err\" class=\"mt-1 text-sm text-error-default\" role=\"alert\">\n ${this.validationMessage}\n </div>\n `)}\n </div>\n `,\n () => html`\n <!-- Regular single-select input -->\n <schmancy-input\n .size=${this.size}\n ${ref(this._inputElementRef)}\n id=\"autocomplete-input\"\n class=\"w-full\"\n .name=${this.name || this.label?.toLowerCase().replace(/\\s+/g, '-') || ''}\n .label=${this.label}\n .placeholder=${this.placeholder}\n .required=${this.required}\n .value=${this._inputValue}\n type=\"text\"\n autocomplete=${this.autocomplete}\n clickable\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls=\"options\"\n aria-expanded=${this._open}\n aria-describedby=${ifDefined(this.description ? descriptionId : undefined)}\n @input=${(e: Event) => {\n const value = (e.target as HTMLInputElement).value\n this._inputValue = value\n this._inputValue$.next(value)\n }}\n @focus=${(e: FocusEvent) => {\n e.stopPropagation()\n this._openDropdown()\n }}\n @click=${(e: MouseEvent) => {\n e.stopPropagation()\n this._openDropdown()\n }}\n @keydown=${(e: KeyboardEvent) => {\n this._handleKeyDown(e)\n }}\n @blur=${() => {\n this._handleAutoSelectOnBlur()\n }}\n >\n </schmancy-input>\n `\n )}\n </slot>\n\n <!-- Options dropdown -->\n <ul\n id=\"options\"\n class=${classMap({\n 'absolute': true,\n 'z-[1000]': true,\n 'mt-1': true,\n 'w-full': true,\n 'rounded-md': true,\n 'shadow-md': true,\n 'overflow-auto': true,\n 'min-w-full': true,\n 'bg-surface-low': true,\n 'flex': true,\n 'flex-col': true, // Enable flexbox for ordering\n })}\n role=\"listbox\"\n aria-multiselectable=${this.multi ? 'true' : 'false'}\n aria-label=${`${this.label || 'Options'} dropdown`}\n ?hidden=${!this._open}\n style=\"max-height: ${this.maxHeight}; display: ${this._open ? 'flex' : 'none'};\"\n @slotchange=${() => {\n this._setupOptionHandlers()\n }}\n >\n <slot></slot>\n ${!this._hasResults ? html`\n <li class=\"px-3 py-2 text-sm text-muted\">No results found</li>\n ` : ''}\n </ul>\n </div>\n `\n }\n\n private _handleAutoSelectOnBlur() {\n // Only auto-select in single-select mode and when dropdown is open with a search term\n if (this.multi || !this._open || !this._inputValue.trim()) {\n return\n }\n \n const searchTerm = this._inputValue.trim()\n \n // Find the best matching option using the same similarity logic as filtering\n let bestMatch: SchmancyOption | null = null\n let bestScore = 0\n \n this._options.forEach(option => {\n // Skip hidden options\n if (option.hidden) return\n \n // Get text to search in (prioritize label, then textContent, then value)\n const optionLabel = option.label || option.textContent || ''\n const optionValue = option.value\n \n // Calculate similarity scores for both label and value\n const labelScore = similarity(searchTerm, optionLabel)\n const valueScore = similarity(searchTerm, optionValue)\n \n // Use the higher score (prioritizing label matches)\n const score = Math.max(labelScore * 1.1, valueScore) // Slight boost for label matches\n \n // Keep track of best match that meets threshold\n if (score > bestScore && score >= this.similarityThreshold) {\n bestScore = score\n bestMatch = option\n }\n })\n \n // Auto-select the best match if found\n if (bestMatch) {\n // Silently update the selected value without firing change event\n this._selectedValue$.next(bestMatch.value)\n this._inputValue = bestMatch.label || bestMatch.textContent || ''\n this._inputValue$.next(this._inputValue)\n this._open = false\n }\n }\n\n private _handleKeyDown(event: KeyboardEvent) {\n const isOpen = this._open\n const selectedValues = this._selectedValues$.value\n\n // Handle backspace to remove last chip in multi-select when input is empty\n if (this.multi && event.key === 'Backspace' && !this._inputValue && selectedValues.length > 0 && !isOpen) {\n event.preventDefault()\n const lastValue = selectedValues[selectedValues.length - 1]\n this.handleChipRemove(lastValue)\n return\n }\n\n if (!isOpen && (event.key === 'ArrowDown' || event.key === 'Enter')) {\n event.preventDefault()\n this._openDropdown()\n\n timer(10)\n .pipe(takeUntil(this.disconnecting))\n .subscribe(() => {\n const firstVisible = this._options.find(opt => !opt.hidden)\n firstVisible?.focus()\n })\n return\n }\n\n if (!isOpen) return\n\n const visibleOptions = this._options.filter(opt => !opt.hidden)\n .toSorted((a, b) => parseInt(a.style.order || '0') - parseInt(b.style.order || '0'))\n\n const focusedOption = visibleOptions.find(opt => opt === document.activeElement)\n const currentIndex = focusedOption ? visibleOptions.indexOf(focusedOption) : -1\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault()\n this._open = false\n this._updateInputDisplay()\n this._inputElementRef.value?.focus()\n break\n\n case 'Tab':\n this._open = false\n this._updateInputDisplay()\n break\n\n case 'ArrowDown':\n event.preventDefault()\n const nextIndex = currentIndex < visibleOptions.length - 1 ? currentIndex + 1 : 0\n visibleOptions[nextIndex]?.focus()\n break\n\n case 'ArrowUp':\n event.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : visibleOptions.length - 1\n visibleOptions[prevIndex]?.focus()\n break\n\n case 'Home':\n event.preventDefault()\n visibleOptions[0]?.focus()\n break\n\n case 'End':\n event.preventDefault()\n visibleOptions[visibleOptions.length - 1]?.focus()\n break\n\n case 'Enter':\n case ' ':\n if (focusedOption) {\n event.preventDefault()\n this._selectOption(focusedOption)\n }\n break\n }\n }\n}\n\n\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'schmancy-autocomplete': SchmancyAutocomplete\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"autocomplete-Mrb3koUN.js","names":[],"sources":["../src/form/fields/autocomplete/autocomplete.scss?inline","../src/form/fields/autocomplete/autocomplete.ts"],"sourcesContent":[":host {\n\tdisplay: block;\n\tborder: unset !important;\n\tline-height: unset !important;\n\tbackground: unset !important;\n\tpadding: unset !important;\n\tfont-size: unset !important;\n\tbox-shadow: unset !important;\n}\n\n:host:focus {\n\tbox-shadow: unset !important;\n}\n\n@keyframes onAutoFillStart {\n\tfrom {/**/}\n\tto {/**/}\n}\n\nsch-input::part(input):-webkit-autofill,\nsch-input input:-webkit-autofill {\n\tanimation-name: onAutoFillStart;\n\tanimation-duration: 1ms;\n}\n","import { SchmancyFormField } from '@mixins/index'\nimport { InputSize, SchmancyInput } from '@schmancy/input'\nimport SchmancyOption from '@schmancy/option/option'\nimport { html, nothing, unsafeCSS } from 'lit'\nimport { customElement, property, query, queryAssignedElements, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { when } from 'lit/directives/when.js'\nimport {\n BehaviorSubject,\n combineLatest,\n fromEvent,\n timer\n} from 'rxjs'\nimport {\n debounceTime,\n distinctUntilChanged,\n takeUntil,\n tap\n} from 'rxjs/operators'\nimport style from './autocomplete.scss?inline'\n\n// Import the similarity function (or include it inline)\nimport { similarity } from '../../../utils/search'\n// Import chip component for multi-select display\nimport '../../../chips/input-chip'\n\nexport type SchmancyAutocompleteChangeEvent = CustomEvent<{\n value: string | string[]\n values?: string[]\n}>\n\ninterface FilteredOption {\n option: SchmancyOption\n score: number\n}\n\n/**\n * Autocomplete input component with filtering and multi-select support.\n *\n * @prop {string} name - Name attribute for form submission\n * @prop {string} label - Label text displayed above the input\n * @prop {string} placeholder - Placeholder text for the input\n * @prop {boolean} required - Whether the field is required\n * @prop {boolean} multi - Enable multi-select mode\n * @prop {string} value - Selected value (single select mode)\n * @prop {string[]} values - Selected values (multi-select mode)\n */\n@customElement('schmancy-autocomplete')\nexport default class SchmancyAutocomplete extends SchmancyFormField(unsafeCSS(style)) {\n\n // `formAssociated`, `internals`, `attachInternals`, `name`, `label`,\n // `required`, `disabled`, `error`, `validationMessage`, `hint`, `id`,\n // `validateOn`, `touched/dirty/submitted`, `markTouched/markSubmitted`,\n // `setCustomValidity`, `formDisabledCallback`, FIELD_CONNECT_EVENT dispatch\n // — all from the mixin.\n\n /** Override mixin's resetForm with autocomplete-specific subject reset. */\n override resetForm(): void {\n if (this.multi) {\n this._selectedValues$.next([])\n } else {\n this._selectedValue$.next('')\n }\n this._inputValue = ''\n this._inputValue$.next('')\n super.resetForm()\n }\n\n // Track whether value/values have been explicitly set\n _valueSet: boolean = false\n _valuesSet: boolean = false\n\n // Autocomplete-specific properties only — `name`, `label`, `required`,\n // `error`, `validationMessage` come from the mixin.\n @property({ type: String }) placeholder = ''\n @property({ type: String }) maxHeight = '300px'\n @property({ type: Boolean }) multi = false\n @property({ type: String }) description = ''\n @property({ type: String, reflect: true }) size: InputSize = 'md'\n @property({ type: String }) autocomplete = 'off'\n @property({ type: Number }) debounceMs = 200\n @property({ type: Number }) similarityThreshold = 0.3 // Minimum similarity score to show option\n\n private readonly _a11yId = `schmancy-autocomplete-${Math.random().toString(36).slice(2, 10)}`\n\n // Values property for multi-select mode\n @property({ type: Array })\n get values() {\n return [...this._selectedValues$.value]\n }\n set values(vals: string[]) {\n this._valuesSet = true\n this._selectedValues$.next(Array.isArray(vals) ? [...vals] : [])\n }\n\n // Value property — narrowed override of the mixin's wide value union.\n @property({ type: String, reflect: true })\n override get value(): string {\n return this.multi\n ? this._selectedValues$.value.join(',')\n : this._selectedValue$.value\n }\n override set value(val: string) {\n this._valueSet = true\n if (this.multi) {\n const newValues = val ? val.split(',').map(v => v.trim()).filter(Boolean) : []\n const currentValues = this._selectedValues$.value\n // Only update if values actually changed\n if (JSON.stringify(newValues) !== JSON.stringify(currentValues)) {\n this._selectedValues$.next(newValues)\n }\n } else {\n // Only update if value actually changed\n if (val !== this._selectedValue$.value) {\n this._selectedValue$.next(val)\n // Update the input display when value is set\n this._updateInputDisplay()\n }\n }\n }\n\n // State\n @state() private _open = false\n @state() private _inputValue = ''\n @state() private _visibleOptionsCount = 0\n @state() private _hasResults = true\n\n // DOM references\n @query('#options') _listbox!: HTMLUListElement\n @query('sch-input') _input!: SchmancyInput\n @queryAssignedElements({ flatten: true }) private _options!: SchmancyOption[]\n private _inputElementRef = createRef<HTMLInputElement>()\n\n // RxJS Subjects - only what we actually need\n private _selectedValue$ = new BehaviorSubject<string>('')\n private _selectedValues$ = new BehaviorSubject<string[]>([])\n private _inputValue$ = new BehaviorSubject<string>('')\n\n override connectedCallback() {\n // FIELD_CONNECT_EVENT is dispatched by the mixin's connectedCallback.\n super.connectedCallback()\n this._setupAutocompleteLogic()\n this._setupDocumentClickHandler()\n }\n\n private _setupAutocompleteLogic() {\n // Sync selection state\n combineLatest([\n this._selectedValue$,\n this._selectedValues$\n ]).pipe(\n tap(([selectedValue, selectedValues]) => {\n this._updateOptionSelection(selectedValue, selectedValues)\n // Keep ElementInternals form value in sync with selection (single and multi).\n const formValue = this.multi ? selectedValues.join(',') : selectedValue\n this.internals?.setFormValue(formValue || null)\n if (this.required) {\n const missing = this.multi ? selectedValues.length === 0 : !selectedValue\n this.internals?.setValidity(\n missing ? { valueMissing: true } : {},\n missing ? this.validationMessage || 'Please select an option.' : undefined,\n )\n }\n }),\n takeUntil(this.disconnecting)\n ).subscribe()\n\n // Filter options based on input\n this._inputValue$.pipe(\n distinctUntilChanged(),\n debounceTime(this.debounceMs),\n tap(searchTerm => {\n if (this._open) {\n this._filterOptions(searchTerm)\n }\n }),\n takeUntil(this.disconnecting)\n ).subscribe()\n }\n\n private _setupOptionHandlers() {\n this._options.forEach((option, index) => {\n option.setAttribute('role', 'option')\n option.tabIndex = -1\n if (!option.id) {\n option.id = `${this.id}-option-${index}`\n }\n // Idempotent: slotchange may fire repeatedly for the same option nodes,\n // and addEventListener doesn't replace prior handlers like onfoo= did.\n if (option.dataset.schmancyAutocompleteHandlers === 'attached') return\n option.dataset.schmancyAutocompleteHandlers = 'attached'\n\n // Prevent blur handler from interfering with option selection\n fromEvent<MouseEvent>(option, 'mousedown')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => e.preventDefault())\n\n // Handle the actual selection\n fromEvent<MouseEvent>(option, 'click')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => {\n e.stopPropagation()\n this._selectOption(option)\n })\n })\n }\n\n private _updateOptionSelection(selectedValue: string, selectedValues: string[]) {\n this._options.forEach(option => {\n option.selected = this.multi\n ? selectedValues.includes(option.value)\n : option.value === selectedValue\n option.setAttribute('aria-selected', String(option.selected))\n })\n }\n\n private _filterOptions(searchTerm: string) {\n const term = searchTerm.trim()\n\n if (!term) {\n // Show all options if no search term\n this._options.forEach(option => {\n option.hidden = false\n option.style.order = '0'\n })\n this._visibleOptionsCount = this._options.length\n this._hasResults = true\n } else {\n // Calculate similarity scores for all options\n const scoredOptions: FilteredOption[] = this._options.map(option => {\n const optionLabel = option.label || option.textContent || ''\n const optionValue = option.value\n\n const labelScore = similarity(term, optionLabel)\n const valueScore = similarity(term, optionValue)\n const score = Math.max(labelScore * 1.1, valueScore)\n\n return { option, score }\n })\n\n // Sort by score (highest first)\n scoredOptions.sort((a, b) => b.score - a.score)\n\n // Apply visibility and ordering\n let visibleCount = 0\n scoredOptions.forEach((item, index) => {\n const { option, score } = item\n\n if (score < this.similarityThreshold) {\n option.hidden = true\n } else {\n option.hidden = false\n visibleCount++\n option.style.order = String(index)\n }\n })\n\n this._visibleOptionsCount = visibleCount\n this._hasResults = visibleCount > 0\n }\n\n this._announceToScreenReader(\n this._visibleOptionsCount > 0\n ? `${this._visibleOptionsCount} option${this._visibleOptionsCount === 1 ? '' : 's'} available.`\n : 'No results found.'\n )\n }\n\n private _openDropdown() {\n this._open = true\n // Reset filters based on current input value when dropdown opens\n this._filterOptions(this._inputValue)\n }\n\n private _selectOption(option: SchmancyOption) {\n if (this.multi) {\n const currentValues = this._selectedValues$.value\n const index = currentValues.indexOf(option.value)\n const newValues = index > -1\n ? currentValues.filter(v => v !== option.value)\n : [...currentValues, option.value]\n\n this._selectedValues$.next(newValues)\n this._announceToScreenReader(\n newValues.length > 0\n ? `Selected: ${this._getSelectedLabels().join(', ')}`\n : 'No options selected'\n )\n this._fireChangeEvent()\n } else {\n // Update value first\n this._selectedValue$.next(option.value)\n\n // Close dropdown IMMEDIATELY to prevent blur handler from firing\n this._open = false\n\n // Now fire event with the NEW value\n this._fireChangeEvent()\n\n // Update UI\n this._inputValue = option.label || option.textContent || ''\n this._inputValue$.next(this._inputValue)\n\n this._announceToScreenReader(`Selected: ${option.label || option.textContent}`)\n }\n }\n\n private _setupDocumentClickHandler() {\n fromEvent<MouseEvent>(document, 'click')\n .pipe(takeUntil(this.disconnecting))\n .subscribe(e => {\n if (!this._open) return\n const path = e.composedPath()\n if (!path.includes(this) && !this._options.some(opt => path.includes(opt))) {\n this._open = false\n this._updateInputDisplay()\n }\n })\n }\n\n\n private _updateInputDisplay() {\n // For multi-select, we don't update input display since chips show the selections\n if (this.multi) return\n\n const selectedValue = this._selectedValue$.value\n const option = this._options.find(opt => opt.value === selectedValue)\n this._inputValue = option ? option.label || option.textContent || '' : ''\n this._inputValue$.next(this._inputValue)\n\n if (this._inputElementRef.value) {\n this._inputElementRef.value.value = this._inputValue\n }\n }\n\n private _getSelectedLabels(): string[] {\n return this._options\n .filter(option => \n this.multi \n ? this._selectedValues$.value.includes(option.value)\n : option.value === this._selectedValue$.value\n )\n .map(option => option.label || option.textContent || '')\n }\n\n private _announceToScreenReader(message: string) {\n const liveRegion = this.shadowRoot?.querySelector('#live-status')\n if (liveRegion) {\n liveRegion.textContent = message\n }\n }\n\n private _fireChangeEvent() {\n const detail: SchmancyAutocompleteChangeEvent['detail'] = {\n value: this.value,\n }\n\n if (this.multi) {\n detail.values = [...this._selectedValues$.value]\n }\n\n this.dispatchEvent(\n new CustomEvent<SchmancyAutocompleteChangeEvent['detail']>('change', {\n detail,\n bubbles: true,\n composed: true,\n })\n )\n }\n\n public checkValidity(): boolean {\n if (!this.required) return true\n return this.multi \n ? this._selectedValues$.value.length > 0 \n : Boolean(this._selectedValue$.value)\n }\n\n public reportValidity(): boolean {\n if (this._inputElementRef.value) {\n return this._inputElementRef.value.reportValidity()\n }\n return this.checkValidity()\n }\n\n firstUpdated() {\n this._setupOptionHandlers()\n\n // Sync initial value with display after options are available\n this._updateInputDisplay()\n\n // Update options when slot changes\n const slot = this.shadowRoot?.querySelector('slot')\n slot?.addEventListener('slotchange', () => {\n this._setupOptionHandlers()\n this._updateOptionSelection(this._selectedValue$.value, this._selectedValues$.value)\n })\n }\n\n private handleChipRemove(value: string) {\n const currentValues = this._selectedValues$.value\n const newValues = currentValues.filter(v => v !== value)\n this._selectedValues$.next(newValues)\n this._fireChangeEvent()\n this._announceToScreenReader(`Removed: ${this._getChipLabel(value)}`)\n }\n\n private _getChipLabel(value: string): string {\n const option = this._options.find(opt => opt.value === value)\n return option ? option.label || option.textContent || value : value\n }\n\n private _focusTextInput() {\n if (this._inputElementRef.value) {\n this._inputElementRef.value.focus()\n }\n }\n\n render() {\n const descriptionId = `${this.id}-desc`\n\n // Get size-based styling to match Schmancy input\n const getSizeStyles = () => {\n switch (this.size) {\n case 'sm':\n return {\n height: 'min-h-[40px]',\n padding: 'px-2',\n fontSize: 'text-sm', // 14px\n labelSize: 'text-sm'\n }\n case 'lg':\n return {\n height: 'min-h-[60px]',\n padding: 'px-5',\n fontSize: 'text-lg', // 18px\n labelSize: 'text-lg'\n }\n case 'md':\n default:\n return {\n height: 'min-h-[50px]',\n padding: 'px-4',\n fontSize: 'text-base', // 16px\n labelSize: 'text-base'\n }\n }\n }\n\n const { height, padding, fontSize, labelSize } = getSizeStyles()\n\n return html`\n <div class=\"relative\">\n <!-- Screen reader live region -->\n <div id=\"live-status\" role=\"status\" aria-live=\"polite\" class=\"sr-only\"></div>\n\n <!-- Description -->\n ${this.description ? html`<div id=\"${descriptionId}\" class=\"sr-only\">${this.description}</div>` : ''}\n\n <!-- Custom input wrapper for Gmail-style chip input -->\n <slot name=\"trigger\">\n ${when(this.multi,\n () => html`\n <!-- Custom multi-select input with inline chips -->\n <div class=\"relative\">\n ${when(this.label, () => html`\n <label class=\"${classMap({\n 'block mb-1 font-medium': true,\n 'text-primary-default': !this.error,\n 'text-error-default': this.error,\n [labelSize]: true\n })}\">\n ${this.label}${this.required ? html`<span class=\"text-error-default ml-1\">*</span>` : ''}\n </label>\n `)}\n <div\n class=\"${classMap({\n 'flex flex-wrap items-center gap-1': true,\n [height]: true,\n [padding]: true,\n 'block w-full min-w-0 rounded-[8px] border-0': true,\n 'bg-surface-highest text-surface-on': true,\n 'ring-0 ring-inset focus-within:ring-1 focus-within:ring-inset': true,\n 'ring-secondary-default focus-within:ring-secondary-default': !this.error,\n 'ring-error-default focus-within:ring-error-default': this.error,\n 'cursor-text transition-colors duration-200': true\n })}\"\n @click=${() => this._focusTextInput()}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls=\"options\"\n aria-expanded=${this._open}\n >\n <!-- Render chips inline -->\n ${repeat(\n this._selectedValues$.value,\n value => value,\n value => html`\n <schmancy-input-chip\n .value=${value}\n @remove=${(e: CustomEvent) => this.handleChipRemove(e.detail.value)}\n class=\"shrink-0 my-0.5\"\n >\n ${this._getChipLabel(value)}\n </schmancy-input-chip>\n `\n )}\n\n <!-- Text input for typing -->\n <input\n ${ref(this._inputElementRef)}\n id=\"autocomplete-input\"\n type=\"text\"\n class=\"flex-1 min-w-[120px] py-1 bg-transparent border-none outline-none ${fontSize} font-medium text-surface-on placeholder:text-muted\"\n name=${this.name || this.label?.toLowerCase().replace(/\\s+/g, '-') || ''}\n .placeholder=${this._selectedValues$.value.length > 0 ? 'Add more...' : this.placeholder}\n .value=${this._inputValue}\n .autocomplete=${this.autocomplete}\n aria-invalid=${this.error ? 'true' : 'false'}\n aria-required=${this.required ? 'true' : 'false'}\n aria-describedby=${this.error && this.validationMessage ? `${this._a11yId}-err` : nothing}\n aria-label=${!this.label && this.placeholder ? this.placeholder : nothing}\n @input=${(e: Event) => {\n const value = (e.target as HTMLInputElement).value\n this._inputValue = value\n this._inputValue$.next(value)\n }}\n @focus=${(e: FocusEvent) => {\n e.stopPropagation()\n // Clear input on focus for new searches\n this._inputValue = ''\n this._inputValue$.next('')\n this._openDropdown()\n }}\n @keydown=${(e: KeyboardEvent) => {\n this._handleKeyDown(e)\n }}\n @blur=${() => {\n this._handleAutoSelectOnBlur()\n }}\n />\n </div>\n\n <!-- Validation message -->\n ${when(this.error && this.validationMessage, () => html`\n <div id=\"${this._a11yId}-err\" class=\"mt-1 text-sm text-error-default\" role=\"alert\">\n ${this.validationMessage}\n </div>\n `)}\n </div>\n `,\n () => html`\n <!-- Regular single-select input -->\n <schmancy-input\n .size=${this.size}\n ${ref(this._inputElementRef)}\n id=\"autocomplete-input\"\n class=\"w-full\"\n .name=${this.name || this.label?.toLowerCase().replace(/\\s+/g, '-') || ''}\n .label=${this.label}\n .placeholder=${this.placeholder}\n .required=${this.required}\n .value=${this._inputValue}\n type=\"text\"\n autocomplete=${this.autocomplete}\n clickable\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls=\"options\"\n aria-expanded=${this._open}\n aria-describedby=${ifDefined(this.description ? descriptionId : undefined)}\n @input=${(e: Event) => {\n const value = (e.target as HTMLInputElement).value\n this._inputValue = value\n this._inputValue$.next(value)\n }}\n @focus=${(e: FocusEvent) => {\n e.stopPropagation()\n this._openDropdown()\n }}\n @click=${(e: MouseEvent) => {\n e.stopPropagation()\n this._openDropdown()\n }}\n @keydown=${(e: KeyboardEvent) => {\n this._handleKeyDown(e)\n }}\n @blur=${() => {\n this._handleAutoSelectOnBlur()\n }}\n >\n </schmancy-input>\n `\n )}\n </slot>\n\n <!-- Options dropdown -->\n <ul\n id=\"options\"\n class=${classMap({\n 'absolute': true,\n 'z-[1000]': true,\n 'mt-1': true,\n 'w-full': true,\n 'rounded-md': true,\n 'shadow-md': true,\n 'overflow-auto': true,\n 'min-w-full': true,\n 'bg-surface-low': true,\n 'flex': true,\n 'flex-col': true, // Enable flexbox for ordering\n })}\n role=\"listbox\"\n aria-multiselectable=${this.multi ? 'true' : 'false'}\n aria-label=${`${this.label || 'Options'} dropdown`}\n ?hidden=${!this._open}\n style=\"max-height: ${this.maxHeight}; display: ${this._open ? 'flex' : 'none'};\"\n @slotchange=${() => {\n this._setupOptionHandlers()\n }}\n >\n <slot></slot>\n ${!this._hasResults ? html`\n <li class=\"px-3 py-2 text-sm text-muted\">No results found</li>\n ` : ''}\n </ul>\n </div>\n `\n }\n\n private _handleAutoSelectOnBlur() {\n // Only auto-select in single-select mode and when dropdown is open with a search term\n if (this.multi || !this._open || !this._inputValue.trim()) {\n return\n }\n \n const searchTerm = this._inputValue.trim()\n \n // Find the best matching option using the same similarity logic as filtering\n let bestMatch: SchmancyOption | null = null\n let bestScore = 0\n \n this._options.forEach(option => {\n // Skip hidden options\n if (option.hidden) return\n \n // Get text to search in (prioritize label, then textContent, then value)\n const optionLabel = option.label || option.textContent || ''\n const optionValue = option.value\n \n // Calculate similarity scores for both label and value\n const labelScore = similarity(searchTerm, optionLabel)\n const valueScore = similarity(searchTerm, optionValue)\n \n // Use the higher score (prioritizing label matches)\n const score = Math.max(labelScore * 1.1, valueScore) // Slight boost for label matches\n \n // Keep track of best match that meets threshold\n if (score > bestScore && score >= this.similarityThreshold) {\n bestScore = score\n bestMatch = option\n }\n })\n \n // Auto-select the best match if found\n if (bestMatch) {\n // Silently update the selected value without firing change event\n this._selectedValue$.next(bestMatch.value)\n this._inputValue = bestMatch.label || bestMatch.textContent || ''\n this._inputValue$.next(this._inputValue)\n this._open = false\n }\n }\n\n private _handleKeyDown(event: KeyboardEvent) {\n const isOpen = this._open\n const selectedValues = this._selectedValues$.value\n\n // Handle backspace to remove last chip in multi-select when input is empty\n if (this.multi && event.key === 'Backspace' && !this._inputValue && selectedValues.length > 0 && !isOpen) {\n event.preventDefault()\n const lastValue = selectedValues[selectedValues.length - 1]\n this.handleChipRemove(lastValue)\n return\n }\n\n if (!isOpen && (event.key === 'ArrowDown' || event.key === 'Enter')) {\n event.preventDefault()\n this._openDropdown()\n\n timer(10)\n .pipe(takeUntil(this.disconnecting))\n .subscribe(() => {\n const firstVisible = this._options.find(opt => !opt.hidden)\n firstVisible?.focus()\n })\n return\n }\n\n if (!isOpen) return\n\n const visibleOptions = this._options.filter(opt => !opt.hidden)\n .toSorted((a, b) => parseInt(a.style.order || '0') - parseInt(b.style.order || '0'))\n\n const focusedOption = visibleOptions.find(opt => opt === document.activeElement)\n const currentIndex = focusedOption ? visibleOptions.indexOf(focusedOption) : -1\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault()\n this._open = false\n this._updateInputDisplay()\n this._inputElementRef.value?.focus()\n break\n\n case 'Tab':\n this._open = false\n this._updateInputDisplay()\n break\n\n case 'ArrowDown':\n event.preventDefault()\n const nextIndex = currentIndex < visibleOptions.length - 1 ? currentIndex + 1 : 0\n visibleOptions[nextIndex]?.focus()\n break\n\n case 'ArrowUp':\n event.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : visibleOptions.length - 1\n visibleOptions[prevIndex]?.focus()\n break\n\n case 'Home':\n event.preventDefault()\n visibleOptions[0]?.focus()\n break\n\n case 'End':\n event.preventDefault()\n visibleOptions[visibleOptions.length - 1]?.focus()\n break\n\n case 'Enter':\n case ' ':\n if (focusedOption) {\n event.preventDefault()\n this._selectOption(focusedOption)\n }\n break\n }\n }\n}\n\n\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'schmancy-autocomplete': SchmancyAutocomplete\n }\n}\n"],"mappings":"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"}
|
package/dist/autocomplete.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require(`./autocomplete-
|
|
1
|
+
require(`./autocomplete-B8CE5vGw.cjs`);
|
package/dist/autocomplete.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import "./autocomplete-
|
|
1
|
+
import "./autocomplete-Mrb3koUN.js";
|
package/dist/avatar.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunk-CncqDLb2.cjs`);const e=require(`./mixins-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunk-CncqDLb2.cjs`);const e=require(`./mixins-Du9HMrIG.cjs`),t=require(`./active-host-jH3iloCR.cjs`),n=require(`./directives.cjs`),r=require(`./theme.interface-D4NeufQA.cjs`);let i=require(`lit/decorators.js`),a=require(`lit`);var o=class extends e.c{constructor(...e){super(...e),this.initials=``,this.src=``,this.icon=``,this.size=`md`,this.color=`primary`,this.shape=`circle`,this.bordered=!1,this.status=`none`}render(){let e;e=this.src?a.html`<img class="w-full h-full object-cover" src="${this.src}" alt="Avatar" />`:this.initials?a.html`<span class="text-center font-medium">${this.initials.substring(0,2).toUpperCase()}</span>`:this.icon?a.html`<schmancy-icon>${this.icon}</schmancy-icon>`:a.html`<schmancy-icon>person</schmancy-icon>`;let t={"relative flex items-center justify-center overflow-hidden":!0,[{xxs:`w-5 h-5 text-[8px]`,xs:`w-6 h-6 text-xs`,sm:`w-8 h-8 text-sm`,md:`w-10 h-10 text-base`,lg:`w-12 h-12 text-lg`,xl:`w-16 h-16 text-xl`}[this.size]]:!0,[{circle:`rounded-full`,square:`rounded-md`}[this.shape]]:!0,"border-2 border-surface-container":this.bordered},n=this.getColorAttributes();return a.html`
|
|
2
2
|
<div class="${this.classMap(t)}" ${n}>
|
|
3
3
|
${e} ${this.status===`none`?``:this.renderStatusIndicator()}
|
|
4
4
|
</div>
|
package/dist/avatar.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { c as e } from "./mixins-
|
|
1
|
+
import { c as e } from "./mixins-DCVXqL1Q.js";
|
|
2
2
|
import { a as t } from "./active-host-BP0zy_Y9.js";
|
|
3
3
|
import { color as n } from "./directives.js";
|
|
4
|
-
import { t as r } from "./theme.interface-
|
|
4
|
+
import { t as r } from "./theme.interface-C2XNgsLB.js";
|
|
5
5
|
import { customElement as i, property as a } from "lit/decorators.js";
|
|
6
6
|
import { html as o } from "lit";
|
|
7
7
|
var s = class extends e {
|
package/dist/avatar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.js","names":[],"sources":["../src/avatar/avatar.ts"],"sourcesContent":["import { SchmancyElement } from '@mixins/index'\nimport { html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { color } from '@schmancy/directives'\nimport { SchmancyTheme } from '@schmancy/theme/theme.interface'\n\n/**\n * M3 avatar sizes: 20dp → 24dp → 32dp → 40dp → 48dp → 64dp\n * - xxs: Ultra-compact (20px) - for menu cards\n * - xs: 24px - M3 compact\n * - sm: 32px - M3 small\n * - md: 40px - M3 medium (default)\n * - lg: 48px - M3 large\n * - xl: 64px - M3 extra large\n */\nexport type AvatarSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nexport type AvatarColor = 'primary' | 'secondary' | 'tertiary' | 'success' | 'error' | 'neutral'\nexport type AvatarShape = 'circle' | 'square'\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away' | 'none'\n\n/**\n * A customizable avatar component that displays initials or an icon\n * Designed to match the Schmancy design system\n *\n * @element schmancy-avatar\n *\n * @property {string} initials - Text initials to display (limited to 2 characters)\n * @property {string} src - URL of an image to display\n * @property {string} icon - Name of an icon to display\n * @property {AvatarSize} size - Size of the avatar (xs, sm, md, lg, xl)\n * @property {AvatarColor} color - Color theme of the avatar\n * @property {AvatarShape} shape - Shape of the avatar (circle or square)\n * @property {boolean} bordered - Whether to add a border around the avatar\n * @property {AvatarStatus} status - Optional status indicator to display\n *\n * @example\n * <schmancy-avatar\n * initials=\"JD\"\n * size=\"md\"\n * color=\"primary\"\n * ></schmancy-avatar>\n */\n@customElement('schmancy-avatar')\nexport class SchmancyAvatar extends SchmancyElement {\n\t@property({ type: String }) initials: string = ''\n\t@property({ type: String }) src: string = ''\n\t@property({ type: String }) icon: string = ''\n\t@property({ type: String }) size: AvatarSize = 'md'\n\t@property({ type: String }) color: AvatarColor = 'primary'\n\t@property({ type: String }) shape: AvatarShape = 'circle'\n\t@property({ type: Boolean }) bordered: boolean = false\n\t@property({ type: String }) status: AvatarStatus = 'none'\n\n\trender() {\n\t\t// Determine content to display (image, initials, or icon)\n\t\tlet content\n\t\tif (this.src) {\n\t\t\tcontent = html`<img class=\"w-full h-full object-cover\" src=\"${this.src}\" alt=\"Avatar\" />`\n\t\t} else if (this.initials) {\n\t\t\tcontent = html`<span class=\"text-center font-medium\">${this.initials.substring(0, 2).toUpperCase()}</span>`\n\t\t} else if (this.icon) {\n\t\t\tcontent = html`<schmancy-icon>${this.icon}</schmancy-icon>`\n\t\t} else {\n\t\t\tcontent = html`<schmancy-icon>person</schmancy-icon>`\n\t\t}\n\n\t\t// Size classes - M3 aligned: 20dp → 24dp → 32dp → 40dp → 48dp → 64dp\n\t\tconst sizeClasses = {\n\t\t\txxs: 'w-5 h-5 text-[8px]', // 20px - Ultra-compact\n\t\t\txs: 'w-6 h-6 text-xs', // 24px - M3 compact\n\t\t\tsm: 'w-8 h-8 text-sm', // 32px - M3 small\n\t\t\tmd: 'w-10 h-10 text-base', // 40px - M3 medium (default)\n\t\t\tlg: 'w-12 h-12 text-lg', // 48px - M3 large\n\t\t\txl: 'w-16 h-16 text-xl', // 64px - M3 extra large\n\t\t}\n\n\t\t// Shape classes\n\t\tconst shapeClasses = {\n\t\t\tcircle: 'rounded-full',\n\t\t\tsquare: 'rounded-md',\n\t\t}\n\n\t\t// Combine classes\n\t\tconst avatarClasses = {\n\t\t\t'relative flex items-center justify-center overflow-hidden': true,\n\t\t\t[sizeClasses[this.size]]: true,\n\t\t\t[shapeClasses[this.shape]]: true,\n\t\t\t'border-2 border-surface-container': this.bordered,\n\t\t}\n\n\t\t// Get theme colors\n\t\tconst colorAttrs = this.getColorAttributes()\n\n\t\treturn html`\n\t\t\t<div class=\"${this.classMap(avatarClasses)}\" ${colorAttrs}>\n\t\t\t\t${content} ${this.status !== 'none' ? this.renderStatusIndicator() : ''}\n\t\t\t</div>\n\t\t`\n\t}\n\n\tprivate getColorAttributes() {\n\t\tconst colorMap = {\n\t\t\tprimary: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.primary.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.primary.onContainer,\n\t\t\t},\n\t\t\tsecondary: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.secondary.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.secondary.onContainer,\n\t\t\t},\n\t\t\ttertiary: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.tertiary.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.tertiary.onContainer,\n\t\t\t},\n\t\t\tsuccess: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.success.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.success.onContainer,\n\t\t\t},\n\t\t\terror: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.error.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.error.onContainer,\n\t\t\t},\n\t\t\tneutral: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.surface.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.surface.on,\n\t\t\t},\n\t\t}\n\n\t\treturn color(colorMap[this.color])\n\t}\n\n\tprivate renderStatusIndicator() {\n\t\tconst statusColors = {\n\t\t\tonline: SchmancyTheme.sys.color.success.default,\n\t\t\toffline: SchmancyTheme.sys.color.surface.onVariant,\n\t\t\tbusy: SchmancyTheme.sys.color.error.default,\n\t\t\taway: SchmancyTheme.sys.color.tertiary.default,\n\t\t}\n\n\t\tconst sizeMap = {\n\t\t\txxs: 'w-1 h-1',\n\t\t\txs: 'w-1.5 h-1.5',\n\t\t\tsm: 'w-2 h-2',\n\t\t\tmd: 'w-2.5 h-2.5',\n\t\t\tlg: 'w-3 h-3',\n\t\t\txl: 'w-4 h-4',\n\t\t}\n\n\t\tconst statusClasses = {\n\t\t\t'absolute bottom-0 right-0 rounded-full border-2 border-surface-default': true,\n\t\t\t[sizeMap[this.size]]: true,\n\t\t}\n\n\t\treturn html`\n\t\t\t<div class=\"${this.classMap(statusClasses)}\" style=\"background-color: ${statusColors[this.status]};\"></div>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-avatar': SchmancyAvatar\n\t}\n}\n"],"mappings":";;;;;;AA2CO,IAAA,IAAA,cAA6B,EAAA;CAAA,YAAA,GAAA,GAAA;
|
|
1
|
+
{"version":3,"file":"avatar.js","names":[],"sources":["../src/avatar/avatar.ts"],"sourcesContent":["import { SchmancyElement } from '@mixins/index'\nimport { html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { color } from '@schmancy/directives'\nimport { SchmancyTheme } from '@schmancy/theme/theme.interface'\n\n/**\n * M3 avatar sizes: 20dp → 24dp → 32dp → 40dp → 48dp → 64dp\n * - xxs: Ultra-compact (20px) - for menu cards\n * - xs: 24px - M3 compact\n * - sm: 32px - M3 small\n * - md: 40px - M3 medium (default)\n * - lg: 48px - M3 large\n * - xl: 64px - M3 extra large\n */\nexport type AvatarSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nexport type AvatarColor = 'primary' | 'secondary' | 'tertiary' | 'success' | 'error' | 'neutral'\nexport type AvatarShape = 'circle' | 'square'\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away' | 'none'\n\n/**\n * A customizable avatar component that displays initials or an icon\n * Designed to match the Schmancy design system\n *\n * @element schmancy-avatar\n *\n * @property {string} initials - Text initials to display (limited to 2 characters)\n * @property {string} src - URL of an image to display\n * @property {string} icon - Name of an icon to display\n * @property {AvatarSize} size - Size of the avatar (xs, sm, md, lg, xl)\n * @property {AvatarColor} color - Color theme of the avatar\n * @property {AvatarShape} shape - Shape of the avatar (circle or square)\n * @property {boolean} bordered - Whether to add a border around the avatar\n * @property {AvatarStatus} status - Optional status indicator to display\n *\n * @example\n * <schmancy-avatar\n * initials=\"JD\"\n * size=\"md\"\n * color=\"primary\"\n * ></schmancy-avatar>\n */\n@customElement('schmancy-avatar')\nexport class SchmancyAvatar extends SchmancyElement {\n\t@property({ type: String }) initials: string = ''\n\t@property({ type: String }) src: string = ''\n\t@property({ type: String }) icon: string = ''\n\t@property({ type: String }) size: AvatarSize = 'md'\n\t@property({ type: String }) color: AvatarColor = 'primary'\n\t@property({ type: String }) shape: AvatarShape = 'circle'\n\t@property({ type: Boolean }) bordered: boolean = false\n\t@property({ type: String }) status: AvatarStatus = 'none'\n\n\trender() {\n\t\t// Determine content to display (image, initials, or icon)\n\t\tlet content\n\t\tif (this.src) {\n\t\t\tcontent = html`<img class=\"w-full h-full object-cover\" src=\"${this.src}\" alt=\"Avatar\" />`\n\t\t} else if (this.initials) {\n\t\t\tcontent = html`<span class=\"text-center font-medium\">${this.initials.substring(0, 2).toUpperCase()}</span>`\n\t\t} else if (this.icon) {\n\t\t\tcontent = html`<schmancy-icon>${this.icon}</schmancy-icon>`\n\t\t} else {\n\t\t\tcontent = html`<schmancy-icon>person</schmancy-icon>`\n\t\t}\n\n\t\t// Size classes - M3 aligned: 20dp → 24dp → 32dp → 40dp → 48dp → 64dp\n\t\tconst sizeClasses = {\n\t\t\txxs: 'w-5 h-5 text-[8px]', // 20px - Ultra-compact\n\t\t\txs: 'w-6 h-6 text-xs', // 24px - M3 compact\n\t\t\tsm: 'w-8 h-8 text-sm', // 32px - M3 small\n\t\t\tmd: 'w-10 h-10 text-base', // 40px - M3 medium (default)\n\t\t\tlg: 'w-12 h-12 text-lg', // 48px - M3 large\n\t\t\txl: 'w-16 h-16 text-xl', // 64px - M3 extra large\n\t\t}\n\n\t\t// Shape classes\n\t\tconst shapeClasses = {\n\t\t\tcircle: 'rounded-full',\n\t\t\tsquare: 'rounded-md',\n\t\t}\n\n\t\t// Combine classes\n\t\tconst avatarClasses = {\n\t\t\t'relative flex items-center justify-center overflow-hidden': true,\n\t\t\t[sizeClasses[this.size]]: true,\n\t\t\t[shapeClasses[this.shape]]: true,\n\t\t\t'border-2 border-surface-container': this.bordered,\n\t\t}\n\n\t\t// Get theme colors\n\t\tconst colorAttrs = this.getColorAttributes()\n\n\t\treturn html`\n\t\t\t<div class=\"${this.classMap(avatarClasses)}\" ${colorAttrs}>\n\t\t\t\t${content} ${this.status !== 'none' ? this.renderStatusIndicator() : ''}\n\t\t\t</div>\n\t\t`\n\t}\n\n\tprivate getColorAttributes() {\n\t\tconst colorMap = {\n\t\t\tprimary: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.primary.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.primary.onContainer,\n\t\t\t},\n\t\t\tsecondary: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.secondary.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.secondary.onContainer,\n\t\t\t},\n\t\t\ttertiary: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.tertiary.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.tertiary.onContainer,\n\t\t\t},\n\t\t\tsuccess: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.success.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.success.onContainer,\n\t\t\t},\n\t\t\terror: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.error.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.error.onContainer,\n\t\t\t},\n\t\t\tneutral: {\n\t\t\t\tbgColor: SchmancyTheme.sys.color.surface.container,\n\t\t\t\tcolor: SchmancyTheme.sys.color.surface.on,\n\t\t\t},\n\t\t}\n\n\t\treturn color(colorMap[this.color])\n\t}\n\n\tprivate renderStatusIndicator() {\n\t\tconst statusColors = {\n\t\t\tonline: SchmancyTheme.sys.color.success.default,\n\t\t\toffline: SchmancyTheme.sys.color.surface.onVariant,\n\t\t\tbusy: SchmancyTheme.sys.color.error.default,\n\t\t\taway: SchmancyTheme.sys.color.tertiary.default,\n\t\t}\n\n\t\tconst sizeMap = {\n\t\t\txxs: 'w-1 h-1',\n\t\t\txs: 'w-1.5 h-1.5',\n\t\t\tsm: 'w-2 h-2',\n\t\t\tmd: 'w-2.5 h-2.5',\n\t\t\tlg: 'w-3 h-3',\n\t\t\txl: 'w-4 h-4',\n\t\t}\n\n\t\tconst statusClasses = {\n\t\t\t'absolute bottom-0 right-0 rounded-full border-2 border-surface-default': true,\n\t\t\t[sizeMap[this.size]]: true,\n\t\t}\n\n\t\treturn html`\n\t\t\t<div class=\"${this.classMap(statusClasses)}\" style=\"background-color: ${statusColors[this.status]};\"></div>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-avatar': SchmancyAvatar\n\t}\n}\n"],"mappings":"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"}
|
package/dist/badge.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./src-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./src-Blm9PNcf.cjs`);Object.defineProperty(exports,`ScBadgeV2`,{enumerable:!0,get:function(){return e.w}}),Object.defineProperty(exports,`SchmancyBadgeV2`,{enumerable:!0,get:function(){return e.T}});
|
package/dist/badge.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { T as e, w as t } from "./src-
|
|
1
|
+
import { T as e, w as t } from "./src-olrlFt4e.js";
|
|
2
2
|
export { t as ScBadgeV2, e as SchmancyBadgeV2 };
|