@mhmo91/schmancy 0.5.36 → 0.5.38
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/ai/boat.md +38 -106
- package/ai/theme.md +778 -144
- package/dist/ai/boat.md +38 -106
- package/dist/ai/theme.md +778 -144
- package/dist/{animated-text-BEAHZetl.js → animated-text-B6BM8UAR.js} +3 -3
- package/dist/{animated-text-BEAHZetl.js.map → animated-text-B6BM8UAR.js.map} +1 -1
- package/dist/{animated-text-ChV1GUee.cjs → animated-text-DMLVAWR9.cjs} +2 -2
- package/dist/{animated-text-ChV1GUee.cjs.map → animated-text-DMLVAWR9.cjs.map} +1 -1
- package/dist/animated-text.cjs +1 -1
- package/dist/animated-text.js +1 -1
- package/dist/area.cjs +1 -1
- package/dist/{area.component-R4KQInpP.js → area.component-C0i1I-XN.js} +3 -3
- package/dist/{area.component-R4KQInpP.js.map → area.component-C0i1I-XN.js.map} +1 -1
- package/dist/{area.component-cxxQIhCN.cjs → area.component-D630N8ae.cjs} +2 -2
- package/dist/{area.component-cxxQIhCN.cjs.map → area.component-D630N8ae.cjs.map} +1 -1
- package/dist/area.js +1 -1
- package/dist/{autocomplete-DKYBmt2q.js → autocomplete-B8VgSG8j.js} +4 -4
- package/dist/{autocomplete-DKYBmt2q.js.map → autocomplete-B8VgSG8j.js.map} +1 -1
- package/dist/{autocomplete-Cq_NzrBX.cjs → autocomplete-Dz24IUoU.cjs} +2 -2
- package/dist/{autocomplete-Cq_NzrBX.cjs.map → autocomplete-Dz24IUoU.cjs.map} +1 -1
- package/dist/autocomplete.cjs +1 -1
- package/dist/autocomplete.js +1 -1
- package/dist/{avatar-DbUCDe1w.cjs → avatar-DqZd_LTf.cjs} +4 -4
- package/dist/{avatar-DbUCDe1w.cjs.map → avatar-DqZd_LTf.cjs.map} +1 -1
- package/dist/{avatar-DJ7qYc6-.js → avatar-b6tMCYC_.js} +55 -53
- package/dist/{avatar-DJ7qYc6-.js.map → avatar-b6tMCYC_.js.map} +1 -1
- package/dist/badge.cjs +1 -1
- package/dist/badge.js +1 -1
- package/dist/{boat-BBFE1yJY.js → boat-CQlfnrN3.js} +81 -93
- package/dist/boat-CQlfnrN3.js.map +1 -0
- package/dist/boat-CvWXHBGZ.cjs +83 -0
- package/dist/boat-CvWXHBGZ.cjs.map +1 -0
- package/dist/boat.cjs +1 -1
- package/dist/boat.js +1 -1
- package/dist/busy.cjs +1 -1
- package/dist/busy.js +1 -1
- package/dist/button.cjs +1 -1
- package/dist/button.js +1 -1
- package/dist/card.cjs +1 -1
- package/dist/card.js +1 -1
- package/dist/{checkbox-BBJqucMb.cjs → checkbox-BxVFUa5d.cjs} +2 -2
- package/dist/{checkbox-BBJqucMb.cjs.map → checkbox-BxVFUa5d.cjs.map} +1 -1
- package/dist/{checkbox-geD1IIHh.js → checkbox-IXHvFU8T.js} +2 -2
- package/dist/{checkbox-geD1IIHh.js.map → checkbox-IXHvFU8T.js.map} +1 -1
- package/dist/checkbox.cjs +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/chips.cjs +1 -1
- package/dist/chips.js +2 -2
- package/dist/code-highlight.cjs +1 -1
- package/dist/code-highlight.js +1 -1
- package/dist/{code-preview-D2ZpTZ7C.js → code-preview-BckcSzge.js} +2 -2
- package/dist/{code-preview-D2ZpTZ7C.js.map → code-preview-BckcSzge.js.map} +1 -1
- package/dist/{code-preview-CR3U6wXD.cjs → code-preview-BtlXrJte.cjs} +2 -2
- package/dist/{code-preview-CR3U6wXD.cjs.map → code-preview-BtlXrJte.cjs.map} +1 -1
- package/dist/components.cjs +1 -1
- package/dist/components.js +1 -1
- package/dist/content-drawer.cjs +1 -1
- package/dist/content-drawer.js +1 -1
- package/dist/{date-range-DkSLcajW.cjs → date-range-CEBvpz9I.cjs} +2 -2
- package/dist/{date-range-DkSLcajW.cjs.map → date-range-CEBvpz9I.cjs.map} +1 -1
- package/dist/{date-range-NB6Q02hz.js → date-range-DJlpBhfg.js} +3 -3
- package/dist/{date-range-NB6Q02hz.js.map → date-range-DJlpBhfg.js.map} +1 -1
- package/dist/{date-range-inline-DXBR0Ocx.js → date-range-inline-DUkLYZw-.js} +3 -3
- package/dist/{date-range-inline-DXBR0Ocx.js.map → date-range-inline-DUkLYZw-.js.map} +1 -1
- package/dist/{date-range-inline-C8InUZoD.cjs → date-range-inline-svKzfEjk.cjs} +2 -2
- package/dist/{date-range-inline-C8InUZoD.cjs.map → date-range-inline-svKzfEjk.cjs.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-B4IPKZEn.cjs → delay-dCJupQL7.cjs} +2 -2
- package/dist/{delay-B4IPKZEn.cjs.map → delay-dCJupQL7.cjs.map} +1 -1
- package/dist/{delay-DsOC-uuq.js → delay-zFsG2bgS.js} +2 -2
- package/dist/{delay-DsOC-uuq.js.map → delay-zFsG2bgS.js.map} +1 -1
- package/dist/delay.cjs +1 -1
- package/dist/delay.js +1 -1
- package/dist/{details-7pcQWJF9.cjs → details-63cgbcG4.cjs} +2 -2
- package/dist/{details-7pcQWJF9.cjs.map → details-63cgbcG4.cjs.map} +1 -1
- package/dist/{details-D6Vq36lN.js → details-zr1wF8T5.js} +2 -2
- package/dist/{details-D6Vq36lN.js.map → details-zr1wF8T5.js.map} +1 -1
- package/dist/details.cjs +1 -1
- package/dist/details.js +1 -1
- package/dist/{dialog-content-BC--KBf7.cjs → dialog-content-CCwZGDWl.cjs} +2 -2
- package/dist/{dialog-content-BC--KBf7.cjs.map → dialog-content-CCwZGDWl.cjs.map} +1 -1
- package/dist/{dialog-content-XoKxxGTv.js → dialog-content-D4hLDFG7.js} +3 -3
- package/dist/{dialog-content-XoKxxGTv.js.map → dialog-content-D4hLDFG7.js.map} +1 -1
- package/dist/dialog.cjs +1 -1
- package/dist/dialog.js +1 -1
- package/dist/{divider-55yUklFI.cjs → divider-BDpbyVks.cjs} +2 -2
- package/dist/{divider-55yUklFI.cjs.map → divider-BDpbyVks.cjs.map} +1 -1
- package/dist/{divider-JaB5FtmR.js → divider-DXh9y_Nv.js} +3 -3
- package/dist/{divider-JaB5FtmR.js.map → divider-DXh9y_Nv.js.map} +1 -1
- package/dist/divider.cjs +1 -1
- package/dist/divider.js +1 -1
- package/dist/{dropdown-content-C2nxdAFA.cjs → dropdown-content-DGxquZCA.cjs} +2 -2
- package/dist/{dropdown-content-C2nxdAFA.cjs.map → dropdown-content-DGxquZCA.cjs.map} +1 -1
- package/dist/{dropdown-content-Qzt-B1FB.js → dropdown-content-zM3fWF1d.js} +3 -3
- package/dist/{dropdown-content-Qzt-B1FB.js.map → dropdown-content-zM3fWF1d.js.map} +1 -1
- package/dist/dropdown.cjs +1 -1
- package/dist/dropdown.js +1 -1
- package/dist/{email-recipients-C3TfQU2c.js → email-recipients-DqOHKxsV.js} +5 -5
- package/dist/{email-recipients-C3TfQU2c.js.map → email-recipients-DqOHKxsV.js.map} +1 -1
- package/dist/{email-recipients-7reIxhmF.cjs → email-recipients-MvSCLUmk.cjs} +2 -2
- package/dist/{email-recipients-7reIxhmF.cjs.map → email-recipients-MvSCLUmk.cjs.map} +1 -1
- package/dist/extra.cjs +1 -1
- package/dist/extra.js +1 -1
- package/dist/{flex-DauT7n0E.js → flex-BjpIb0Xr.js} +2 -2
- package/dist/{flex-DauT7n0E.js.map → flex-BjpIb0Xr.js.map} +1 -1
- package/dist/{flex-1y7FNRpS.cjs → flex-D1NZuZez.cjs} +2 -2
- package/dist/{flex-1y7FNRpS.cjs.map → flex-D1NZuZez.cjs.map} +1 -1
- package/dist/{form-Xg8jZsBF.cjs → form-CRPFTmNd.cjs} +2 -2
- package/dist/{form-Xg8jZsBF.cjs.map → form-CRPFTmNd.cjs.map} +1 -1
- package/dist/{form-DqA7DfNR.js → form-UlL9mkQq.js} +2 -2
- package/dist/{form-DqA7DfNR.js.map → form-UlL9mkQq.js.map} +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.js +1 -1
- package/dist/{formField.mixin-YvrrvL_A.js → formField.mixin-6_cx2CQR.js} +2 -2
- package/dist/{formField.mixin-YvrrvL_A.js.map → formField.mixin-6_cx2CQR.js.map} +1 -1
- package/dist/{formField.mixin-BnSYnYXQ.cjs → formField.mixin-CXYETznz.cjs} +2 -2
- package/dist/{formField.mixin-BnSYnYXQ.cjs.map → formField.mixin-CXYETznz.cjs.map} +1 -1
- package/dist/{icon-BFYUD00J.cjs → icon-BjvTgGum.cjs} +2 -2
- package/dist/{icon-BFYUD00J.cjs.map → icon-BjvTgGum.cjs.map} +1 -1
- package/dist/{icon-BtdeB2JT.js → icon-Ce_dFWKs.js} +2 -2
- package/dist/{icon-BtdeB2JT.js.map → icon-Ce_dFWKs.js.map} +1 -1
- package/dist/{icon-button-DwL4WnDE.js → icon-button-BLp0zzBs.js} +3 -3
- package/dist/{icon-button-DwL4WnDE.js.map → icon-button-BLp0zzBs.js.map} +1 -1
- package/dist/{icon-button-B-uxvO86.cjs → icon-button-yr8UowN8.cjs} +2 -2
- package/dist/{icon-button-B-uxvO86.cjs.map → icon-button-yr8UowN8.cjs.map} +1 -1
- package/dist/icons.cjs +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +49 -49
- package/dist/{input-PoerIsqx.cjs → input-BbBgA67h.cjs} +2 -2
- package/dist/{input-PoerIsqx.cjs.map → input-BbBgA67h.cjs.map} +1 -1
- package/dist/{input-CuOmXLVJ.js → input-FbaIdP-U.js} +3 -3
- package/dist/{input-CuOmXLVJ.js.map → input-FbaIdP-U.js.map} +1 -1
- package/dist/{input-chip-BlmZB-cO.cjs → input-chip-B49269QA.cjs} +2 -2
- package/dist/{input-chip-BlmZB-cO.cjs.map → input-chip-B49269QA.cjs.map} +1 -1
- package/dist/{input-chip-CcNElytP.js → input-chip-r5DIdtls.js} +2 -2
- package/dist/{input-chip-CcNElytP.js.map → input-chip-r5DIdtls.js.map} +1 -1
- package/dist/input.cjs +1 -1
- package/dist/input.js +1 -1
- package/dist/layout.cjs +1 -1
- package/dist/layout.js +1 -1
- package/dist/{list-BJjW-iAW.cjs → list-BLG8XA7G.cjs} +2 -2
- package/dist/{list-BJjW-iAW.cjs.map → list-BLG8XA7G.cjs.map} +1 -1
- package/dist/{list-Bou3BRYQ.js → list-QEY7H4eL.js} +2 -2
- package/dist/{list-Bou3BRYQ.js.map → list-QEY7H4eL.js.map} +1 -1
- package/dist/list.cjs +1 -1
- package/dist/list.js +1 -1
- package/dist/{litElement.mixin-Bkdw4DeE.js → litElement.mixin-D5MC2dPM.js} +2 -2
- package/dist/{litElement.mixin-Bkdw4DeE.js.map → litElement.mixin-D5MC2dPM.js.map} +1 -1
- package/dist/{litElement.mixin-Di-HgRnn.cjs → litElement.mixin-Dmtg7y_h.cjs} +2 -2
- package/dist/{litElement.mixin-Di-HgRnn.cjs.map → litElement.mixin-Dmtg7y_h.cjs.map} +1 -1
- package/dist/mailbox.cjs +1 -1
- package/dist/mailbox.js +1 -1
- package/dist/{map-CXNKwo__.cjs → map-BygoKmAX.cjs} +2 -2
- package/dist/{map-CXNKwo__.cjs.map → map-BygoKmAX.cjs.map} +1 -1
- package/dist/{map-bUVyL7jN.js → map-DY3fXMM4.js} +2 -2
- package/dist/{map-bUVyL7jN.js.map → map-DY3fXMM4.js.map} +1 -1
- package/dist/map.cjs +1 -1
- package/dist/map.js +1 -1
- package/dist/{media-8D6oDv1e.cjs → media-BFkmF0pK.cjs} +2 -2
- package/dist/{media-8D6oDv1e.cjs.map → media-BFkmF0pK.cjs.map} +1 -1
- package/dist/{media-CF1lpFAm.js → media-ChpYwvB3.js} +2 -2
- package/dist/{media-CF1lpFAm.js.map → media-ChpYwvB3.js.map} +1 -1
- package/dist/{menu-B8Ad1OVm.cjs → menu-BXHjDZge.cjs} +2 -2
- package/dist/{menu-B8Ad1OVm.cjs.map → menu-BXHjDZge.cjs.map} +1 -1
- package/dist/{menu-C9mJa_ck.js → menu-gLYzAVLB.js} +3 -3
- package/dist/{menu-C9mJa_ck.js.map → menu-gLYzAVLB.js.map} +1 -1
- package/dist/menu.cjs +1 -1
- package/dist/menu.js +1 -1
- package/dist/mixins/baseElement.ts +1 -1
- package/dist/mixins/discovery.service.ts +60 -0
- 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-Dh3B6B0L.js → navigation-rail-SPrrtWOS.js} +22 -20
- package/dist/{navigation-rail-Dh3B6B0L.js.map → navigation-rail-SPrrtWOS.js.map} +1 -1
- package/dist/{navigation-rail-CAgKSJh4.cjs → navigation-rail-luQXsJ36.cjs} +7 -7
- package/dist/{navigation-rail-CAgKSJh4.cjs.map → navigation-rail-luQXsJ36.cjs.map} +1 -1
- package/dist/navigation-rail.cjs +1 -1
- package/dist/navigation-rail.js +1 -1
- package/dist/{notification-service-IBQJTcmw.js → notification-service-Bzxf4TIc.js} +4 -4
- package/dist/{notification-service-IBQJTcmw.js.map → notification-service-Bzxf4TIc.js.map} +1 -1
- package/dist/{notification-service-L82ozhd0.cjs → notification-service-uoprkE19.cjs} +2 -2
- package/dist/{notification-service-L82ozhd0.cjs.map → notification-service-uoprkE19.cjs.map} +1 -1
- package/dist/notification.cjs +1 -1
- package/dist/notification.js +2 -2
- package/dist/{notify-CtxRmxjL.js → notify-BK0mniGw.js} +2 -2
- package/dist/{notify-CtxRmxjL.js.map → notify-BK0mniGw.js.map} +1 -1
- package/dist/{notify-AIKWEjDG.cjs → notify-BhSCT3Xk.cjs} +2 -2
- package/dist/{notify-AIKWEjDG.cjs.map → notify-BhSCT3Xk.cjs.map} +1 -1
- package/dist/{option-DHGTgRBn.js → option-BZue6YG8.js} +2 -2
- package/dist/{option-DHGTgRBn.js.map → option-BZue6YG8.js.map} +1 -1
- package/dist/{option-D5OW1kDk.cjs → option-Kk_GQY6j.cjs} +2 -2
- package/dist/{option-D5OW1kDk.cjs.map → option-Kk_GQY6j.cjs.map} +1 -1
- package/dist/option.cjs +1 -1
- package/dist/option.js +1 -1
- package/dist/{payment-card-form-CHS_s_Fk.cjs → payment-card-form-BcKkjxkm.cjs} +2 -2
- package/dist/{payment-card-form-CHS_s_Fk.cjs.map → payment-card-form-BcKkjxkm.cjs.map} +1 -1
- package/dist/{payment-card-form-wj2JWoyn.js → payment-card-form-C3JgpEIE.js} +3 -3
- package/dist/{payment-card-form-wj2JWoyn.js.map → payment-card-form-C3JgpEIE.js.map} +1 -1
- package/dist/{progress-CP4R_l3i.cjs → progress-BXnQuNBd.cjs} +2 -2
- package/dist/{progress-CP4R_l3i.cjs.map → progress-BXnQuNBd.cjs.map} +1 -1
- package/dist/{progress-ZrDv_k3Z.js → progress-CPGV-HHh.js} +2 -2
- package/dist/{progress-ZrDv_k3Z.js.map → progress-CPGV-HHh.js.map} +1 -1
- package/dist/progress.cjs +1 -1
- package/dist/progress.js +1 -1
- package/dist/{radio-button-BXP_yPjS.cjs → radio-button-DDgwyanN.cjs} +2 -2
- package/dist/{radio-button-BXP_yPjS.cjs.map → radio-button-DDgwyanN.cjs.map} +1 -1
- package/dist/{radio-button-D0pVoIe-.js → radio-button-Dsv9rYTJ.js} +3 -3
- package/dist/{radio-button-D0pVoIe-.js.map → radio-button-Dsv9rYTJ.js.map} +1 -1
- package/dist/radio-group.cjs +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/{schmancy-steps-container-BSv1aURP.cjs → schmancy-steps-container-C7evWzAc.cjs} +2 -2
- package/dist/{schmancy-steps-container-BSv1aURP.cjs.map → schmancy-steps-container-C7evWzAc.cjs.map} +1 -1
- package/dist/{schmancy-steps-container-vjioa19k.js → schmancy-steps-container-Cbzqrhes.js} +2 -2
- package/dist/{schmancy-steps-container-vjioa19k.js.map → schmancy-steps-container-Cbzqrhes.js.map} +1 -1
- package/dist/{select-DZ-Cy-lg.cjs → select-BuZt9KsB.cjs} +2 -2
- package/dist/{select-DZ-Cy-lg.cjs.map → select-BuZt9KsB.cjs.map} +1 -1
- package/dist/{select-SgSe22qC.js → select-Ru5E-2M3.js} +3 -3
- package/dist/{select-SgSe22qC.js.map → select-Ru5E-2M3.js.map} +1 -1
- package/dist/select.cjs +1 -1
- package/dist/select.js +1 -1
- package/dist/{sheet-CevNG0tZ.js → sheet-Cta5o1Yq.js} +3 -3
- package/dist/{sheet-CevNG0tZ.js.map → sheet-Cta5o1Yq.js.map} +1 -1
- package/dist/{sheet-CNMKrulQ.cjs → sheet-Dg6bkAGj.cjs} +2 -2
- package/dist/{sheet-CNMKrulQ.cjs.map → sheet-Dg6bkAGj.cjs.map} +1 -1
- package/dist/sheet.cjs +1 -1
- package/dist/sheet.js +1 -1
- package/dist/{slider-DIRocNv8.js → slider-C7pfCYir.js} +3 -3
- package/dist/{slider-DIRocNv8.js.map → slider-C7pfCYir.js.map} +1 -1
- package/dist/{slider-BSxJatG-.cjs → slider-CDhICxOr.cjs} +2 -2
- package/dist/{slider-BSxJatG-.cjs.map → slider-CDhICxOr.cjs.map} +1 -1
- package/dist/slider.cjs +1 -1
- package/dist/slider.js +1 -1
- package/dist/{spinner-DZcG-AtO.js → spinner-6-lTUGhs.js} +2 -2
- package/dist/{spinner-DZcG-AtO.js.map → spinner-6-lTUGhs.js.map} +1 -1
- package/dist/{spinner-Cx54uto8.cjs → spinner-nAYWwwNr.cjs} +2 -2
- package/dist/{spinner-Cx54uto8.cjs.map → spinner-nAYWwwNr.cjs.map} +1 -1
- package/dist/steps.cjs +1 -1
- package/dist/steps.js +1 -1
- package/dist/{suggestion-chip-DADIje6B.js → suggestion-chip-5_s9HR2Y.js} +3 -3
- package/dist/{suggestion-chip-DADIje6B.js.map → suggestion-chip-5_s9HR2Y.js.map} +1 -1
- package/dist/{suggestion-chip-ssmmc0q6.cjs → suggestion-chip-CsGRZal0.cjs} +2 -2
- package/dist/{suggestion-chip-ssmmc0q6.cjs.map → suggestion-chip-CsGRZal0.cjs.map} +1 -1
- package/dist/{surface-_cS9Ehk0.js → surface-D5c_ddsq.js} +2 -2
- package/dist/{surface-_cS9Ehk0.js.map → surface-D5c_ddsq.js.map} +1 -1
- package/dist/{surface-ix9qOb7a.cjs → surface-EDSS-N2K.cjs} +2 -2
- package/dist/{surface-ix9qOb7a.cjs.map → surface-EDSS-N2K.cjs.map} +1 -1
- package/dist/surface.cjs +1 -1
- package/dist/surface.js +1 -1
- package/dist/{table-Bi2ftsJe.js → table-5TjWY5RR.js} +2 -2
- package/dist/{table-Bi2ftsJe.js.map → table-5TjWY5RR.js.map} +1 -1
- package/dist/{table-DSEK3bMb.cjs → table-B_GbZCU6.cjs} +2 -2
- package/dist/{table-DSEK3bMb.cjs.map → table-B_GbZCU6.cjs.map} +1 -1
- package/dist/table.cjs +1 -1
- package/dist/table.js +1 -1
- package/dist/{tabs-compatibility-BE2Q3rig.cjs → tabs-compatibility-byG-7uxY.cjs} +2 -2
- package/dist/{tabs-compatibility-BE2Q3rig.cjs.map → tabs-compatibility-byG-7uxY.cjs.map} +1 -1
- package/dist/{tabs-compatibility-DA3RIq35.js → tabs-compatibility-eM8y7Hkw.js} +2 -2
- package/dist/{tabs-compatibility-DA3RIq35.js.map → tabs-compatibility-eM8y7Hkw.js.map} +1 -1
- package/dist/tabs.cjs +1 -1
- package/dist/tabs.js +1 -1
- package/dist/tailwind.mixin-BOTmjQKh.js +64 -0
- package/dist/tailwind.mixin-BOTmjQKh.js.map +1 -0
- package/dist/tailwind.mixin-SjjyWekZ.cjs +2 -0
- package/dist/tailwind.mixin-SjjyWekZ.cjs.map +1 -0
- package/dist/teleport.cjs +1 -1
- package/dist/teleport.js +1 -1
- package/dist/{textarea-CBb2CzKu.js → textarea-Ba0EbwKj.js} +2 -2
- package/dist/{textarea-CBb2CzKu.js.map → textarea-Ba0EbwKj.js.map} +1 -1
- package/dist/{textarea-ClgK_mP6.cjs → textarea-C5G_bBP8.cjs} +2 -2
- package/dist/{textarea-ClgK_mP6.cjs.map → textarea-C5G_bBP8.cjs.map} +1 -1
- package/dist/textarea.cjs +1 -1
- package/dist/textarea.js +1 -1
- package/dist/{theme-button-Z_xWXMaf.js → theme-button--FRHwiCC.js} +2 -2
- package/dist/{theme-button-Z_xWXMaf.js.map → theme-button--FRHwiCC.js.map} +1 -1
- package/dist/{theme-button-Dhp3ozyB.cjs → theme-button-BiQ-jfG4.cjs} +2 -2
- package/dist/{theme-button-Dhp3ozyB.cjs.map → theme-button-BiQ-jfG4.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.controls-C_zAMJgA.cjs → theme.controls-BPnEjft1.cjs} +2 -2
- package/dist/{theme.controls-C_zAMJgA.cjs.map → theme.controls-BPnEjft1.cjs.map} +1 -1
- package/dist/{theme.controls-BtaZcM7z.js → theme.controls-Bua4rENX.js} +3 -3
- package/dist/{theme.controls-BtaZcM7z.js.map → theme.controls-Bua4rENX.js.map} +1 -1
- package/dist/theme.js +1 -1
- package/dist/{timezone-DucGbWcE.cjs → timezone-CCvqNgyF.cjs} +2 -2
- package/dist/{timezone-DucGbWcE.cjs.map → timezone-CCvqNgyF.cjs.map} +1 -1
- package/dist/{timezone-CZ0gCI2P.js → timezone-D54Cff6x.js} +3 -3
- package/dist/{timezone-CZ0gCI2P.js.map → timezone-D54Cff6x.js.map} +1 -1
- package/dist/{tooltip-BSppSqZM.js → tooltip-C8m-rfYS.js} +2 -2
- package/dist/{tooltip-BSppSqZM.js.map → tooltip-C8m-rfYS.js.map} +1 -1
- package/dist/{tooltip-BSWp7Mmz.cjs → tooltip-CCl6ctrG.cjs} +2 -2
- package/dist/{tooltip-BSWp7Mmz.cjs.map → tooltip-CCl6ctrG.cjs.map} +1 -1
- package/dist/tooltip.cjs +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/{tree-DL71EUih.cjs → tree-COuLggJS.cjs} +2 -2
- package/dist/{tree-DL71EUih.cjs.map → tree-COuLggJS.cjs.map} +1 -1
- package/dist/{tree-dEse6eMH.js → tree-t1IWaICA.js} +2 -2
- package/dist/{tree-dEse6eMH.js.map → tree-t1IWaICA.js.map} +1 -1
- package/dist/tree.cjs +1 -1
- package/dist/tree.js +1 -1
- package/dist/{typewriter-DBvUYzpl.js → typewriter-B1SrKdhR.js} +4 -4
- package/dist/{typewriter-DBvUYzpl.js.map → typewriter-B1SrKdhR.js.map} +1 -1
- package/dist/{typewriter-B1Au4MRO.cjs → typewriter-iHUlWvZZ.cjs} +2 -2
- package/dist/{typewriter-B1Au4MRO.cjs.map → typewriter-iHUlWvZZ.cjs.map} +1 -1
- package/dist/typewriter.cjs +1 -1
- package/dist/typewriter.js +1 -1
- package/dist/{typography-3gXQvLXN.cjs → typography-J_EEO2HF.cjs} +2 -2
- package/dist/{typography-3gXQvLXN.cjs.map → typography-J_EEO2HF.cjs.map} +1 -1
- package/dist/{typography-iOtjgSkI.js → typography-X_jjdG7E.js} +2 -2
- package/dist/{typography-iOtjgSkI.js.map → typography-X_jjdG7E.js.map} +1 -1
- package/dist/typography.cjs +1 -1
- package/dist/typography.js +1 -1
- package/package.json +1 -1
- package/types/mixins/discovery.service.d.ts +17 -0
- package/types/src/boat/boat.d.ts +3 -3
- package/types/src/navigation-bar/navigation-bar.d.ts +2 -1
- package/types/src/navigation-rail/navigation-rail.d.ts +2 -3
- package/dist/boat-BBFE1yJY.js.map +0 -1
- package/dist/boat-BSYtwy1W.cjs +0 -78
- package/dist/boat-BSYtwy1W.cjs.map +0 -1
- package/dist/tailwind.mixin-CvQn8Ynb.cjs +0 -2
- package/dist/tailwind.mixin-CvQn8Ynb.cjs.map +0 -1
- package/dist/tailwind.mixin-DGLcZhRp.js +0 -57
- package/dist/tailwind.mixin-DGLcZhRp.js.map +0 -1
package/dist/ai/theme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Theme Service
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Comprehensive Material Design 3 theme management with reactive observables, automatic persistence, and a complete token system for colors, typography, motion, and more.
|
|
4
4
|
|
|
5
5
|
## Import
|
|
6
6
|
|
|
@@ -16,6 +16,7 @@ import { theme } from '@schmancy/theme'
|
|
|
16
16
|
- **Color**: Primary theme color in hex format
|
|
17
17
|
- **Fullscreen**: Navigation visibility state
|
|
18
18
|
- **Theme Component**: Visual theme provider that registers with service
|
|
19
|
+
- **Material Design 3 Tokens**: Complete design system with colors, surfaces, typography, motion, and more
|
|
19
20
|
|
|
20
21
|
## Properties (Synchronous)
|
|
21
22
|
|
|
@@ -24,7 +25,7 @@ theme.scheme // 'dark' | 'light' | 'auto'
|
|
|
24
25
|
theme.color // '#6200ee'
|
|
25
26
|
theme.fullscreen // boolean
|
|
26
27
|
theme.themeComponent // SchmancyThemeComponent | null
|
|
27
|
-
theme.theme // Partial<TSchmancyTheme>
|
|
28
|
+
theme.theme // Partial<TSchmancyTheme> - Full M3 token system
|
|
28
29
|
```
|
|
29
30
|
|
|
30
31
|
## Observables
|
|
@@ -35,9 +36,9 @@ theme.scheme$.subscribe(scheme => {
|
|
|
35
36
|
console.log(scheme) // 'dark' | 'light' | 'auto'
|
|
36
37
|
})
|
|
37
38
|
|
|
38
|
-
// Resolved scheme (auto → actual)
|
|
39
|
+
// Resolved scheme (auto → actual) - NEVER returns 'auto'
|
|
39
40
|
theme.resolvedScheme$.subscribe(scheme => {
|
|
40
|
-
console.log(scheme) // 'dark' | 'light' (
|
|
41
|
+
console.log(scheme) // 'dark' | 'light' (automatically resolved)
|
|
41
42
|
})
|
|
42
43
|
|
|
43
44
|
// Color changes
|
|
@@ -50,20 +51,20 @@ theme.fullscreen$.subscribe(isFullscreen => {
|
|
|
50
51
|
console.log(isFullscreen) // true/false
|
|
51
52
|
})
|
|
52
53
|
|
|
53
|
-
//
|
|
54
|
+
// Complete theme configuration
|
|
54
55
|
theme.theme$.subscribe(themeConfig => {
|
|
55
|
-
console.log(themeConfig) // Material Design 3 theme object
|
|
56
|
+
console.log(themeConfig) // Full Material Design 3 theme object
|
|
56
57
|
})
|
|
57
58
|
```
|
|
58
59
|
|
|
59
60
|
## Methods
|
|
60
61
|
|
|
61
62
|
### `setScheme(scheme)`
|
|
62
|
-
Set color scheme.
|
|
63
|
+
Set color scheme with automatic persistence.
|
|
63
64
|
```typescript
|
|
64
65
|
theme.setScheme('dark') // Force dark
|
|
65
66
|
theme.setScheme('light') // Force light
|
|
66
|
-
theme.setScheme('auto') // Follow system
|
|
67
|
+
theme.setScheme('auto') // Follow system preferences
|
|
67
68
|
```
|
|
68
69
|
|
|
69
70
|
### `toggleScheme()`
|
|
@@ -73,13 +74,13 @@ theme.toggleScheme() // light → dark → light
|
|
|
73
74
|
```
|
|
74
75
|
|
|
75
76
|
### `setColor(color)`
|
|
76
|
-
Set primary color.
|
|
77
|
+
Set primary color - automatically generates full M3 palette.
|
|
77
78
|
```typescript
|
|
78
|
-
theme.setColor('#6750A4')
|
|
79
|
+
theme.setColor('#6750A4') // Generates all tones and color roles
|
|
79
80
|
```
|
|
80
81
|
|
|
81
82
|
### `isDarkMode()`
|
|
82
|
-
|
|
83
|
+
Observable that emits current dark mode state.
|
|
83
84
|
```typescript
|
|
84
85
|
theme.isDarkMode().subscribe(isDark => {
|
|
85
86
|
console.log(isDark) // true/false
|
|
@@ -87,7 +88,7 @@ theme.isDarkMode().subscribe(isDark => {
|
|
|
87
88
|
```
|
|
88
89
|
|
|
89
90
|
### `setFullscreen(value)`
|
|
90
|
-
Control fullscreen mode.
|
|
91
|
+
Control fullscreen mode for immersive experiences.
|
|
91
92
|
```typescript
|
|
92
93
|
theme.setFullscreen(true) // Hide navigation
|
|
93
94
|
theme.setFullscreen(false) // Show navigation
|
|
@@ -100,7 +101,7 @@ theme.toggleFullscreen()
|
|
|
100
101
|
```
|
|
101
102
|
|
|
102
103
|
### `next(values)`
|
|
103
|
-
Update multiple properties
|
|
104
|
+
Update multiple properties atomically.
|
|
104
105
|
```typescript
|
|
105
106
|
theme.next({
|
|
106
107
|
fullscreen: true,
|
|
@@ -110,243 +111,876 @@ theme.next({
|
|
|
110
111
|
```
|
|
111
112
|
|
|
112
113
|
### `getCSSVariable(name)`
|
|
113
|
-
Get CSS variable value.
|
|
114
|
+
Get computed CSS variable value.
|
|
114
115
|
```typescript
|
|
115
116
|
const primary = theme.getCSSVariable('color-primary')
|
|
116
|
-
|
|
117
|
+
const elevation = theme.getCSSVariable('elevation-3')
|
|
118
|
+
// Returns computed value of --schmancy-{name}
|
|
117
119
|
```
|
|
118
120
|
|
|
119
121
|
### `watchCSSVariable(name)`
|
|
120
|
-
Watch CSS variable changes.
|
|
122
|
+
Watch CSS variable changes reactively.
|
|
121
123
|
```typescript
|
|
122
124
|
theme.watchCSSVariable('color-primary').subscribe(color => {
|
|
123
125
|
console.log('Primary changed:', color)
|
|
124
126
|
})
|
|
125
127
|
```
|
|
126
128
|
|
|
127
|
-
##
|
|
129
|
+
## Theme Controls Component
|
|
128
130
|
|
|
129
|
-
|
|
131
|
+
Ready-to-use UI component for complete theme control:
|
|
130
132
|
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// Custom component integration
|
|
136
|
-
fromEvent(window, 'fullscreen').pipe(
|
|
137
|
-
tap((e: CustomEvent) => {
|
|
138
|
-
this.hidden = e.detail
|
|
139
|
-
}),
|
|
140
|
-
takeUntil(this.disconnecting)
|
|
141
|
-
).subscribe()
|
|
133
|
+
```html
|
|
134
|
+
<schmancy-theme-controls
|
|
135
|
+
.customColors=${['#6750A4', '#0061A4', '#006E1C']}
|
|
136
|
+
></schmancy-theme-controls>
|
|
142
137
|
```
|
|
143
138
|
|
|
144
|
-
|
|
139
|
+
### Features
|
|
140
|
+
- **Color Picker**: Visual color selection with debounced input
|
|
141
|
+
- **Scheme Toggle**: Beautiful icons for light/dark/auto modes
|
|
142
|
+
- **Random Color**: Generate random theme colors
|
|
143
|
+
- **Custom Presets**: Define your own color palette
|
|
145
144
|
|
|
146
|
-
###
|
|
145
|
+
### Implementation Example
|
|
147
146
|
```typescript
|
|
148
|
-
@
|
|
149
|
-
export class ThemeControls extends $LitElement() {
|
|
150
|
-
@state() private currentScheme = theme.scheme
|
|
151
|
-
@state() private isFullscreen = theme.fullscreen
|
|
147
|
+
import '@schmancy/theme-controls'
|
|
152
148
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
theme.fullscreen$.pipe(
|
|
162
|
-
tap(fullscreen => this.isFullscreen = fullscreen),
|
|
163
|
-
takeUntil(this.disconnecting)
|
|
164
|
-
).subscribe()
|
|
165
|
-
}
|
|
149
|
+
@customElement('my-settings')
|
|
150
|
+
export class MySettings extends $LitElement() {
|
|
151
|
+
private brandColors = [
|
|
152
|
+
'#6750A4', // Brand primary
|
|
153
|
+
'#0061A4', // Brand secondary
|
|
154
|
+
'#006E1C', // Brand success
|
|
155
|
+
'#BA1B1B' // Brand error
|
|
156
|
+
]
|
|
166
157
|
|
|
167
158
|
render() {
|
|
168
159
|
return html`
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
160
|
+
<schmancy-surface type="container" class="p-4">
|
|
161
|
+
<schmancy-typography type="title" token="medium">
|
|
162
|
+
Theme Settings
|
|
163
|
+
</schmancy-typography>
|
|
164
|
+
|
|
165
|
+
<schmancy-theme-controls
|
|
166
|
+
.customColors=${this.brandColors}
|
|
167
|
+
></schmancy-theme-controls>
|
|
168
|
+
</schmancy-surface>
|
|
175
169
|
`
|
|
176
170
|
}
|
|
177
171
|
}
|
|
178
172
|
```
|
|
179
173
|
|
|
180
|
-
|
|
174
|
+
## Complete Material Design 3 Token System
|
|
175
|
+
|
|
176
|
+
The theme service generates a COMPLETE M3 design system with hundreds of tokens:
|
|
177
|
+
|
|
178
|
+
### Extended Color System
|
|
179
|
+
|
|
180
|
+
Beyond primary/secondary/tertiary/error, the theme includes:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Additional semantic colors
|
|
184
|
+
theme.theme.success // Success states (#006E1C base)
|
|
185
|
+
theme.theme.onSuccess // Text on success backgrounds
|
|
186
|
+
theme.theme.successContainer
|
|
187
|
+
theme.theme.onSuccessContainer
|
|
188
|
+
|
|
189
|
+
theme.theme.warning // Warning states (#FFB800 base)
|
|
190
|
+
theme.theme.onWarning
|
|
191
|
+
theme.theme.warningContainer
|
|
192
|
+
theme.theme.onWarningContainer
|
|
193
|
+
|
|
194
|
+
theme.theme.info // Info states (#0061A4 base)
|
|
195
|
+
theme.theme.onInfo
|
|
196
|
+
theme.theme.infoContainer
|
|
197
|
+
theme.theme.onInfoContainer
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Surface System
|
|
201
|
+
|
|
202
|
+
Complete surface hierarchy with proper elevation:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// Base surfaces
|
|
206
|
+
theme.theme.surface // Default surface
|
|
207
|
+
theme.theme.surfaceDim // Dimmed surface
|
|
208
|
+
theme.theme.surfaceBright // Bright surface
|
|
209
|
+
|
|
210
|
+
// Container hierarchy
|
|
211
|
+
theme.theme.surfaceContainerLowest // Lowest elevation
|
|
212
|
+
theme.theme.surfaceContainerLow // Low elevation
|
|
213
|
+
theme.theme.surfaceContainer // Default container
|
|
214
|
+
theme.theme.surfaceContainerHigh // High elevation
|
|
215
|
+
theme.theme.surfaceContainerHighest // Highest elevation
|
|
216
|
+
|
|
217
|
+
// Fixed color variants (don't change with theme)
|
|
218
|
+
theme.theme.primaryFixed // Fixed primary
|
|
219
|
+
theme.theme.primaryFixedDim // Dimmed fixed primary
|
|
220
|
+
theme.theme.onPrimaryFixed // Text on fixed primary
|
|
221
|
+
theme.theme.onPrimaryFixedVariant
|
|
222
|
+
// (Same for secondary, tertiary)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Typography System
|
|
226
|
+
|
|
227
|
+
Complete type scale with three axes:
|
|
228
|
+
|
|
181
229
|
```typescript
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
230
|
+
// Display - Largest, for hero text
|
|
231
|
+
theme.theme.typeface.scale.display.large // 57px
|
|
232
|
+
theme.theme.typeface.scale.display.medium // 45px
|
|
233
|
+
theme.theme.typeface.scale.display.small // 36px
|
|
234
|
+
|
|
235
|
+
// Headline - For section headers
|
|
236
|
+
theme.theme.typeface.scale.headline.large // 32px
|
|
237
|
+
theme.theme.typeface.scale.headline.medium // 28px
|
|
238
|
+
theme.theme.typeface.scale.headline.small // 24px
|
|
239
|
+
|
|
240
|
+
// Title - For cards and lists
|
|
241
|
+
theme.theme.typeface.scale.title.large // 22px
|
|
242
|
+
theme.theme.typeface.scale.title.medium // 16px
|
|
243
|
+
theme.theme.typeface.scale.title.small // 14px
|
|
244
|
+
|
|
245
|
+
// Body - For content
|
|
246
|
+
theme.theme.typeface.scale.body.large // 16px
|
|
247
|
+
theme.theme.typeface.scale.body.medium // 14px
|
|
248
|
+
theme.theme.typeface.scale.body.small // 12px
|
|
249
|
+
|
|
250
|
+
// Label - For UI elements
|
|
251
|
+
theme.theme.typeface.scale.label.large // 14px
|
|
252
|
+
theme.theme.typeface.scale.label.medium // 12px
|
|
253
|
+
theme.theme.typeface.scale.label.small // 11px
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Motion System
|
|
257
|
+
|
|
258
|
+
Sophisticated animation tokens:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// Easing curves
|
|
262
|
+
theme.theme.motion.easing.emphasized // Expressive motion
|
|
263
|
+
theme.theme.motion.easing.emphasizedDecelerate // Enter animations
|
|
264
|
+
theme.theme.motion.easing.emphasizedAccelerate // Exit animations
|
|
265
|
+
theme.theme.motion.easing.standard // Standard transitions
|
|
266
|
+
theme.theme.motion.easing.standardDecelerate
|
|
267
|
+
theme.theme.motion.easing.standardAccelerate
|
|
268
|
+
theme.theme.motion.easing.legacy // Backward compatibility
|
|
269
|
+
theme.theme.motion.easing.linear // Constant speed
|
|
270
|
+
|
|
271
|
+
// Duration scales (in ms)
|
|
272
|
+
theme.theme.motion.duration.short1 // 50ms - Micro interactions
|
|
273
|
+
theme.theme.motion.duration.short2 // 100ms
|
|
274
|
+
theme.theme.motion.duration.short3 // 150ms
|
|
275
|
+
theme.theme.motion.duration.short4 // 200ms
|
|
276
|
+
|
|
277
|
+
theme.theme.motion.duration.medium1 // 250ms - Standard transitions
|
|
278
|
+
theme.theme.motion.duration.medium2 // 300ms
|
|
279
|
+
theme.theme.motion.duration.medium3 // 350ms
|
|
280
|
+
theme.theme.motion.duration.medium4 // 400ms
|
|
281
|
+
|
|
282
|
+
theme.theme.motion.duration.long1 // 450ms - Complex animations
|
|
283
|
+
theme.theme.motion.duration.long2 // 500ms
|
|
284
|
+
theme.theme.motion.duration.long3 // 550ms
|
|
285
|
+
theme.theme.motion.duration.long4 // 600ms
|
|
286
|
+
|
|
287
|
+
theme.theme.motion.duration.extraLong1 // 700ms - Dramatic effects
|
|
288
|
+
theme.theme.motion.duration.extraLong2 // 800ms
|
|
289
|
+
theme.theme.motion.duration.extraLong3 // 900ms
|
|
290
|
+
theme.theme.motion.duration.extraLong4 // 1000ms
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Shape System
|
|
294
|
+
|
|
295
|
+
Corner radius tokens:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
theme.theme.shape.corner.none // 0px
|
|
299
|
+
theme.theme.shape.corner.extraSmall // 4px
|
|
300
|
+
theme.theme.shape.corner.small // 8px
|
|
301
|
+
theme.theme.shape.corner.medium // 12px
|
|
302
|
+
theme.theme.shape.corner.large // 16px
|
|
303
|
+
theme.theme.shape.corner.extraLarge // 28px
|
|
304
|
+
theme.theme.shape.corner.full // 9999px (pill shape)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Elevation System
|
|
308
|
+
|
|
309
|
+
Elevation with tinted shadows in dark mode:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
theme.theme.elevation.level0 // Flat
|
|
313
|
+
theme.theme.elevation.level1 // Cards
|
|
314
|
+
theme.theme.elevation.level2 // Raised cards
|
|
315
|
+
theme.theme.elevation.level3 // Floating action buttons
|
|
316
|
+
theme.theme.elevation.level4 // Dialogs
|
|
317
|
+
theme.theme.elevation.level5 // Highest elevation
|
|
318
|
+
|
|
319
|
+
// In dark mode, shadows are tinted with primary color
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### State Layer Opacities
|
|
323
|
+
|
|
324
|
+
Interaction state opacities:
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
theme.theme.states.hover.stateLayerOpacity // 0.08
|
|
328
|
+
theme.theme.states.focus.stateLayerOpacity // 0.1
|
|
329
|
+
theme.theme.states.pressed.stateLayerOpacity // 0.1
|
|
330
|
+
theme.theme.states.dragged.stateLayerOpacity // 0.15
|
|
331
|
+
theme.theme.states.disabled.containerOpacity // 0.12
|
|
332
|
+
theme.theme.states.disabled.contentOpacity // 0.38
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Spacing System
|
|
336
|
+
|
|
337
|
+
4dp grid spacing:
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
theme.theme.spacing.size.none // 0px
|
|
341
|
+
theme.theme.spacing.size.s1 // 4px
|
|
342
|
+
theme.theme.spacing.size.s2 // 8px
|
|
343
|
+
theme.theme.spacing.size.s3 // 12px
|
|
344
|
+
theme.theme.spacing.size.s4 // 16px
|
|
345
|
+
theme.theme.spacing.size.s5 // 20px
|
|
346
|
+
theme.theme.spacing.size.s6 // 24px
|
|
347
|
+
theme.theme.spacing.size.s7 // 28px
|
|
348
|
+
theme.theme.spacing.size.s8 // 32px
|
|
349
|
+
theme.theme.spacing.size.s9 // 36px
|
|
350
|
+
theme.theme.spacing.size.s10 // 40px
|
|
351
|
+
theme.theme.spacing.size.s11 // 44px
|
|
352
|
+
theme.theme.spacing.size.s12 // 48px
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## State Management & Persistence
|
|
356
|
+
|
|
357
|
+
The theme service uses a **persistent context** that automatically saves to localStorage:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
// No manual localStorage code needed!
|
|
361
|
+
// Settings persist automatically via context
|
|
362
|
+
|
|
363
|
+
// The context key 'schmancy-theme-settings' stores:
|
|
364
|
+
// - scheme: 'dark' | 'light' | 'auto'
|
|
365
|
+
// - color: hex color string
|
|
366
|
+
|
|
367
|
+
// Automatic restoration on page load
|
|
368
|
+
// Just use the service - persistence is handled
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Theme Discovery Pattern
|
|
372
|
+
|
|
373
|
+
The service uses a sophisticated bidirectional event system:
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
// Service dispatches discovery event
|
|
377
|
+
dispatchEvent(new CustomEvent('ThemeWhereAreYou'))
|
|
378
|
+
|
|
379
|
+
// Theme component responds
|
|
380
|
+
dispatchEvent(new CustomEvent('ThemeHereIAm', {
|
|
381
|
+
detail: themeComponent
|
|
382
|
+
}))
|
|
383
|
+
|
|
384
|
+
// Automatic registration with timeout
|
|
385
|
+
theme.discoverTheme().pipe(
|
|
386
|
+
timeout(1000), // 1 second timeout
|
|
387
|
+
catchError(() => of(null))
|
|
388
|
+
).subscribe(component => {
|
|
389
|
+
if (component) {
|
|
390
|
+
console.log('Theme component found and registered')
|
|
391
|
+
}
|
|
392
|
+
})
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Advanced Patterns
|
|
396
|
+
|
|
397
|
+
### Activity Logging for Debugging
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
@customElement('theme-debugger')
|
|
401
|
+
export class ThemeDebugger extends $LitElement() {
|
|
402
|
+
@state() private activities: string[] = []
|
|
185
403
|
|
|
186
404
|
connectedCallback() {
|
|
187
405
|
super.connectedCallback()
|
|
188
406
|
|
|
189
|
-
theme
|
|
190
|
-
|
|
407
|
+
// Log all theme changes
|
|
408
|
+
combineLatest([
|
|
409
|
+
theme.scheme$,
|
|
410
|
+
theme.color$,
|
|
411
|
+
theme.fullscreen$
|
|
412
|
+
]).pipe(
|
|
413
|
+
tap(([scheme, color, fullscreen]) => {
|
|
414
|
+
const activity = `[${new Date().toLocaleTimeString()}] ` +
|
|
415
|
+
`Scheme: ${scheme}, Color: ${color}, Fullscreen: ${fullscreen}`
|
|
416
|
+
this.activities = [...this.activities, activity].slice(-10)
|
|
417
|
+
}),
|
|
191
418
|
takeUntil(this.disconnecting)
|
|
192
419
|
).subscribe()
|
|
193
420
|
}
|
|
194
421
|
|
|
195
422
|
render() {
|
|
196
423
|
return html`
|
|
197
|
-
<div class
|
|
198
|
-
|
|
424
|
+
<div class="font-mono text-xs">
|
|
425
|
+
${this.activities.map(a => html`<div>${a}</div>`)}
|
|
199
426
|
</div>
|
|
200
427
|
`
|
|
201
428
|
}
|
|
202
429
|
}
|
|
203
430
|
```
|
|
204
431
|
|
|
205
|
-
### Color
|
|
432
|
+
### Custom Color Presets with Categories
|
|
433
|
+
|
|
206
434
|
```typescript
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
435
|
+
interface ColorPreset {
|
|
436
|
+
category: string
|
|
437
|
+
colors: Array<{ name: string; value: string }>
|
|
438
|
+
}
|
|
210
439
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
440
|
+
const presets: ColorPreset[] = [
|
|
441
|
+
{
|
|
442
|
+
category: 'Brand',
|
|
443
|
+
colors: [
|
|
444
|
+
{ name: 'Primary', value: '#6750A4' },
|
|
445
|
+
{ name: 'Secondary', value: '#625B71' }
|
|
446
|
+
]
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
category: 'Semantic',
|
|
450
|
+
colors: [
|
|
451
|
+
{ name: 'Success', value: '#006E1C' },
|
|
452
|
+
{ name: 'Warning', value: '#FFB800' },
|
|
453
|
+
{ name: 'Error', value: '#BA1B1B' },
|
|
454
|
+
{ name: 'Info', value: '#0061A4' }
|
|
455
|
+
]
|
|
456
|
+
}
|
|
457
|
+
]
|
|
458
|
+
|
|
459
|
+
// Use in component
|
|
460
|
+
html`
|
|
461
|
+
${presets.map(preset => html`
|
|
462
|
+
<div>
|
|
463
|
+
<h3>${preset.category}</h3>
|
|
464
|
+
${preset.colors.map(color => html`
|
|
214
465
|
<button
|
|
215
|
-
style="background: ${color}"
|
|
216
|
-
@click=${() => theme.setColor(color)}
|
|
466
|
+
style="background: ${color.value}"
|
|
467
|
+
@click=${() => theme.setColor(color.value)}
|
|
468
|
+
title=${color.name}
|
|
217
469
|
></button>
|
|
218
470
|
`)}
|
|
219
|
-
|
|
471
|
+
</div>
|
|
472
|
+
`)}
|
|
473
|
+
`
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Animated Theme Transitions
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
@customElement('smooth-theme')
|
|
480
|
+
export class SmoothTheme extends $LitElement(css`
|
|
481
|
+
:host {
|
|
482
|
+
transition: background-color
|
|
483
|
+
var(--schmancy-motion-duration-medium2)
|
|
484
|
+
var(--schmancy-motion-easing-standard);
|
|
485
|
+
}
|
|
486
|
+
`) {
|
|
487
|
+
connectedCallback() {
|
|
488
|
+
super.connectedCallback()
|
|
489
|
+
|
|
490
|
+
// Apply smooth transitions using motion tokens
|
|
491
|
+
theme.resolvedScheme$.pipe(
|
|
492
|
+
tap(() => {
|
|
493
|
+
// Background transitions automatically via CSS variables
|
|
494
|
+
this.style.setProperty('background-color',
|
|
495
|
+
'var(--schmancy-color-surface)')
|
|
496
|
+
}),
|
|
497
|
+
takeUntil(this.disconnecting)
|
|
498
|
+
).subscribe()
|
|
220
499
|
}
|
|
221
500
|
}
|
|
222
501
|
```
|
|
223
502
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
Auto mode follows system preferences:
|
|
503
|
+
### Responsive Theme Based on Time
|
|
227
504
|
|
|
228
505
|
```typescript
|
|
229
|
-
|
|
230
|
-
|
|
506
|
+
@customElement('time-aware-theme')
|
|
507
|
+
export class TimeAwareTheme extends $LitElement() {
|
|
508
|
+
connectedCallback() {
|
|
509
|
+
super.connectedCallback()
|
|
231
510
|
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
511
|
+
// Auto-switch theme based on time
|
|
512
|
+
interval(60000).pipe( // Check every minute
|
|
513
|
+
startWith(0),
|
|
514
|
+
map(() => new Date().getHours()),
|
|
515
|
+
map(hour => hour >= 6 && hour < 18 ? 'light' : 'dark'),
|
|
516
|
+
distinctUntilChanged(),
|
|
517
|
+
tap(scheme => theme.setScheme(scheme)),
|
|
518
|
+
takeUntil(this.disconnecting)
|
|
519
|
+
).subscribe()
|
|
520
|
+
}
|
|
521
|
+
}
|
|
236
522
|
```
|
|
237
523
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
Service automatically discovers theme components:
|
|
524
|
+
### Theme-Aware Data Visualization
|
|
241
525
|
|
|
242
526
|
```typescript
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
527
|
+
@customElement('theme-chart')
|
|
528
|
+
export class ThemeChart extends $LitElement() {
|
|
529
|
+
@state() private chartColors = {
|
|
530
|
+
primary: '',
|
|
531
|
+
surface: '',
|
|
532
|
+
error: ''
|
|
247
533
|
}
|
|
248
|
-
|
|
534
|
+
|
|
535
|
+
connectedCallback() {
|
|
536
|
+
super.connectedCallback()
|
|
537
|
+
|
|
538
|
+
// Update chart colors when theme changes
|
|
539
|
+
theme.theme$.pipe(
|
|
540
|
+
tap(themeData => {
|
|
541
|
+
this.chartColors = {
|
|
542
|
+
primary: themeData.primary,
|
|
543
|
+
surface: themeData.surface,
|
|
544
|
+
error: themeData.error
|
|
545
|
+
}
|
|
546
|
+
this.updateChart()
|
|
547
|
+
}),
|
|
548
|
+
takeUntil(this.disconnecting)
|
|
549
|
+
).subscribe()
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
private updateChart() {
|
|
553
|
+
// Use theme colors in charts/visualizations
|
|
554
|
+
// Colors automatically adapt to light/dark mode
|
|
555
|
+
}
|
|
556
|
+
}
|
|
249
557
|
```
|
|
250
558
|
|
|
251
|
-
## CSS
|
|
559
|
+
## Complete CSS Variable Reference
|
|
560
|
+
|
|
561
|
+
All tokens are available as CSS variables with `--schmancy-` prefix:
|
|
562
|
+
|
|
563
|
+
### Color Variables
|
|
564
|
+
```css
|
|
565
|
+
/* Core colors */
|
|
566
|
+
--schmancy-color-primary
|
|
567
|
+
--schmancy-color-onPrimary
|
|
568
|
+
--schmancy-color-primaryContainer
|
|
569
|
+
--schmancy-color-onPrimaryContainer
|
|
570
|
+
|
|
571
|
+
--schmancy-color-secondary
|
|
572
|
+
--schmancy-color-onSecondary
|
|
573
|
+
--schmancy-color-secondaryContainer
|
|
574
|
+
--schmancy-color-onSecondaryContainer
|
|
575
|
+
|
|
576
|
+
--schmancy-color-tertiary
|
|
577
|
+
--schmancy-color-onTertiary
|
|
578
|
+
--schmancy-color-tertiaryContainer
|
|
579
|
+
--schmancy-color-onTertiaryContainer
|
|
580
|
+
|
|
581
|
+
--schmancy-color-error
|
|
582
|
+
--schmancy-color-onError
|
|
583
|
+
--schmancy-color-errorContainer
|
|
584
|
+
--schmancy-color-onErrorContainer
|
|
585
|
+
|
|
586
|
+
/* Extended semantic colors */
|
|
587
|
+
--schmancy-color-success
|
|
588
|
+
--schmancy-color-onSuccess
|
|
589
|
+
--schmancy-color-successContainer
|
|
590
|
+
--schmancy-color-onSuccessContainer
|
|
591
|
+
|
|
592
|
+
--schmancy-color-warning
|
|
593
|
+
--schmancy-color-onWarning
|
|
594
|
+
--schmancy-color-warningContainer
|
|
595
|
+
--schmancy-color-onWarningContainer
|
|
596
|
+
|
|
597
|
+
--schmancy-color-info
|
|
598
|
+
--schmancy-color-onInfo
|
|
599
|
+
--schmancy-color-infoContainer
|
|
600
|
+
--schmancy-color-onInfoContainer
|
|
601
|
+
|
|
602
|
+
/* Surface hierarchy */
|
|
603
|
+
--schmancy-color-surface
|
|
604
|
+
--schmancy-color-onSurface
|
|
605
|
+
--schmancy-color-surfaceVariant
|
|
606
|
+
--schmancy-color-onSurfaceVariant
|
|
607
|
+
--schmancy-color-surfaceDim
|
|
608
|
+
--schmancy-color-surfaceBright
|
|
609
|
+
--schmancy-color-surfaceContainerLowest
|
|
610
|
+
--schmancy-color-surfaceContainerLow
|
|
611
|
+
--schmancy-color-surfaceContainer
|
|
612
|
+
--schmancy-color-surfaceContainerHigh
|
|
613
|
+
--schmancy-color-surfaceContainerHighest
|
|
614
|
+
|
|
615
|
+
/* Fixed variants */
|
|
616
|
+
--schmancy-color-primaryFixed
|
|
617
|
+
--schmancy-color-primaryFixedDim
|
|
618
|
+
--schmancy-color-onPrimaryFixed
|
|
619
|
+
--schmancy-color-onPrimaryFixedVariant
|
|
620
|
+
/* (Same pattern for secondary, tertiary) */
|
|
621
|
+
|
|
622
|
+
/* Other */
|
|
623
|
+
--schmancy-color-outline
|
|
624
|
+
--schmancy-color-outlineVariant
|
|
625
|
+
--schmancy-color-shadow
|
|
626
|
+
--schmancy-color-scrim
|
|
627
|
+
--schmancy-color-inverseSurface
|
|
628
|
+
--schmancy-color-inverseOnSurface
|
|
629
|
+
--schmancy-color-inversePrimary
|
|
630
|
+
```
|
|
252
631
|
|
|
253
|
-
|
|
632
|
+
### Typography Variables
|
|
633
|
+
```css
|
|
634
|
+
/* Display scale */
|
|
635
|
+
--schmancy-typeface-scale-display-large
|
|
636
|
+
--schmancy-typeface-scale-display-medium
|
|
637
|
+
--schmancy-typeface-scale-display-small
|
|
638
|
+
|
|
639
|
+
/* Headline scale */
|
|
640
|
+
--schmancy-typeface-scale-headline-large
|
|
641
|
+
--schmancy-typeface-scale-headline-medium
|
|
642
|
+
--schmancy-typeface-scale-headline-small
|
|
643
|
+
|
|
644
|
+
/* Title scale */
|
|
645
|
+
--schmancy-typeface-scale-title-large
|
|
646
|
+
--schmancy-typeface-scale-title-medium
|
|
647
|
+
--schmancy-typeface-scale-title-small
|
|
648
|
+
|
|
649
|
+
/* Body scale */
|
|
650
|
+
--schmancy-typeface-scale-body-large
|
|
651
|
+
--schmancy-typeface-scale-body-medium
|
|
652
|
+
--schmancy-typeface-scale-body-small
|
|
653
|
+
|
|
654
|
+
/* Label scale */
|
|
655
|
+
--schmancy-typeface-scale-label-large
|
|
656
|
+
--schmancy-typeface-scale-label-medium
|
|
657
|
+
--schmancy-typeface-scale-label-small
|
|
658
|
+
```
|
|
254
659
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
660
|
+
### Motion Variables
|
|
661
|
+
```css
|
|
662
|
+
/* Easing curves */
|
|
663
|
+
--schmancy-motion-easing-emphasized
|
|
664
|
+
--schmancy-motion-easing-emphasizedDecelerate
|
|
665
|
+
--schmancy-motion-easing-emphasizedAccelerate
|
|
666
|
+
--schmancy-motion-easing-standard
|
|
667
|
+
--schmancy-motion-easing-standardDecelerate
|
|
668
|
+
--schmancy-motion-easing-standardAccelerate
|
|
669
|
+
--schmancy-motion-easing-legacy
|
|
670
|
+
--schmancy-motion-easing-linear
|
|
671
|
+
|
|
672
|
+
/* Duration scales */
|
|
673
|
+
--schmancy-motion-duration-short1 /* 50ms */
|
|
674
|
+
--schmancy-motion-duration-short2 /* 100ms */
|
|
675
|
+
--schmancy-motion-duration-short3 /* 150ms */
|
|
676
|
+
--schmancy-motion-duration-short4 /* 200ms */
|
|
677
|
+
|
|
678
|
+
--schmancy-motion-duration-medium1 /* 250ms */
|
|
679
|
+
--schmancy-motion-duration-medium2 /* 300ms */
|
|
680
|
+
--schmancy-motion-duration-medium3 /* 350ms */
|
|
681
|
+
--schmancy-motion-duration-medium4 /* 400ms */
|
|
682
|
+
|
|
683
|
+
--schmancy-motion-duration-long1 /* 450ms */
|
|
684
|
+
--schmancy-motion-duration-long2 /* 500ms */
|
|
685
|
+
--schmancy-motion-duration-long3 /* 550ms */
|
|
686
|
+
--schmancy-motion-duration-long4 /* 600ms */
|
|
687
|
+
|
|
688
|
+
--schmancy-motion-duration-extraLong1 /* 700ms */
|
|
689
|
+
--schmancy-motion-duration-extraLong2 /* 800ms */
|
|
690
|
+
--schmancy-motion-duration-extraLong3 /* 900ms */
|
|
691
|
+
--schmancy-motion-duration-extraLong4 /* 1000ms */
|
|
692
|
+
```
|
|
258
693
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
694
|
+
### Shape Variables
|
|
695
|
+
```css
|
|
696
|
+
--schmancy-shape-corner-none /* 0px */
|
|
697
|
+
--schmancy-shape-corner-extraSmall /* 4px */
|
|
698
|
+
--schmancy-shape-corner-small /* 8px */
|
|
699
|
+
--schmancy-shape-corner-medium /* 12px */
|
|
700
|
+
--schmancy-shape-corner-large /* 16px */
|
|
701
|
+
--schmancy-shape-corner-extraLarge /* 28px */
|
|
702
|
+
--schmancy-shape-corner-full /* 9999px */
|
|
264
703
|
```
|
|
265
704
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
-
|
|
269
|
-
-
|
|
270
|
-
-
|
|
705
|
+
### Elevation Variables
|
|
706
|
+
```css
|
|
707
|
+
--schmancy-elevation-level0
|
|
708
|
+
--schmancy-elevation-level1
|
|
709
|
+
--schmancy-elevation-level2
|
|
710
|
+
--schmancy-elevation-level3
|
|
711
|
+
--schmancy-elevation-level4
|
|
712
|
+
--schmancy-elevation-level5
|
|
713
|
+
```
|
|
271
714
|
|
|
272
|
-
|
|
715
|
+
### State Variables
|
|
716
|
+
```css
|
|
717
|
+
--schmancy-states-hover-stateLayerOpacity /* 0.08 */
|
|
718
|
+
--schmancy-states-focus-stateLayerOpacity /* 0.1 */
|
|
719
|
+
--schmancy-states-pressed-stateLayerOpacity /* 0.1 */
|
|
720
|
+
--schmancy-states-dragged-stateLayerOpacity /* 0.15 */
|
|
721
|
+
--schmancy-states-disabled-containerOpacity /* 0.12 */
|
|
722
|
+
--schmancy-states-disabled-contentOpacity /* 0.38 */
|
|
723
|
+
```
|
|
273
724
|
|
|
274
|
-
###
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
725
|
+
### Spacing Variables
|
|
726
|
+
```css
|
|
727
|
+
--schmancy-spacing-size-none /* 0px */
|
|
728
|
+
--schmancy-spacing-size-s1 /* 4px */
|
|
729
|
+
--schmancy-spacing-size-s2 /* 8px */
|
|
730
|
+
--schmancy-spacing-size-s3 /* 12px */
|
|
731
|
+
--schmancy-spacing-size-s4 /* 16px */
|
|
732
|
+
--schmancy-spacing-size-s5 /* 20px */
|
|
733
|
+
--schmancy-spacing-size-s6 /* 24px */
|
|
734
|
+
--schmancy-spacing-size-s7 /* 28px */
|
|
735
|
+
--schmancy-spacing-size-s8 /* 32px */
|
|
736
|
+
--schmancy-spacing-size-s9 /* 36px */
|
|
737
|
+
--schmancy-spacing-size-s10 /* 40px */
|
|
738
|
+
--schmancy-spacing-size-s11 /* 44px */
|
|
739
|
+
--schmancy-spacing-size-s12 /* 48px */
|
|
280
740
|
```
|
|
281
741
|
|
|
282
|
-
##
|
|
742
|
+
## Fullscreen Integration
|
|
743
|
+
|
|
744
|
+
Navigation components automatically respond to fullscreen:
|
|
283
745
|
|
|
284
746
|
```typescript
|
|
285
|
-
//
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
747
|
+
// Enter fullscreen (hides navigation)
|
|
748
|
+
theme.setFullscreen(true)
|
|
749
|
+
|
|
750
|
+
// Custom component integration
|
|
751
|
+
fromEvent(window, 'fullscreen').pipe(
|
|
752
|
+
tap((e: CustomEvent) => {
|
|
753
|
+
this.hidden = e.detail
|
|
754
|
+
}),
|
|
290
755
|
takeUntil(this.disconnecting)
|
|
291
756
|
).subscribe()
|
|
292
757
|
```
|
|
293
758
|
|
|
759
|
+
## System Preference Detection
|
|
760
|
+
|
|
761
|
+
Auto mode follows system preferences with automatic updates:
|
|
762
|
+
|
|
763
|
+
```typescript
|
|
764
|
+
// Set to auto - follows system preference
|
|
765
|
+
theme.setScheme('auto')
|
|
766
|
+
|
|
767
|
+
// resolvedScheme$ automatically updates when system changes
|
|
768
|
+
// Uses MediaQueryList with listeners for real-time updates
|
|
769
|
+
theme.resolvedScheme$.subscribe(scheme => {
|
|
770
|
+
// Always 'dark' or 'light', never 'auto'
|
|
771
|
+
// Updates immediately when user changes OS theme
|
|
772
|
+
})
|
|
773
|
+
```
|
|
774
|
+
|
|
294
775
|
## Best Practices
|
|
295
776
|
|
|
296
777
|
1. **Always use observables** for reactive updates
|
|
297
|
-
2. **
|
|
298
|
-
3. **Use `
|
|
299
|
-
4. **
|
|
300
|
-
5. **Use
|
|
301
|
-
6. **
|
|
778
|
+
2. **Prefer `resolvedScheme$`** over `scheme$` for UI logic (never returns 'auto')
|
|
779
|
+
3. **Use `next()` method** for batch updates to avoid multiple emissions
|
|
780
|
+
4. **Let theme persist automatically** - no manual localStorage needed
|
|
781
|
+
5. **Use motion tokens** for consistent animations across the app
|
|
782
|
+
6. **Leverage extended colors** (success, warning, info) for semantic meaning
|
|
783
|
+
7. **Use surface hierarchy** for proper elevation and depth
|
|
784
|
+
8. **Apply state opacities** for consistent interaction feedback
|
|
785
|
+
9. **Call `super.connectedCallback()`** when subscribing to observables
|
|
786
|
+
10. **Use `takeUntil(this.disconnecting)`** for proper cleanup
|
|
302
787
|
|
|
303
788
|
## Common Patterns
|
|
304
789
|
|
|
305
|
-
###
|
|
790
|
+
### Complete Theme Toggle Component
|
|
306
791
|
```typescript
|
|
307
|
-
theme
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
).subscribe()
|
|
792
|
+
@customElement('advanced-theme-toggle')
|
|
793
|
+
export class AdvancedThemeToggle extends $LitElement() {
|
|
794
|
+
@state() private resolvedScheme: 'dark' | 'light' = 'light'
|
|
795
|
+
@state() private actualScheme: string = 'auto'
|
|
312
796
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if (saved) theme.setScheme(saved as any)
|
|
316
|
-
```
|
|
797
|
+
connectedCallback() {
|
|
798
|
+
super.connectedCallback()
|
|
317
799
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
800
|
+
// Track both actual and resolved scheme
|
|
801
|
+
combineLatest([
|
|
802
|
+
theme.scheme$,
|
|
803
|
+
theme.resolvedScheme$
|
|
804
|
+
]).pipe(
|
|
805
|
+
tap(([scheme, resolved]) => {
|
|
806
|
+
this.actualScheme = scheme
|
|
807
|
+
this.resolvedScheme = resolved
|
|
808
|
+
}),
|
|
809
|
+
takeUntil(this.disconnecting)
|
|
810
|
+
).subscribe()
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
render() {
|
|
814
|
+
return html`
|
|
815
|
+
<div class="flex gap-2">
|
|
816
|
+
<button
|
|
817
|
+
@click=${() => theme.setScheme('light')}
|
|
818
|
+
class=${this.actualScheme === 'light' ? 'active' : ''}
|
|
819
|
+
>
|
|
820
|
+
☀️ Light
|
|
821
|
+
</button>
|
|
822
|
+
<button
|
|
823
|
+
@click=${() => theme.setScheme('dark')}
|
|
824
|
+
class=${this.actualScheme === 'dark' ? 'active' : ''}
|
|
825
|
+
>
|
|
826
|
+
🌙 Dark
|
|
827
|
+
</button>
|
|
828
|
+
<button
|
|
829
|
+
@click=${() => theme.setScheme('auto')}
|
|
830
|
+
class=${this.actualScheme === 'auto' ? 'active' : ''}
|
|
831
|
+
>
|
|
832
|
+
🔄 Auto (${this.resolvedScheme})
|
|
833
|
+
</button>
|
|
834
|
+
</div>
|
|
835
|
+
`
|
|
836
|
+
}
|
|
837
|
+
}
|
|
325
838
|
```
|
|
326
839
|
|
|
327
840
|
### Fullscreen Video Player
|
|
328
841
|
```typescript
|
|
329
|
-
|
|
842
|
+
@customElement('video-player')
|
|
843
|
+
export class VideoPlayer extends $LitElement() {
|
|
844
|
+
private videoRef = createRef<HTMLVideoElement>()
|
|
845
|
+
|
|
330
846
|
private enterFullscreen() {
|
|
331
847
|
theme.setFullscreen(true)
|
|
332
|
-
this.
|
|
848
|
+
this.videoRef.value?.requestFullscreen()
|
|
333
849
|
}
|
|
334
850
|
|
|
335
851
|
private exitFullscreen() {
|
|
336
852
|
theme.setFullscreen(false)
|
|
337
853
|
document.exitFullscreen()
|
|
338
854
|
}
|
|
855
|
+
|
|
856
|
+
render() {
|
|
857
|
+
return html`
|
|
858
|
+
<video ${ref(this.videoRef)}>
|
|
859
|
+
<!-- Video content -->
|
|
860
|
+
</video>
|
|
861
|
+
`
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### Dynamic Motion Timing
|
|
867
|
+
```typescript
|
|
868
|
+
@customElement('animated-component')
|
|
869
|
+
export class AnimatedComponent extends $LitElement() {
|
|
870
|
+
@state() private isExpanded = false
|
|
871
|
+
|
|
872
|
+
render() {
|
|
873
|
+
return html`
|
|
874
|
+
<style>
|
|
875
|
+
.panel {
|
|
876
|
+
transition: height
|
|
877
|
+
var(--schmancy-motion-duration-medium2)
|
|
878
|
+
var(--schmancy-motion-easing-emphasized);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
.fade-in {
|
|
882
|
+
animation: fadeIn
|
|
883
|
+
var(--schmancy-motion-duration-short3)
|
|
884
|
+
var(--schmancy-motion-easing-emphasizedDecelerate);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
@keyframes fadeIn {
|
|
888
|
+
from { opacity: 0; }
|
|
889
|
+
to { opacity: 1; }
|
|
890
|
+
}
|
|
891
|
+
</style>
|
|
892
|
+
|
|
893
|
+
<div class="panel ${this.isExpanded ? 'expanded' : ''}">
|
|
894
|
+
<!-- Content with smooth animations -->
|
|
895
|
+
</div>
|
|
896
|
+
`
|
|
897
|
+
}
|
|
339
898
|
}
|
|
340
899
|
```
|
|
341
900
|
|
|
342
901
|
## Integration with Theme Component
|
|
343
902
|
|
|
344
|
-
The service works with `<schmancy-theme>` component:
|
|
903
|
+
The service works bidirectionally with `<schmancy-theme>` component:
|
|
345
904
|
|
|
346
905
|
```html
|
|
347
906
|
<schmancy-theme color="#6750A4" scheme="auto">
|
|
348
|
-
<!--
|
|
907
|
+
<!-- All children have access to theme tokens -->
|
|
349
908
|
</schmancy-theme>
|
|
350
909
|
```
|
|
351
910
|
|
|
352
|
-
Component automatically
|
|
911
|
+
Component automatically:
|
|
912
|
+
- Registers with service via discovery events
|
|
913
|
+
- Syncs state bidirectionally
|
|
914
|
+
- Generates full M3 token system
|
|
915
|
+
- Updates CSS variables in real-time
|
|
916
|
+
- Persists settings to localStorage
|
|
917
|
+
|
|
918
|
+
## Error Handling
|
|
919
|
+
|
|
920
|
+
```typescript
|
|
921
|
+
// Graceful fallback when theme component is missing
|
|
922
|
+
theme.discoverTheme().pipe(
|
|
923
|
+
timeout(1000),
|
|
924
|
+
catchError(() => {
|
|
925
|
+
console.warn('Theme component not found, using defaults')
|
|
926
|
+
return of(null)
|
|
927
|
+
})
|
|
928
|
+
).subscribe()
|
|
929
|
+
|
|
930
|
+
// Validate color input
|
|
931
|
+
const isValidHex = (color: string) => /^#[0-9A-F]{6}$/i.test(color)
|
|
932
|
+
|
|
933
|
+
if (isValidHex(newColor)) {
|
|
934
|
+
theme.setColor(newColor)
|
|
935
|
+
} else {
|
|
936
|
+
console.error('Invalid color format')
|
|
937
|
+
}
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
## Performance Considerations
|
|
941
|
+
|
|
942
|
+
1. **Token Generation**: Full M3 theme is generated once per color change
|
|
943
|
+
2. **CSS Variables**: Updated atomically via `adoptedStyleSheets`
|
|
944
|
+
3. **Persistence**: Debounced writes to localStorage (via context)
|
|
945
|
+
4. **Discovery**: One-time discovery with 1s timeout
|
|
946
|
+
5. **MediaQuery**: Single listener for system preference changes
|
|
947
|
+
6. **Observables**: Multicast for efficient subscriptions
|
|
948
|
+
|
|
949
|
+
## Migration Guide
|
|
950
|
+
|
|
951
|
+
From manual theme management:
|
|
952
|
+
```typescript
|
|
953
|
+
// Old way
|
|
954
|
+
localStorage.setItem('theme', 'dark')
|
|
955
|
+
document.body.classList.add('dark-theme')
|
|
956
|
+
|
|
957
|
+
// New way
|
|
958
|
+
theme.setScheme('dark') // Automatic persistence & styling
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
From custom CSS variables:
|
|
962
|
+
```typescript
|
|
963
|
+
// Old way
|
|
964
|
+
:root {
|
|
965
|
+
--primary: #6750A4;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// New way - Full M3 system generated
|
|
969
|
+
theme.setColor('#6750A4') // Generates 100+ tokens
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
## Summary
|
|
973
|
+
|
|
974
|
+
The theme service provides a complete Material Design 3 implementation with:
|
|
975
|
+
- 🎨 **Extended color system** with semantic colors
|
|
976
|
+
- 📐 **Complete surface hierarchy** for proper elevation
|
|
977
|
+
- 🔤 **Full typography scale** across 5 categories
|
|
978
|
+
- 🎬 **Sophisticated motion system** with easing and duration
|
|
979
|
+
- 🔲 **Shape tokens** for consistent corner radii
|
|
980
|
+
- 💾 **Automatic persistence** via context
|
|
981
|
+
- 🔍 **Smart discovery** with bidirectional events
|
|
982
|
+
- 🌓 **System preference detection** with real-time updates
|
|
983
|
+
- 🎯 **Ready-to-use controls** component
|
|
984
|
+
- ⚡ **Reactive observables** for all properties
|
|
985
|
+
|
|
986
|
+
Use the theme service as your single source of truth for all design tokens and theming needs.
|