@mhmo91/schmancy 0.5.35 → 0.5.36
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/content-drawer.md +114 -140
- package/ai/navigation-bar.md +30 -4
- package/ai/navigation-rail.md +72 -0
- package/ai/theme.md +218 -789
- package/dist/ai/content-drawer.md +114 -140
- package/dist/ai/navigation-bar.md +30 -4
- package/dist/ai/navigation-rail.md +72 -0
- package/dist/ai/theme.md +218 -789
- package/dist/{animated-text-COvhr8E3.js → animated-text-BEAHZetl.js} +4 -3
- package/dist/{animated-text-COvhr8E3.js.map → animated-text-BEAHZetl.js.map} +1 -1
- package/dist/{animated-text-BZUrBdvN.cjs → animated-text-ChV1GUee.cjs} +2 -2
- package/dist/{animated-text-BZUrBdvN.cjs.map → animated-text-ChV1GUee.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-BHtBHWVt.js → area.component-R4KQInpP.js} +4 -3
- package/dist/{area.component-BHtBHWVt.js.map → area.component-R4KQInpP.js.map} +1 -1
- package/dist/area.component-cxxQIhCN.cjs +12 -0
- package/dist/{area.component-Ch2Eaa4i.cjs.map → area.component-cxxQIhCN.cjs.map} +1 -1
- package/dist/area.js +1 -1
- package/dist/{autocomplete-CenwFcT1.cjs → autocomplete-Cq_NzrBX.cjs} +2 -2
- package/dist/{autocomplete-CenwFcT1.cjs.map → autocomplete-Cq_NzrBX.cjs.map} +1 -1
- package/dist/{autocomplete-9RkU9LmA.js → autocomplete-DKYBmt2q.js} +18 -18
- package/dist/{autocomplete-9RkU9LmA.js.map → autocomplete-DKYBmt2q.js.map} +1 -1
- package/dist/autocomplete.cjs +1 -1
- package/dist/autocomplete.js +1 -1
- package/dist/{avatar-CjjwZDsw.js → avatar-DJ7qYc6-.js} +144 -134
- package/dist/avatar-DJ7qYc6-.js.map +1 -0
- package/dist/avatar-DbUCDe1w.cjs +306 -0
- package/dist/avatar-DbUCDe1w.cjs.map +1 -0
- package/dist/badge.cjs +1 -1
- package/dist/badge.js +1 -1
- package/dist/boat-BBFE1yJY.js +276 -0
- package/dist/boat-BBFE1yJY.js.map +1 -0
- package/dist/boat-BSYtwy1W.cjs +78 -0
- package/dist/boat-BSYtwy1W.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-8djp_8NK.cjs → checkbox-BBJqucMb.cjs} +2 -2
- package/dist/{checkbox-8djp_8NK.cjs.map → checkbox-BBJqucMb.cjs.map} +1 -1
- package/dist/{checkbox-D6-WQeEk.js → checkbox-geD1IIHh.js} +3 -2
- package/dist/{checkbox-D6-WQeEk.js.map → checkbox-geD1IIHh.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-BFoEmN8y.cjs → code-preview-CR3U6wXD.cjs} +5 -5
- package/dist/{code-preview-BFoEmN8y.cjs.map → code-preview-CR3U6wXD.cjs.map} +1 -1
- package/dist/{code-preview-Z02-2suM.js → code-preview-D2ZpTZ7C.js} +8 -8
- package/dist/{code-preview-Z02-2suM.js.map → code-preview-D2ZpTZ7C.js.map} +1 -1
- package/dist/components.cjs +1 -1
- package/dist/components.js +1 -1
- package/dist/content-drawer.cjs +1 -1
- package/dist/content-drawer.js +1 -1
- package/dist/context-create-CA907mdD.cjs +2 -0
- package/dist/context-create-CA907mdD.cjs.map +1 -0
- package/dist/{context-object-BE1o2XB3.js → context-create-DCiujzV2.js} +262 -212
- package/dist/context-create-DCiujzV2.js.map +1 -0
- package/dist/{date-range-DoCtnpW6.cjs → date-range-DkSLcajW.cjs} +2 -2
- package/dist/{date-range-DoCtnpW6.cjs.map → date-range-DkSLcajW.cjs.map} +1 -1
- package/dist/{date-range-kFnTrnHN.js → date-range-NB6Q02hz.js} +141 -140
- package/dist/{date-range-kFnTrnHN.js.map → date-range-NB6Q02hz.js.map} +1 -1
- package/dist/date-range-inline-C8InUZoD.cjs +44 -0
- package/dist/{date-range-inline-DNr7C5X-.cjs.map → date-range-inline-C8InUZoD.cjs.map} +1 -1
- package/dist/{date-range-inline-BXeX6T7R.js → date-range-inline-DXBR0Ocx.js} +8 -7
- package/dist/{date-range-inline-BXeX6T7R.js.map → date-range-inline-DXBR0Ocx.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-CrdOikhP.cjs → delay-B4IPKZEn.cjs} +2 -2
- package/dist/{delay-CrdOikhP.cjs.map → delay-B4IPKZEn.cjs.map} +1 -1
- package/dist/{delay-Cz-9rZxi.js → delay-DsOC-uuq.js} +2 -2
- package/dist/{delay-Cz-9rZxi.js.map → delay-DsOC-uuq.js.map} +1 -1
- package/dist/delay.cjs +1 -1
- package/dist/delay.js +1 -1
- package/dist/{details-CsqhGMjL.cjs → details-7pcQWJF9.cjs} +2 -2
- package/dist/{details-CsqhGMjL.cjs.map → details-7pcQWJF9.cjs.map} +1 -1
- package/dist/{details-DeBtsJlp.js → details-D6Vq36lN.js} +3 -2
- package/dist/{details-DeBtsJlp.js.map → details-D6Vq36lN.js.map} +1 -1
- package/dist/details.cjs +1 -1
- package/dist/details.js +1 -1
- package/dist/{dialog-content-BzSQoM2J.cjs → dialog-content-BC--KBf7.cjs} +2 -2
- package/dist/{dialog-content-BzSQoM2J.cjs.map → dialog-content-BC--KBf7.cjs.map} +1 -1
- package/dist/{dialog-content-DTKdAF_l.js → dialog-content-XoKxxGTv.js} +4 -4
- package/dist/{dialog-content-DTKdAF_l.js.map → dialog-content-XoKxxGTv.js.map} +1 -1
- package/dist/dialog.cjs +1 -1
- package/dist/dialog.js +1 -1
- package/dist/discovery.cjs +2 -0
- package/dist/discovery.cjs.map +1 -0
- package/dist/discovery.js +6 -0
- package/dist/discovery.js.map +1 -0
- package/dist/discovery.service-BbYjU5x8.js +21 -0
- package/dist/discovery.service-BbYjU5x8.js.map +1 -0
- package/dist/discovery.service-BpGCuXPd.cjs +2 -0
- package/dist/discovery.service-BpGCuXPd.cjs.map +1 -0
- package/dist/divider-55yUklFI.cjs +2 -0
- package/dist/{divider-CNxOc8ep.cjs.map → divider-55yUklFI.cjs.map} +1 -1
- package/dist/{divider-7iyyEd8k.js → divider-JaB5FtmR.js} +4 -3
- package/dist/{divider-7iyyEd8k.js.map → divider-JaB5FtmR.js.map} +1 -1
- package/dist/divider.cjs +1 -1
- package/dist/divider.js +1 -1
- package/dist/{dropdown-content-De0OkNoq.cjs → dropdown-content-C2nxdAFA.cjs} +2 -2
- package/dist/{dropdown-content-De0OkNoq.cjs.map → dropdown-content-C2nxdAFA.cjs.map} +1 -1
- package/dist/{dropdown-content-_GMpqsNq.js → dropdown-content-Qzt-B1FB.js} +4 -3
- package/dist/{dropdown-content-_GMpqsNq.js.map → dropdown-content-Qzt-B1FB.js.map} +1 -1
- package/dist/dropdown.cjs +1 -1
- package/dist/dropdown.js +1 -1
- package/dist/{email-recipients-DS01C3V3.cjs → email-recipients-7reIxhmF.cjs} +2 -2
- package/dist/{email-recipients-DS01C3V3.cjs.map → email-recipients-7reIxhmF.cjs.map} +1 -1
- package/dist/{email-recipients-CPZlUiRR.js → email-recipients-C3TfQU2c.js} +6 -5
- package/dist/{email-recipients-CPZlUiRR.js.map → email-recipients-C3TfQU2c.js.map} +1 -1
- package/dist/extra.cjs +1 -1
- package/dist/extra.js +1 -1
- package/dist/{flex-CHf9Gc5V.cjs → flex-1y7FNRpS.cjs} +2 -2
- package/dist/{flex-CHf9Gc5V.cjs.map → flex-1y7FNRpS.cjs.map} +1 -1
- package/dist/{flex-BeSoRNTu.js → flex-DauT7n0E.js} +3 -2
- package/dist/{flex-BeSoRNTu.js.map → flex-DauT7n0E.js.map} +1 -1
- package/dist/{form-DNeKagke.js → form-DqA7DfNR.js} +3 -2
- package/dist/{form-DNeKagke.js.map → form-DqA7DfNR.js.map} +1 -1
- package/dist/form-Xg8jZsBF.cjs +2 -0
- package/dist/{form-DzDksPgv.cjs.map → form-Xg8jZsBF.cjs.map} +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.js +1 -1
- package/dist/{formField.mixin-D5YAYIS1.cjs → formField.mixin-BnSYnYXQ.cjs} +2 -2
- package/dist/{formField.mixin-D5YAYIS1.cjs.map → formField.mixin-BnSYnYXQ.cjs.map} +1 -1
- package/dist/{formField.mixin-BNj75WQ4.js → formField.mixin-YvrrvL_A.js} +2 -2
- package/dist/{formField.mixin-BNj75WQ4.js.map → formField.mixin-YvrrvL_A.js.map} +1 -1
- package/dist/{icon-DebIySqv.cjs → icon-BFYUD00J.cjs} +3 -3
- package/dist/{icon-DebIySqv.cjs.map → icon-BFYUD00J.cjs.map} +1 -1
- package/dist/{icon-CCMpTJTp.js → icon-BtdeB2JT.js} +9 -9
- package/dist/{icon-CCMpTJTp.js.map → icon-BtdeB2JT.js.map} +1 -1
- package/dist/{icon-button-DwnnW2oj.cjs → icon-button-B-uxvO86.cjs} +2 -2
- package/dist/{icon-button-DwnnW2oj.cjs.map → icon-button-B-uxvO86.cjs.map} +1 -1
- package/dist/{icon-button-D6DH52j4.js → icon-button-DwL4WnDE.js} +4 -3
- package/dist/{icon-button-D6DH52j4.js.map → icon-button-DwL4WnDE.js.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 +187 -182
- package/dist/index.js.map +1 -1
- package/dist/{input-DtHPCCyd.js → input-CuOmXLVJ.js} +4 -3
- package/dist/{input-DtHPCCyd.js.map → input-CuOmXLVJ.js.map} +1 -1
- package/dist/input-PoerIsqx.cjs +51 -0
- package/dist/{input-C2Vz-51i.cjs.map → input-PoerIsqx.cjs.map} +1 -1
- package/dist/{input-chip-B7ANrtLF.cjs → input-chip-BlmZB-cO.cjs} +2 -2
- package/dist/{input-chip-B7ANrtLF.cjs.map → input-chip-BlmZB-cO.cjs.map} +1 -1
- package/dist/{input-chip-DbIvSyvP.js → input-chip-CcNElytP.js} +2 -2
- package/dist/{input-chip-DbIvSyvP.js.map → input-chip-CcNElytP.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-BH8OJ3Rv.cjs → list-BJjW-iAW.cjs} +2 -2
- package/dist/{list-BH8OJ3Rv.cjs.map → list-BJjW-iAW.cjs.map} +1 -1
- package/dist/{list-BBo0--_Q.js → list-Bou3BRYQ.js} +3 -2
- package/dist/{list-BBo0--_Q.js.map → list-Bou3BRYQ.js.map} +1 -1
- package/dist/list.cjs +1 -1
- package/dist/list.js +1 -1
- package/dist/{litElement.mixin-CzF0mNQd.js → litElement.mixin-Bkdw4DeE.js} +2 -2
- package/dist/{litElement.mixin-CzF0mNQd.js.map → litElement.mixin-Bkdw4DeE.js.map} +1 -1
- package/dist/{litElement.mixin-LplXbzd8.cjs → litElement.mixin-Di-HgRnn.cjs} +2 -2
- package/dist/{litElement.mixin-LplXbzd8.cjs.map → litElement.mixin-Di-HgRnn.cjs.map} +1 -1
- package/dist/mailbox.cjs +1 -1
- package/dist/mailbox.js +1 -1
- package/dist/{map-C7lxYU4A.cjs → map-CXNKwo__.cjs} +2 -2
- package/dist/{map-C7lxYU4A.cjs.map → map-CXNKwo__.cjs.map} +1 -1
- package/dist/{map-DeiCBxMP.js → map-bUVyL7jN.js} +19 -19
- package/dist/{map-DeiCBxMP.js.map → map-bUVyL7jN.js.map} +1 -1
- package/dist/map.cjs +1 -1
- package/dist/map.js +1 -1
- package/dist/{media-CsYVcfaX.cjs → media-8D6oDv1e.cjs} +6 -6
- package/dist/{media-CsYVcfaX.cjs.map → media-8D6oDv1e.cjs.map} +1 -1
- package/dist/{media-CEnaqjig.js → media-CF1lpFAm.js} +9 -8
- package/dist/{media-CEnaqjig.js.map → media-CF1lpFAm.js.map} +1 -1
- package/dist/{menu-Boqsyfmh.cjs → menu-B8Ad1OVm.cjs} +2 -2
- package/dist/{menu-Boqsyfmh.cjs.map → menu-B8Ad1OVm.cjs.map} +1 -1
- package/dist/{menu-wtkHGlyc.js → menu-C9mJa_ck.js} +4 -3
- package/dist/{menu-wtkHGlyc.js.map → menu-C9mJa_ck.js.map} +1 -1
- package/dist/menu.cjs +1 -1
- package/dist/menu.js +1 -1
- package/dist/mixins/baseElement.ts +33 -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-6ONc-XE-.cjs → navigation-rail-CAgKSJh4.cjs} +14 -11
- package/dist/navigation-rail-CAgKSJh4.cjs.map +1 -0
- package/dist/{navigation-rail-D-lK9oVd.js → navigation-rail-Dh3B6B0L.js} +43 -31
- package/dist/navigation-rail-Dh3B6B0L.js.map +1 -0
- package/dist/navigation-rail.cjs +1 -1
- package/dist/navigation-rail.js +1 -1
- package/dist/{notification-service-ZiGUSd63.js → notification-service-IBQJTcmw.js} +7 -6
- package/dist/{notification-service-ZiGUSd63.js.map → notification-service-IBQJTcmw.js.map} +1 -1
- package/dist/{notification-service-9HXSKWcw.cjs → notification-service-L82ozhd0.cjs} +2 -2
- package/dist/{notification-service-9HXSKWcw.cjs.map → notification-service-L82ozhd0.cjs.map} +1 -1
- package/dist/notification.cjs +1 -1
- package/dist/notification.js +2 -2
- package/dist/{notify-W-NrP0cC.cjs → notify-AIKWEjDG.cjs} +2 -2
- package/dist/{notify-W-NrP0cC.cjs.map → notify-AIKWEjDG.cjs.map} +1 -1
- package/dist/{notify-DbfX6Z2P.js → notify-CtxRmxjL.js} +2 -2
- package/dist/{notify-DbfX6Z2P.js.map → notify-CtxRmxjL.js.map} +1 -1
- package/dist/{option-D2bxihLu.cjs → option-D5OW1kDk.cjs} +2 -2
- package/dist/{option-D2bxihLu.cjs.map → option-D5OW1kDk.cjs.map} +1 -1
- package/dist/{option-BFlWiCu0.js → option-DHGTgRBn.js} +11 -10
- package/dist/{option-BFlWiCu0.js.map → option-DHGTgRBn.js.map} +1 -1
- package/dist/option.cjs +1 -1
- package/dist/option.js +1 -1
- package/dist/payment-card-form-CHS_s_Fk.cjs +74 -0
- package/dist/{payment-card-form--v94EhJF.cjs.map → payment-card-form-CHS_s_Fk.cjs.map} +1 -1
- package/dist/{payment-card-form-DLRNX9NX.js → payment-card-form-wj2JWoyn.js} +4 -3
- package/dist/{payment-card-form-DLRNX9NX.js.map → payment-card-form-wj2JWoyn.js.map} +1 -1
- package/dist/{progress-CjkD8QBy.cjs → progress-CP4R_l3i.cjs} +2 -2
- package/dist/{progress-CjkD8QBy.cjs.map → progress-CP4R_l3i.cjs.map} +1 -1
- package/dist/{progress-BYohUvYO.js → progress-ZrDv_k3Z.js} +10 -9
- package/dist/{progress-BYohUvYO.js.map → progress-ZrDv_k3Z.js.map} +1 -1
- package/dist/progress.cjs +1 -1
- package/dist/progress.js +1 -1
- package/dist/{radio-button-CGmGOAil.cjs → radio-button-BXP_yPjS.cjs} +2 -2
- package/dist/{radio-button-CGmGOAil.cjs.map → radio-button-BXP_yPjS.cjs.map} +1 -1
- package/dist/{radio-button-BlxeCjdq.js → radio-button-D0pVoIe-.js} +4 -3
- package/dist/{radio-button-BlxeCjdq.js.map → radio-button-D0pVoIe-.js.map} +1 -1
- package/dist/radio-group.cjs +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/{schmancy-steps-container-CydL78yk.cjs → schmancy-steps-container-BSv1aURP.cjs} +2 -2
- package/dist/{schmancy-steps-container-CydL78yk.cjs.map → schmancy-steps-container-BSv1aURP.cjs.map} +1 -1
- package/dist/{schmancy-steps-container-BtAHCm73.js → schmancy-steps-container-vjioa19k.js} +2 -2
- package/dist/{schmancy-steps-container-BtAHCm73.js.map → schmancy-steps-container-vjioa19k.js.map} +1 -1
- package/dist/{select-CrB02cIO.cjs → select-DZ-Cy-lg.cjs} +2 -2
- package/dist/{select-CrB02cIO.cjs.map → select-DZ-Cy-lg.cjs.map} +1 -1
- package/dist/{select-BiN334GN.js → select-SgSe22qC.js} +13 -13
- package/dist/{select-BiN334GN.js.map → select-SgSe22qC.js.map} +1 -1
- package/dist/select.cjs +1 -1
- package/dist/select.js +1 -1
- package/dist/selector-hook-BWMY8npH.cjs +2 -0
- package/dist/selector-hook-BWMY8npH.cjs.map +1 -0
- package/dist/selector-hook-CKeyK4K-.js +313 -0
- package/dist/selector-hook-CKeyK4K-.js.map +1 -0
- package/dist/{sheet-sgVoRMi1.cjs → sheet-CNMKrulQ.cjs} +2 -2
- package/dist/{sheet-sgVoRMi1.cjs.map → sheet-CNMKrulQ.cjs.map} +1 -1
- package/dist/{sheet-DpJv4DRi.js → sheet-CevNG0tZ.js} +4 -3
- package/dist/{sheet-DpJv4DRi.js.map → sheet-CevNG0tZ.js.map} +1 -1
- package/dist/sheet.cjs +1 -1
- package/dist/sheet.js +1 -1
- package/dist/{slider-Dd1L6oYm.cjs → slider-BSxJatG-.cjs} +4 -4
- package/dist/{slider-Dd1L6oYm.cjs.map → slider-BSxJatG-.cjs.map} +1 -1
- package/dist/{slider-D7qdxfvX.js → slider-DIRocNv8.js} +9 -9
- package/dist/{slider-D7qdxfvX.js.map → slider-DIRocNv8.js.map} +1 -1
- package/dist/slider.cjs +1 -1
- package/dist/slider.js +1 -1
- package/dist/{spinner-CaXU45TV.cjs → spinner-Cx54uto8.cjs} +2 -2
- package/dist/{spinner-CaXU45TV.cjs.map → spinner-Cx54uto8.cjs.map} +1 -1
- package/dist/{spinner-XN4W5ihQ.js → spinner-DZcG-AtO.js} +3 -2
- package/dist/{spinner-XN4W5ihQ.js.map → spinner-DZcG-AtO.js.map} +1 -1
- package/dist/steps.cjs +1 -1
- package/dist/steps.js +1 -1
- package/dist/store.cjs +1 -1
- package/dist/store.js +26 -26
- package/dist/{suggestion-chip-CdhoATv9.js → suggestion-chip-DADIje6B.js} +3 -3
- package/dist/{suggestion-chip-CdhoATv9.js.map → suggestion-chip-DADIje6B.js.map} +1 -1
- package/dist/{suggestion-chip-PI24Hc3s.cjs → suggestion-chip-ssmmc0q6.cjs} +2 -2
- package/dist/{suggestion-chip-PI24Hc3s.cjs.map → suggestion-chip-ssmmc0q6.cjs.map} +1 -1
- package/dist/{surface-CKrYJ58l.js → surface-_cS9Ehk0.js} +2 -2
- package/dist/{surface-CKrYJ58l.js.map → surface-_cS9Ehk0.js.map} +1 -1
- package/dist/{surface-Ax6I7ldp.cjs → surface-ix9qOb7a.cjs} +2 -2
- package/dist/{surface-Ax6I7ldp.cjs.map → surface-ix9qOb7a.cjs.map} +1 -1
- package/dist/surface.cjs +1 -1
- package/dist/surface.js +1 -1
- package/dist/{table-CP6_NkPm.js → table-Bi2ftsJe.js} +2 -2
- package/dist/{table-CP6_NkPm.js.map → table-Bi2ftsJe.js.map} +1 -1
- package/dist/{table-BlwUyf_4.cjs → table-DSEK3bMb.cjs} +2 -2
- package/dist/{table-BlwUyf_4.cjs.map → table-DSEK3bMb.cjs.map} +1 -1
- package/dist/table.cjs +1 -1
- package/dist/table.js +1 -1
- package/dist/{tabs-compatibility-CX0cIu_Y.cjs → tabs-compatibility-BE2Q3rig.cjs} +4 -4
- package/dist/{tabs-compatibility-CX0cIu_Y.cjs.map → tabs-compatibility-BE2Q3rig.cjs.map} +1 -1
- package/dist/{tabs-compatibility-7QKuXX4i.js → tabs-compatibility-DA3RIq35.js} +7 -6
- package/dist/{tabs-compatibility-7QKuXX4i.js.map → tabs-compatibility-DA3RIq35.js.map} +1 -1
- package/dist/tabs.cjs +1 -1
- package/dist/tabs.js +1 -1
- package/dist/tailwind.mixin-CvQn8Ynb.cjs +2 -0
- package/dist/tailwind.mixin-CvQn8Ynb.cjs.map +1 -0
- package/dist/tailwind.mixin-DGLcZhRp.js +57 -0
- package/dist/tailwind.mixin-DGLcZhRp.js.map +1 -0
- package/dist/teleport.cjs +1 -1
- package/dist/teleport.js +1 -1
- package/dist/{textarea-DHrDn-O6.js → textarea-CBb2CzKu.js} +3 -2
- package/dist/{textarea-DHrDn-O6.js.map → textarea-CBb2CzKu.js.map} +1 -1
- package/dist/textarea-ClgK_mP6.cjs +44 -0
- package/dist/{textarea-qLA0vP78.cjs.map → textarea-ClgK_mP6.cjs.map} +1 -1
- package/dist/textarea.cjs +1 -1
- package/dist/textarea.js +1 -1
- package/dist/theme-button-Dhp3ozyB.cjs +9 -0
- package/dist/{theme-button-D7fBEUGf.cjs.map → theme-button-Dhp3ozyB.cjs.map} +1 -1
- package/dist/{theme-button-BEUsbH5m.js → theme-button-Z_xWXMaf.js} +6 -5
- package/dist/{theme-button-BEUsbH5m.js.map → theme-button-Z_xWXMaf.js.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.component-ByGua01V.js → theme.controls-BtaZcM7z.js} +367 -238
- package/dist/theme.controls-BtaZcM7z.js.map +1 -0
- package/dist/theme.controls-C_zAMJgA.cjs +67 -0
- package/dist/theme.controls-C_zAMJgA.cjs.map +1 -0
- package/dist/theme.js +13 -11
- package/dist/{timezone-BpDMR26D.js → timezone-CZ0gCI2P.js} +10 -9
- package/dist/{timezone-BpDMR26D.js.map → timezone-CZ0gCI2P.js.map} +1 -1
- package/dist/{timezone-Bw4EXBt7.cjs → timezone-DucGbWcE.cjs} +2 -2
- package/dist/{timezone-Bw4EXBt7.cjs.map → timezone-DucGbWcE.cjs.map} +1 -1
- package/dist/{tooltip-Dhs4HL3A.cjs → tooltip-BSWp7Mmz.cjs} +2 -2
- package/dist/{tooltip-Dhs4HL3A.cjs.map → tooltip-BSWp7Mmz.cjs.map} +1 -1
- package/dist/{tooltip-B1jynZOH.js → tooltip-BSppSqZM.js} +2 -2
- package/dist/{tooltip-B1jynZOH.js.map → tooltip-BSppSqZM.js.map} +1 -1
- package/dist/tooltip.cjs +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/{tree-D-ezei_U.cjs → tree-DL71EUih.cjs} +4 -4
- package/dist/{tree-D-ezei_U.cjs.map → tree-DL71EUih.cjs.map} +1 -1
- package/dist/{tree-BH1qCJ_U.js → tree-dEse6eMH.js} +3 -2
- package/dist/{tree-BH1qCJ_U.js.map → tree-dEse6eMH.js.map} +1 -1
- package/dist/tree.cjs +1 -1
- package/dist/tree.js +1 -1
- package/dist/typewriter-B1Au4MRO.cjs +9 -0
- package/dist/{typewriter-CtPh4Pyj.cjs.map → typewriter-B1Au4MRO.cjs.map} +1 -1
- package/dist/{typewriter-DQbpNPtY.js → typewriter-DBvUYzpl.js} +5 -4
- package/dist/{typewriter-DQbpNPtY.js.map → typewriter-DBvUYzpl.js.map} +1 -1
- package/dist/typewriter.cjs +1 -1
- package/dist/typewriter.js +1 -1
- package/dist/{typography-BrIaOYmC.cjs → typography-3gXQvLXN.cjs} +2 -2
- package/dist/{typography-BrIaOYmC.cjs.map → typography-3gXQvLXN.cjs.map} +1 -1
- package/dist/{typography-D71cmr0R.js → typography-iOtjgSkI.js} +2 -2
- package/dist/{typography-D71cmr0R.js.map → typography-iOtjgSkI.js.map} +1 -1
- package/dist/typography.cjs +1 -1
- package/dist/typography.js +1 -1
- package/package.json +1 -1
- package/types/mixins/baseElement.d.ts +2 -1
- package/types/src/boat/boat.d.ts +10 -5
- package/types/src/discovery/discovery.service.d.ts +17 -0
- package/types/src/discovery/index.d.ts +1 -0
- package/types/src/index.d.ts +1 -0
- package/types/src/navigation-bar/navigation-bar.d.ts +15 -1
- package/types/src/navigation-rail/navigation-rail.d.ts +13 -0
- package/types/src/theme/index.d.ts +1 -0
- package/types/src/theme/theme.controls.d.ts +27 -0
- package/types/src/theme/theme.service.d.ts +58 -2
- package/dist/area.component-Ch2Eaa4i.cjs +0 -12
- package/dist/avatar-CjjwZDsw.js.map +0 -1
- package/dist/avatar-DlhBTIc8.cjs +0 -303
- package/dist/avatar-DlhBTIc8.cjs.map +0 -1
- package/dist/boat-CUsJXaLf.js +0 -240
- package/dist/boat-CUsJXaLf.js.map +0 -1
- package/dist/boat-Dfx9-P8c.cjs +0 -83
- package/dist/boat-Dfx9-P8c.cjs.map +0 -1
- package/dist/context-object-BE1o2XB3.js.map +0 -1
- package/dist/context-object-DA9DM9QJ.cjs +0 -2
- package/dist/context-object-DA9DM9QJ.cjs.map +0 -1
- package/dist/date-range-inline-DNr7C5X-.cjs +0 -44
- package/dist/divider-CNxOc8ep.cjs +0 -2
- package/dist/form-DzDksPgv.cjs +0 -2
- package/dist/input-C2Vz-51i.cjs +0 -51
- package/dist/navigation-rail-6ONc-XE-.cjs.map +0 -1
- package/dist/navigation-rail-D-lK9oVd.js.map +0 -1
- package/dist/payment-card-form--v94EhJF.cjs +0 -74
- package/dist/selector-hook-DOsvFxG2.js +0 -364
- package/dist/selector-hook-DOsvFxG2.js.map +0 -1
- package/dist/selector-hook-DQ9zoDM4.cjs +0 -2
- package/dist/selector-hook-DQ9zoDM4.cjs.map +0 -1
- package/dist/tailwind.mixin-BjDGMGbj.js +0 -43
- package/dist/tailwind.mixin-BjDGMGbj.js.map +0 -1
- package/dist/tailwind.mixin-ClfV2_Nh.cjs +0 -2
- package/dist/tailwind.mixin-ClfV2_Nh.cjs.map +0 -1
- package/dist/textarea-qLA0vP78.cjs +0 -44
- package/dist/theme-button-D7fBEUGf.cjs +0 -9
- package/dist/theme.component-ByGua01V.js.map +0 -1
- package/dist/theme.component-CQ1trrZB.cjs +0 -3
- package/dist/theme.component-CQ1trrZB.cjs.map +0 -1
- package/dist/typewriter-CtPh4Pyj.cjs +0 -9
package/ai/theme.md
CHANGED
|
@@ -1,923 +1,352 @@
|
|
|
1
|
-
# Theme
|
|
1
|
+
# Theme Service
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Centralized theme management with reactive observables for color schemes, fullscreen mode, and Material Design 3 integration.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
The Schmancy theme system consists of two main parts:
|
|
8
|
-
1. **Theme Component** (`<schmancy-theme>`) - Visual theme configuration interface
|
|
9
|
-
2. **Theme Service API** (`themeService`) - Programmatic theme management and subscriptions
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
### Using the Theme Component
|
|
14
|
-
|
|
15
|
-
```html
|
|
16
|
-
<!-- Basic theme with auto color -->
|
|
17
|
-
<schmancy-theme>
|
|
18
|
-
<div class="my-app">
|
|
19
|
-
<!-- All children inherit theme -->
|
|
20
|
-
</div>
|
|
21
|
-
</schmancy-theme>
|
|
22
|
-
|
|
23
|
-
<!-- Custom color theme -->
|
|
24
|
-
<schmancy-theme color="#6750A4" scheme="light">
|
|
25
|
-
<schmancy-card>
|
|
26
|
-
<h2>Themed Content</h2>
|
|
27
|
-
</schmancy-card>
|
|
28
|
-
</schmancy-theme>
|
|
29
|
-
|
|
30
|
-
<!-- Root-level theme -->
|
|
31
|
-
<schmancy-theme color="#00695C" root>
|
|
32
|
-
<!-- Theme applies to entire document -->
|
|
33
|
-
</schmancy-theme>
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Using the Theme Service
|
|
5
|
+
## Import
|
|
37
6
|
|
|
38
7
|
```typescript
|
|
39
|
-
import {
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
// Get current theme
|
|
43
|
-
const theme = themeService.getCurrentTheme()
|
|
44
|
-
|
|
45
|
-
// Set theme mode
|
|
46
|
-
themeService.setMode('dark')
|
|
47
|
-
|
|
48
|
-
// Set primary color
|
|
49
|
-
themeService.setPrimaryColor('#6750A4')
|
|
50
|
-
|
|
51
|
-
// Subscribe to theme changes
|
|
52
|
-
themeService.theme$.subscribe(theme => {
|
|
53
|
-
console.log('Theme updated:', theme)
|
|
54
|
-
})
|
|
8
|
+
import { theme } from '@schmancy/theme'
|
|
9
|
+
// Alternative: schmancyTheme
|
|
55
10
|
```
|
|
56
11
|
|
|
57
|
-
##
|
|
58
|
-
|
|
59
|
-
| Property | Type | Default | Description |
|
|
60
|
-
|----------|------|---------|-------------|
|
|
61
|
-
| `color` | `string` | `random` | Source color for theme generation |
|
|
62
|
-
| `scheme` | `'dark' \| 'light' \| 'auto'` | `'auto'` | Color scheme mode |
|
|
63
|
-
| `root` | `boolean` | `false` | Apply theme to document root |
|
|
64
|
-
| `theme` | `Partial<TSchmancyTheme>` | `{}` | Custom theme overrides |
|
|
12
|
+
## Core Concepts
|
|
65
13
|
|
|
66
|
-
|
|
14
|
+
- **Scheme**: Color mode (`'dark'` | `'light'` | `'auto'`)
|
|
15
|
+
- **Resolved Scheme**: Actual theme after resolving `'auto'` based on system preferences
|
|
16
|
+
- **Color**: Primary theme color in hex format
|
|
17
|
+
- **Fullscreen**: Navigation visibility state
|
|
18
|
+
- **Theme Component**: Visual theme provider that registers with service
|
|
67
19
|
|
|
68
|
-
|
|
20
|
+
## Properties (Synchronous)
|
|
69
21
|
|
|
70
22
|
```typescript
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
## Examples
|
|
78
|
-
|
|
79
|
-
### App-Wide Theme
|
|
80
|
-
```html
|
|
81
|
-
<!-- In your app root -->
|
|
82
|
-
<schmancy-theme color="#1976D2" root>
|
|
83
|
-
<schmancy-app>
|
|
84
|
-
<!-- Entire app uses this theme -->
|
|
85
|
-
</schmancy-app>
|
|
86
|
-
</schmancy-theme>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Component-Level Theming
|
|
90
|
-
```html
|
|
91
|
-
<!-- Different sections with different themes -->
|
|
92
|
-
<div class="dashboard">
|
|
93
|
-
<schmancy-theme color="#00897B">
|
|
94
|
-
<section class="analytics">
|
|
95
|
-
<!-- Teal theme -->
|
|
96
|
-
</section>
|
|
97
|
-
</schmancy-theme>
|
|
98
|
-
|
|
99
|
-
<schmancy-theme color="#E53935">
|
|
100
|
-
<section class="alerts">
|
|
101
|
-
<!-- Red theme for alerts -->
|
|
102
|
-
</section>
|
|
103
|
-
</schmancy-theme>
|
|
104
|
-
</div>
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Dark Mode Support
|
|
108
|
-
```html
|
|
109
|
-
<!-- Automatic dark/light switching -->
|
|
110
|
-
<schmancy-theme scheme="auto">
|
|
111
|
-
<schmancy-surface>
|
|
112
|
-
<p>Adapts to system preferences</p>
|
|
113
|
-
</schmancy-surface>
|
|
114
|
-
</schmancy-theme>
|
|
115
|
-
|
|
116
|
-
<!-- Force dark mode -->
|
|
117
|
-
<schmancy-theme scheme="dark" color="#673AB7">
|
|
118
|
-
<schmancy-card>
|
|
119
|
-
<h3>Always Dark</h3>
|
|
120
|
-
</schmancy-card>
|
|
121
|
-
</schmancy-theme>
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Theme Overrides
|
|
125
|
-
```html
|
|
126
|
-
<schmancy-theme
|
|
127
|
-
color="#FF5722"
|
|
128
|
-
.theme="${{
|
|
129
|
-
sys: {
|
|
130
|
-
color: {
|
|
131
|
-
primary: {
|
|
132
|
-
default: '#FF5722',
|
|
133
|
-
onDefault: '#FFFFFF'
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}}"
|
|
138
|
-
>
|
|
139
|
-
<schmancy-button variant="filled">
|
|
140
|
-
Custom Themed Button
|
|
141
|
-
</schmancy-button>
|
|
142
|
-
</schmancy-theme>
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Generated CSS Properties
|
|
146
|
-
|
|
147
|
-
The theme generates a comprehensive set of CSS custom properties:
|
|
148
|
-
|
|
149
|
-
```css
|
|
150
|
-
/* Primary colors */
|
|
151
|
-
--schmancy-sys-color-primary-default
|
|
152
|
-
--schmancy-sys-color-primary-onDefault
|
|
153
|
-
--schmancy-sys-color-primary-container
|
|
154
|
-
--schmancy-sys-color-primary-onContainer
|
|
155
|
-
|
|
156
|
-
/* Secondary colors */
|
|
157
|
-
--schmancy-sys-color-secondary-default
|
|
158
|
-
--schmancy-sys-color-secondary-onDefault
|
|
159
|
-
--schmancy-sys-color-secondary-container
|
|
160
|
-
--schmancy-sys-color-secondary-onContainer
|
|
161
|
-
|
|
162
|
-
/* Tertiary colors */
|
|
163
|
-
--schmancy-sys-color-tertiary-default
|
|
164
|
-
--schmancy-sys-color-tertiary-onDefault
|
|
165
|
-
|
|
166
|
-
/* Surface colors */
|
|
167
|
-
--schmancy-sys-color-surface-default
|
|
168
|
-
--schmancy-sys-color-surface-on
|
|
169
|
-
--schmancy-sys-color-surface-container
|
|
170
|
-
--schmancy-sys-color-surface-containerHigh
|
|
171
|
-
--schmancy-sys-color-surface-containerHighest
|
|
172
|
-
|
|
173
|
-
/* And many more... */
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Auto Color Scheme Detection
|
|
177
|
-
|
|
178
|
-
```javascript
|
|
179
|
-
// Automatically detects system preference
|
|
180
|
-
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
181
|
-
|
|
182
|
-
// Reactive updates when system preference changes
|
|
183
|
-
scheme === 'auto' && mediaQuery.addEventListener('change', updateTheme);
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
## Random Color Generation
|
|
187
|
-
|
|
188
|
-
When no color is specified, generates a random color:
|
|
189
|
-
|
|
190
|
-
```javascript
|
|
191
|
-
generateRandomColor() {
|
|
192
|
-
const randomColor = Math.floor(Math.random() * 16777215).toString(16);
|
|
193
|
-
return '#' + randomColor.padStart(6, '0');
|
|
194
|
-
}
|
|
23
|
+
theme.scheme // 'dark' | 'light' | 'auto'
|
|
24
|
+
theme.color // '#6200ee'
|
|
25
|
+
theme.fullscreen // boolean
|
|
26
|
+
theme.themeComponent // SchmancyThemeComponent | null
|
|
27
|
+
theme.theme // Partial<TSchmancyTheme>
|
|
195
28
|
```
|
|
196
29
|
|
|
197
|
-
##
|
|
198
|
-
|
|
199
|
-
The theme component provides its theme via Lit Context:
|
|
200
|
-
|
|
201
|
-
```javascript
|
|
202
|
-
import { consume } from '@lit/context';
|
|
203
|
-
import { themeContext } from '@schmancy/index';
|
|
204
|
-
// Or specific import: import { themeContext } from '@schmancy/index'
|
|
205
|
-
// Or specific import: import { themeContext } from '@schmancy/theme';
|
|
206
|
-
|
|
207
|
-
// In child components
|
|
208
|
-
@consume({ context: themeContext })
|
|
209
|
-
theme: TSchmancyTheme;
|
|
210
|
-
```
|
|
30
|
+
## Observables
|
|
211
31
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
<div class="main-content">
|
|
218
|
-
<!-- Blue light theme -->
|
|
219
|
-
|
|
220
|
-
<schmancy-theme color="#F44336" scheme="dark">
|
|
221
|
-
<aside class="sidebar">
|
|
222
|
-
<!-- Red dark theme -->
|
|
223
|
-
</aside>
|
|
224
|
-
</schmancy-theme>
|
|
225
|
-
</div>
|
|
226
|
-
</schmancy-theme>
|
|
227
|
-
```
|
|
32
|
+
```typescript
|
|
33
|
+
// Scheme changes
|
|
34
|
+
theme.scheme$.subscribe(scheme => {
|
|
35
|
+
console.log(scheme) // 'dark' | 'light' | 'auto'
|
|
36
|
+
})
|
|
228
37
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
38
|
+
// Resolved scheme (auto → actual)
|
|
39
|
+
theme.resolvedScheme$.subscribe(scheme => {
|
|
40
|
+
console.log(scheme) // 'dark' | 'light' (never 'auto')
|
|
41
|
+
})
|
|
232
42
|
|
|
233
|
-
//
|
|
234
|
-
|
|
43
|
+
// Color changes
|
|
44
|
+
theme.color$.subscribe(color => {
|
|
45
|
+
console.log(color) // '#6200ee'
|
|
46
|
+
})
|
|
235
47
|
|
|
236
|
-
//
|
|
237
|
-
|
|
48
|
+
// Fullscreen state
|
|
49
|
+
theme.fullscreen$.subscribe(isFullscreen => {
|
|
50
|
+
console.log(isFullscreen) // true/false
|
|
51
|
+
})
|
|
238
52
|
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
error: {
|
|
244
|
-
default: '#FF0000'
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
};
|
|
53
|
+
// Theme configuration
|
|
54
|
+
theme.theme$.subscribe(themeConfig => {
|
|
55
|
+
console.log(themeConfig) // Material Design 3 theme object
|
|
56
|
+
})
|
|
249
57
|
```
|
|
250
58
|
|
|
251
|
-
##
|
|
252
|
-
|
|
253
|
-
The theme service provides programmatic control over the theme system with reactive observables for state management.
|
|
254
|
-
|
|
255
|
-
### Service Methods
|
|
256
|
-
|
|
257
|
-
#### `getCurrentTheme()`
|
|
258
|
-
Returns the current theme configuration.
|
|
59
|
+
## Methods
|
|
259
60
|
|
|
61
|
+
### `setScheme(scheme)`
|
|
62
|
+
Set color scheme.
|
|
260
63
|
```typescript
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
console.log(theme.isDark) // boolean
|
|
64
|
+
theme.setScheme('dark') // Force dark
|
|
65
|
+
theme.setScheme('light') // Force light
|
|
66
|
+
theme.setScheme('auto') // Follow system
|
|
265
67
|
```
|
|
266
68
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
69
|
+
### `toggleScheme()`
|
|
70
|
+
Toggle between light/dark modes.
|
|
270
71
|
```typescript
|
|
271
|
-
//
|
|
272
|
-
themeService.setMode('light')
|
|
273
|
-
|
|
274
|
-
// Force dark mode
|
|
275
|
-
themeService.setMode('dark')
|
|
276
|
-
|
|
277
|
-
// Auto mode (follows system preference)
|
|
278
|
-
themeService.setMode('auto')
|
|
72
|
+
theme.toggleScheme() // light → dark → light
|
|
279
73
|
```
|
|
280
74
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
75
|
+
### `setColor(color)`
|
|
76
|
+
Set primary color.
|
|
284
77
|
```typescript
|
|
285
|
-
|
|
78
|
+
theme.setColor('#6750A4')
|
|
286
79
|
```
|
|
287
80
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
81
|
+
### `isDarkMode()`
|
|
82
|
+
Check if currently in dark mode.
|
|
291
83
|
```typescript
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
primaryColor: '#00897B',
|
|
295
|
-
fontFamily: 'Roboto',
|
|
296
|
-
borderRadius: 'medium'
|
|
84
|
+
theme.isDarkMode().subscribe(isDark => {
|
|
85
|
+
console.log(isDark) // true/false
|
|
297
86
|
})
|
|
298
87
|
```
|
|
299
88
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
89
|
+
### `setFullscreen(value)`
|
|
90
|
+
Control fullscreen mode.
|
|
303
91
|
```typescript
|
|
304
|
-
|
|
92
|
+
theme.setFullscreen(true) // Hide navigation
|
|
93
|
+
theme.setFullscreen(false) // Show navigation
|
|
305
94
|
```
|
|
306
95
|
|
|
307
|
-
###
|
|
308
|
-
|
|
309
|
-
|
|
96
|
+
### `toggleFullscreen()`
|
|
97
|
+
Toggle fullscreen state.
|
|
98
|
+
```typescript
|
|
99
|
+
theme.toggleFullscreen()
|
|
100
|
+
```
|
|
310
101
|
|
|
311
|
-
|
|
102
|
+
### `next(values)`
|
|
103
|
+
Update multiple properties at once.
|
|
312
104
|
```typescript
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
console.log('Theme updated:', theme)
|
|
319
|
-
// theme.mode, theme.primaryColor, theme.isDark, etc.
|
|
320
|
-
})
|
|
105
|
+
theme.next({
|
|
106
|
+
fullscreen: true,
|
|
107
|
+
scheme: 'dark',
|
|
108
|
+
color: '#6750A4'
|
|
109
|
+
})
|
|
321
110
|
```
|
|
322
111
|
|
|
323
|
-
|
|
112
|
+
### `getCSSVariable(name)`
|
|
113
|
+
Get CSS variable value.
|
|
324
114
|
```typescript
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
.subscribe(mode => {
|
|
328
|
-
console.log('Mode changed to:', mode)
|
|
329
|
-
})
|
|
115
|
+
const primary = theme.getCSSVariable('color-primary')
|
|
116
|
+
// Returns computed value of --schmancy-color-primary
|
|
330
117
|
```
|
|
331
118
|
|
|
332
|
-
|
|
119
|
+
### `watchCSSVariable(name)`
|
|
120
|
+
Watch CSS variable changes.
|
|
333
121
|
```typescript
|
|
334
|
-
|
|
335
|
-
.
|
|
336
|
-
|
|
337
|
-
console.log('Primary color changed to:', color)
|
|
338
|
-
})
|
|
122
|
+
theme.watchCSSVariable('color-primary').subscribe(color => {
|
|
123
|
+
console.log('Primary changed:', color)
|
|
124
|
+
})
|
|
339
125
|
```
|
|
340
126
|
|
|
341
|
-
|
|
127
|
+
## Fullscreen Integration
|
|
342
128
|
|
|
343
|
-
|
|
129
|
+
Navigation components automatically respond to fullscreen:
|
|
344
130
|
|
|
345
131
|
```typescript
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
import { themeContext } from '@schmancy/index'
|
|
349
|
-
// Or specific import: import { themeContext } from '@schmancy/theme'
|
|
350
|
-
|
|
351
|
-
@customElement('my-component')
|
|
352
|
-
class MyComponent extends LitElement {
|
|
353
|
-
@select(themeContext) theme!: ThemeState
|
|
132
|
+
// Enter fullscreen (hides navigation)
|
|
133
|
+
theme.setFullscreen(true)
|
|
354
134
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
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()
|
|
363
142
|
```
|
|
364
143
|
|
|
365
|
-
|
|
144
|
+
## Component Usage
|
|
366
145
|
|
|
367
|
-
|
|
146
|
+
### Basic Theme Controls
|
|
368
147
|
```typescript
|
|
369
|
-
@customElement('theme-
|
|
370
|
-
export class
|
|
371
|
-
@state() private
|
|
148
|
+
@customElement('theme-controls')
|
|
149
|
+
export class ThemeControls extends $LitElement() {
|
|
150
|
+
@state() private currentScheme = theme.scheme
|
|
151
|
+
@state() private isFullscreen = theme.fullscreen
|
|
372
152
|
|
|
373
153
|
connectedCallback() {
|
|
374
154
|
super.connectedCallback()
|
|
375
155
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
.
|
|
379
|
-
|
|
380
|
-
})
|
|
381
|
-
}
|
|
156
|
+
theme.scheme$.pipe(
|
|
157
|
+
tap(scheme => this.currentScheme = scheme),
|
|
158
|
+
takeUntil(this.disconnecting)
|
|
159
|
+
).subscribe()
|
|
382
160
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
themeService.setMode(nextMode)
|
|
161
|
+
theme.fullscreen$.pipe(
|
|
162
|
+
tap(fullscreen => this.isFullscreen = fullscreen),
|
|
163
|
+
takeUntil(this.disconnecting)
|
|
164
|
+
).subscribe()
|
|
388
165
|
}
|
|
389
166
|
|
|
390
167
|
render() {
|
|
391
|
-
const icon = this.currentMode === 'light' ? 'light_mode' :
|
|
392
|
-
this.currentMode === 'dark' ? 'dark_mode' : 'brightness_auto'
|
|
393
|
-
|
|
394
168
|
return html`
|
|
395
|
-
<
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
169
|
+
<button @click=${() => theme.toggleScheme()}>
|
|
170
|
+
${this.currentScheme}
|
|
171
|
+
</button>
|
|
172
|
+
<button @click=${() => theme.toggleFullscreen()}>
|
|
173
|
+
${this.isFullscreen ? 'Exit' : 'Enter'} Fullscreen
|
|
174
|
+
</button>
|
|
399
175
|
`
|
|
400
176
|
}
|
|
401
177
|
}
|
|
402
178
|
```
|
|
403
179
|
|
|
404
|
-
|
|
180
|
+
### Theme-Aware Component
|
|
405
181
|
```typescript
|
|
406
|
-
@customElement('
|
|
407
|
-
export class
|
|
408
|
-
@state() private
|
|
409
|
-
|
|
410
|
-
private colors = [
|
|
411
|
-
{ name: 'Purple', value: '#6750A4' },
|
|
412
|
-
{ name: 'Blue', value: '#0061A4' },
|
|
413
|
-
{ name: 'Green', value: '#006E1C' },
|
|
414
|
-
{ name: 'Orange', value: '#D84315' },
|
|
415
|
-
{ name: 'Pink', value: '#C2185B' }
|
|
416
|
-
]
|
|
182
|
+
@customElement('theme-aware')
|
|
183
|
+
export class ThemeAware extends $LitElement() {
|
|
184
|
+
@state() private isDark = false
|
|
417
185
|
|
|
418
186
|
connectedCallback() {
|
|
419
187
|
super.connectedCallback()
|
|
420
188
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
.
|
|
424
|
-
|
|
425
|
-
})
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
private selectColor(color: string) {
|
|
429
|
-
themeService.setPrimaryColor(color)
|
|
189
|
+
theme.isDarkMode().pipe(
|
|
190
|
+
tap(isDark => this.isDark = isDark),
|
|
191
|
+
takeUntil(this.disconnecting)
|
|
192
|
+
).subscribe()
|
|
430
193
|
}
|
|
431
194
|
|
|
432
195
|
render() {
|
|
433
196
|
return html`
|
|
434
|
-
<div class
|
|
435
|
-
|
|
436
|
-
<button
|
|
437
|
-
@click=${() => this.selectColor(color.value)}
|
|
438
|
-
style="background-color: ${color.value}"
|
|
439
|
-
class="w-10 h-10 rounded-full border-2 transition-all ${
|
|
440
|
-
this.selectedColor === color.value ?
|
|
441
|
-
'border-white shadow-lg scale-110' :
|
|
442
|
-
'border-transparent'
|
|
443
|
-
}"
|
|
444
|
-
title=${color.name}
|
|
445
|
-
></button>
|
|
446
|
-
`)}
|
|
197
|
+
<div class=${this.isDark ? 'dark-theme' : 'light-theme'}>
|
|
198
|
+
Content adapts to theme
|
|
447
199
|
</div>
|
|
448
200
|
`
|
|
449
201
|
}
|
|
450
202
|
}
|
|
451
203
|
```
|
|
452
204
|
|
|
453
|
-
|
|
205
|
+
### Color Picker
|
|
454
206
|
```typescript
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
class ThemePersistence {
|
|
459
|
-
constructor() {
|
|
460
|
-
// Load saved theme on initialization
|
|
461
|
-
this.loadTheme()
|
|
462
|
-
|
|
463
|
-
// Save theme changes
|
|
464
|
-
themeService.theme$
|
|
465
|
-
.pipe(
|
|
466
|
-
debounceTime(500) // Debounce to avoid excessive saves
|
|
467
|
-
)
|
|
468
|
-
.subscribe(theme => {
|
|
469
|
-
this.saveTheme(theme)
|
|
470
|
-
})
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
private loadTheme() {
|
|
474
|
-
const saved = localStorage.getItem('user-theme')
|
|
475
|
-
if (saved) {
|
|
476
|
-
try {
|
|
477
|
-
const theme = JSON.parse(saved)
|
|
478
|
-
themeService.setTheme(theme)
|
|
479
|
-
} catch (e) {
|
|
480
|
-
console.error('Failed to load saved theme', e)
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
private saveTheme(theme: ThemeState) {
|
|
486
|
-
localStorage.setItem('user-theme', JSON.stringify({
|
|
487
|
-
mode: theme.mode,
|
|
488
|
-
primaryColor: theme.primaryColor
|
|
489
|
-
}))
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// Initialize once in your app
|
|
494
|
-
new ThemePersistence()
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
#### Responding to System Preferences
|
|
498
|
-
```typescript
|
|
499
|
-
@customElement('system-aware')
|
|
500
|
-
export class SystemAware extends LitElement {
|
|
501
|
-
@state() private isDark = false
|
|
502
|
-
@state() private isAuto = false
|
|
503
|
-
|
|
504
|
-
connectedCallback() {
|
|
505
|
-
super.connectedCallback()
|
|
506
|
-
|
|
507
|
-
// Subscribe to theme changes
|
|
508
|
-
themeService.theme$
|
|
509
|
-
.pipe(takeUntil(this.disconnecting))
|
|
510
|
-
.subscribe(theme => {
|
|
511
|
-
this.isAuto = theme.mode === 'auto'
|
|
512
|
-
this.isDark = theme.isDark
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
// Listen to system preference changes
|
|
516
|
-
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
|
517
|
-
mediaQuery.addEventListener('change', (e) => {
|
|
518
|
-
if (this.isAuto) {
|
|
519
|
-
this.isDark = e.matches
|
|
520
|
-
}
|
|
521
|
-
})
|
|
522
|
-
}
|
|
207
|
+
@customElement('color-picker')
|
|
208
|
+
export class ColorPicker extends $LitElement() {
|
|
209
|
+
private colors = ['#6750A4', '#0061A4', '#006E1C']
|
|
523
210
|
|
|
524
211
|
render() {
|
|
525
212
|
return html`
|
|
526
|
-
|
|
527
|
-
<
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
</div>
|
|
213
|
+
${this.colors.map(color => html`
|
|
214
|
+
<button
|
|
215
|
+
style="background: ${color}"
|
|
216
|
+
@click=${() => theme.setColor(color)}
|
|
217
|
+
></button>
|
|
218
|
+
`)}
|
|
533
219
|
`
|
|
534
220
|
}
|
|
535
221
|
}
|
|
536
222
|
```
|
|
537
223
|
|
|
538
|
-
##
|
|
224
|
+
## System Preference Detection
|
|
539
225
|
|
|
540
|
-
|
|
541
|
-
interface ThemeConfig {
|
|
542
|
-
mode: 'light' | 'dark' | 'auto'
|
|
543
|
-
primaryColor: string
|
|
544
|
-
fontFamily?: string
|
|
545
|
-
borderRadius?: 'none' | 'small' | 'medium' | 'large' | 'full'
|
|
546
|
-
contrast?: 'standard' | 'medium' | 'high'
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
interface ThemeState extends ThemeConfig {
|
|
550
|
-
isDark: boolean
|
|
551
|
-
isAuto: boolean
|
|
552
|
-
systemPreference: 'light' | 'dark'
|
|
553
|
-
theme: TSchmancyTheme // Full Material Design 3 theme object
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
interface ThemeService {
|
|
557
|
-
// Observables
|
|
558
|
-
theme$: Observable<ThemeState>
|
|
559
|
-
mode$: Observable<'light' | 'dark' | 'auto'>
|
|
560
|
-
primaryColor$: Observable<string>
|
|
561
|
-
|
|
562
|
-
// Methods
|
|
563
|
-
getCurrentTheme(): ThemeState
|
|
564
|
-
setMode(mode: 'light' | 'dark' | 'auto'): void
|
|
565
|
-
setPrimaryColor(color: string): void
|
|
566
|
-
setTheme(theme: ThemeConfig): void
|
|
567
|
-
reset(): void
|
|
568
|
-
}
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
## Best Practices
|
|
572
|
-
|
|
573
|
-
1. **Root Theme**: Use one root theme for consistency
|
|
574
|
-
2. **Color Choice**: Pick colors with good contrast ratios
|
|
575
|
-
3. **Scheme Handling**: Respect user preferences with 'auto'
|
|
576
|
-
4. **Performance**: Limit nested themes, debounce theme changes
|
|
577
|
-
5. **Accessibility**: Test themes with contrast checkers
|
|
578
|
-
6. **Persistence**: Save user preferences to localStorage
|
|
579
|
-
7. **Cleanup**: Always use `takeUntil(this.disconnecting)` in components
|
|
580
|
-
8. **Type Safety**: Use provided TypeScript interfaces
|
|
581
|
-
|
|
582
|
-
## CSS Variables Reference
|
|
583
|
-
|
|
584
|
-
### Using Theme Variables in Styles
|
|
226
|
+
Auto mode follows system preferences:
|
|
585
227
|
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
.
|
|
589
|
-
/* Backgrounds */
|
|
590
|
-
background: var(--schmancy-sys-color-surface-default);
|
|
591
|
-
|
|
592
|
-
/* Text colors */
|
|
593
|
-
color: var(--schmancy-sys-color-surface-on);
|
|
594
|
-
|
|
595
|
-
/* Borders */
|
|
596
|
-
border: 1px solid var(--schmancy-sys-color-outline);
|
|
597
|
-
|
|
598
|
-
/* Elevation/shadows */
|
|
599
|
-
box-shadow: var(--schmancy-sys-elevation-1);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
/* Semantic color usage */
|
|
603
|
-
.primary-action {
|
|
604
|
-
background: var(--schmancy-sys-color-primary-default);
|
|
605
|
-
color: var(--schmancy-sys-color-primary-onDefault);
|
|
606
|
-
}
|
|
228
|
+
```typescript
|
|
229
|
+
// Internally handles MediaQueryList
|
|
230
|
+
theme.setScheme('auto')
|
|
607
231
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
232
|
+
// Resolved scheme updates automatically
|
|
233
|
+
theme.resolvedScheme$.subscribe(scheme => {
|
|
234
|
+
// 'dark' or 'light' based on system
|
|
235
|
+
})
|
|
612
236
|
```
|
|
613
237
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
#### Primary Colors
|
|
617
|
-
- `--schmancy-sys-color-primary-default`
|
|
618
|
-
- `--schmancy-sys-color-primary-onDefault`
|
|
619
|
-
- `--schmancy-sys-color-primary-container`
|
|
620
|
-
- `--schmancy-sys-color-primary-onContainer`
|
|
621
|
-
|
|
622
|
-
#### Secondary Colors
|
|
623
|
-
- `--schmancy-sys-color-secondary-default`
|
|
624
|
-
- `--schmancy-sys-color-secondary-onDefault`
|
|
625
|
-
- `--schmancy-sys-color-secondary-container`
|
|
626
|
-
- `--schmancy-sys-color-secondary-onContainer`
|
|
627
|
-
|
|
628
|
-
#### Tertiary Colors
|
|
629
|
-
- `--schmancy-sys-color-tertiary-default`
|
|
630
|
-
- `--schmancy-sys-color-tertiary-onDefault`
|
|
631
|
-
- `--schmancy-sys-color-tertiary-container`
|
|
632
|
-
- `--schmancy-sys-color-tertiary-onContainer`
|
|
633
|
-
|
|
634
|
-
#### Error Colors
|
|
635
|
-
- `--schmancy-sys-color-error-default`
|
|
636
|
-
- `--schmancy-sys-color-error-onDefault`
|
|
637
|
-
- `--schmancy-sys-color-error-container`
|
|
638
|
-
- `--schmancy-sys-color-error-onContainer`
|
|
639
|
-
|
|
640
|
-
#### Surface Colors
|
|
641
|
-
- `--schmancy-sys-color-surface-default`
|
|
642
|
-
- `--schmancy-sys-color-surface-on`
|
|
643
|
-
- `--schmancy-sys-color-surface-onVariant`
|
|
644
|
-
- `--schmancy-sys-color-surface-container`
|
|
645
|
-
- `--schmancy-sys-color-surface-containerLow`
|
|
646
|
-
- `--schmancy-sys-color-surface-containerHigh`
|
|
647
|
-
- `--schmancy-sys-color-surface-containerHighest`
|
|
648
|
-
|
|
649
|
-
#### Background & Outline
|
|
650
|
-
- `--schmancy-sys-color-background-default`
|
|
651
|
-
- `--schmancy-sys-color-background-on`
|
|
652
|
-
- `--schmancy-sys-color-outline-default`
|
|
653
|
-
- `--schmancy-sys-color-outline-variant`
|
|
654
|
-
|
|
655
|
-
## Migration Guide
|
|
656
|
-
|
|
657
|
-
### From Hardcoded Colors
|
|
658
|
-
|
|
659
|
-
```css
|
|
660
|
-
/* Before - Hardcoded colors */
|
|
661
|
-
.card {
|
|
662
|
-
background: #ffffff;
|
|
663
|
-
color: #000000;
|
|
664
|
-
border: 1px solid #e0e0e0;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
/* After - Theme-aware */
|
|
668
|
-
.card {
|
|
669
|
-
background: var(--schmancy-sys-color-surface-default);
|
|
670
|
-
color: var(--schmancy-sys-color-surface-on);
|
|
671
|
-
border: 1px solid var(--schmancy-sys-color-outline-variant);
|
|
672
|
-
}
|
|
673
|
-
```
|
|
238
|
+
## Theme Discovery
|
|
674
239
|
|
|
675
|
-
|
|
240
|
+
Service automatically discovers theme components:
|
|
676
241
|
|
|
677
242
|
```typescript
|
|
678
|
-
//
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
color: theme.colors.text
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
// After - CSS with variables
|
|
687
|
-
static styles = css`
|
|
688
|
-
.card {
|
|
689
|
-
background: var(--schmancy-sys-color-surface-default);
|
|
690
|
-
color: var(--schmancy-sys-color-surface-on);
|
|
243
|
+
// Manual discovery (rarely needed)
|
|
244
|
+
theme.discoverTheme().subscribe(component => {
|
|
245
|
+
if (component) {
|
|
246
|
+
console.log('Found theme component')
|
|
691
247
|
}
|
|
692
|
-
|
|
248
|
+
})
|
|
693
249
|
```
|
|
694
250
|
|
|
695
|
-
|
|
251
|
+
## CSS Variables
|
|
252
|
+
|
|
253
|
+
Access Material Design 3 variables:
|
|
696
254
|
|
|
697
255
|
```typescript
|
|
698
|
-
//
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
render() {
|
|
702
|
-
return html`
|
|
703
|
-
<div class=${this.isDark ? 'dark-theme' : 'light-theme'}>
|
|
704
|
-
<!-- content -->
|
|
705
|
-
</div>
|
|
706
|
-
`
|
|
707
|
-
}
|
|
256
|
+
// Get current value
|
|
257
|
+
const surface = theme.getCSSVariable('color-surface')
|
|
708
258
|
|
|
709
|
-
//
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
<!-- content automatically themed -->
|
|
715
|
-
</div>
|
|
716
|
-
`
|
|
717
|
-
}
|
|
259
|
+
// Watch for changes
|
|
260
|
+
theme.watchCSSVariable('color-primary').pipe(
|
|
261
|
+
tap(color => updateUI(color)),
|
|
262
|
+
takeUntil(this.disconnecting)
|
|
263
|
+
).subscribe()
|
|
718
264
|
```
|
|
719
265
|
|
|
720
|
-
|
|
266
|
+
Common variables:
|
|
267
|
+
- `color-primary`
|
|
268
|
+
- `color-surface`
|
|
269
|
+
- `color-error`
|
|
270
|
+
- `elevation-1` through `elevation-5`
|
|
721
271
|
|
|
722
|
-
|
|
272
|
+
## Events
|
|
723
273
|
|
|
274
|
+
### Fullscreen Event
|
|
724
275
|
```typescript
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
static styles = css`
|
|
730
|
-
:host {
|
|
731
|
-
display: block;
|
|
732
|
-
background: var(--schmancy-sys-color-surface-container);
|
|
733
|
-
color: var(--schmancy-sys-color-surface-on);
|
|
734
|
-
border-radius: var(--schmancy-sys-shape-corner-medium);
|
|
735
|
-
padding: 16px;
|
|
736
|
-
transition: all 200ms ease-in-out;
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
:host([elevated]) {
|
|
740
|
-
box-shadow: var(--schmancy-sys-elevation-2);
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
.header {
|
|
744
|
-
color: var(--schmancy-sys-color-primary-default);
|
|
745
|
-
font-size: var(--schmancy-sys-typescale-headline-small-size);
|
|
746
|
-
}
|
|
747
|
-
`
|
|
748
|
-
|
|
749
|
-
render() {
|
|
750
|
-
return html`
|
|
751
|
-
<div class="header">
|
|
752
|
-
<slot name="header"></slot>
|
|
753
|
-
</div>
|
|
754
|
-
<slot></slot>
|
|
755
|
-
`
|
|
756
|
-
}
|
|
757
|
-
}
|
|
276
|
+
window.addEventListener('fullscreen', (e: CustomEvent) => {
|
|
277
|
+
const isFullscreen = e.detail
|
|
278
|
+
// Hide/show UI elements
|
|
279
|
+
})
|
|
758
280
|
```
|
|
759
281
|
|
|
760
|
-
|
|
282
|
+
## State Management Pattern
|
|
761
283
|
|
|
762
284
|
```typescript
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
vibrant: {
|
|
773
|
-
mode: 'auto' as const,
|
|
774
|
-
primaryColor: '#FF6B6B',
|
|
775
|
-
fontFamily: 'Poppins, sans-serif',
|
|
776
|
-
borderRadius: 'large'
|
|
777
|
-
},
|
|
778
|
-
|
|
779
|
-
minimal: {
|
|
780
|
-
mode: 'auto' as const,
|
|
781
|
-
primaryColor: '#2C3E50',
|
|
782
|
-
fontFamily: 'system-ui',
|
|
783
|
-
borderRadius: 'none'
|
|
784
|
-
},
|
|
785
|
-
|
|
786
|
-
accessibility: {
|
|
787
|
-
mode: 'light' as const,
|
|
788
|
-
primaryColor: '#0055AA',
|
|
789
|
-
contrast: 'high',
|
|
790
|
-
fontFamily: 'Arial, sans-serif',
|
|
791
|
-
borderRadius: 'medium'
|
|
792
|
-
}
|
|
793
|
-
}
|
|
285
|
+
// All state changes through pipelines
|
|
286
|
+
of(newColor).pipe(
|
|
287
|
+
tap(() => theme.setColor(newColor)),
|
|
288
|
+
switchMap(() => theme.color$),
|
|
289
|
+
tap(color => console.log('Color updated:', color)),
|
|
290
|
+
takeUntil(this.disconnecting)
|
|
291
|
+
).subscribe()
|
|
292
|
+
```
|
|
794
293
|
|
|
795
|
-
|
|
796
|
-
const preset = ThemePresets.presets[presetName]
|
|
797
|
-
themeService.setTheme(preset)
|
|
798
|
-
}
|
|
799
|
-
}
|
|
294
|
+
## Best Practices
|
|
800
295
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
296
|
+
1. **Always use observables** for reactive updates
|
|
297
|
+
2. **Call `super.connectedCallback()`** when subscribing
|
|
298
|
+
3. **Use `takeUntil(this.disconnecting)`** for cleanup
|
|
299
|
+
4. **Prefer `resolvedScheme$`** over `scheme$` for UI logic
|
|
300
|
+
5. **Use `next()` method** for batch updates
|
|
301
|
+
6. **Let navigation components** handle fullscreen automatically
|
|
804
302
|
|
|
805
|
-
|
|
303
|
+
## Common Patterns
|
|
806
304
|
|
|
305
|
+
### Persist User Preference
|
|
807
306
|
```typescript
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
},
|
|
814
|
-
partner: {
|
|
815
|
-
primaryColor: '#00897B',
|
|
816
|
-
logo: '/assets/partner-logo.svg'
|
|
817
|
-
}
|
|
818
|
-
}
|
|
307
|
+
theme.scheme$.pipe(
|
|
308
|
+
skip(1), // Skip initial value
|
|
309
|
+
tap(scheme => localStorage.setItem('theme-scheme', scheme)),
|
|
310
|
+
takeUntil(this.disconnecting)
|
|
311
|
+
).subscribe()
|
|
819
312
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
// Update logo and other brand assets
|
|
824
|
-
this.updateBrandAssets(brand)
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
private updateBrandAssets(brand: any) {
|
|
828
|
-
// Update logos, fonts, etc.
|
|
829
|
-
}
|
|
830
|
-
}
|
|
313
|
+
// Restore on load
|
|
314
|
+
const saved = localStorage.getItem('theme-scheme')
|
|
315
|
+
if (saved) theme.setScheme(saved as any)
|
|
831
316
|
```
|
|
832
317
|
|
|
833
|
-
|
|
834
|
-
|
|
318
|
+
### Theme Toggle Button
|
|
835
319
|
```typescript
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
it('renders correctly in light mode', async () => {
|
|
843
|
-
themeService.setMode('light')
|
|
844
|
-
const el = await fixture(html`<themed-component></themed-component>`)
|
|
845
|
-
// Test light mode rendering
|
|
846
|
-
})
|
|
847
|
-
|
|
848
|
-
it('renders correctly in dark mode', async () => {
|
|
849
|
-
themeService.setMode('dark')
|
|
850
|
-
const el = await fixture(html`<themed-component></themed-component>`)
|
|
851
|
-
// Test dark mode rendering
|
|
852
|
-
})
|
|
853
|
-
|
|
854
|
-
it('responds to theme changes', async () => {
|
|
855
|
-
const el = await fixture(html`<themed-component></themed-component>`)
|
|
856
|
-
|
|
857
|
-
themeService.setPrimaryColor('#FF5722')
|
|
858
|
-
await el.updateComplete
|
|
859
|
-
|
|
860
|
-
// Verify component updated with new theme
|
|
861
|
-
})
|
|
862
|
-
})
|
|
320
|
+
html`
|
|
321
|
+
<button @click=${() => theme.toggleScheme()}>
|
|
322
|
+
${theme.scheme === 'dark' ? '🌙' : '☀️'}
|
|
323
|
+
</button>
|
|
324
|
+
`
|
|
863
325
|
```
|
|
864
326
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
### Debouncing Theme Changes
|
|
868
|
-
|
|
327
|
+
### Fullscreen Video Player
|
|
869
328
|
```typescript
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
distinctUntilChanged((a, b) =>
|
|
876
|
-
a.primaryColor === b.primaryColor &&
|
|
877
|
-
a.mode === b.mode
|
|
878
|
-
),
|
|
879
|
-
takeUntil(this.disconnecting)
|
|
880
|
-
)
|
|
881
|
-
.subscribe(theme => {
|
|
882
|
-
// Handle theme changes
|
|
883
|
-
})
|
|
884
|
-
```
|
|
885
|
-
|
|
886
|
-
### Lazy Loading Theme Components
|
|
329
|
+
class VideoPlayer extends $LitElement() {
|
|
330
|
+
private enterFullscreen() {
|
|
331
|
+
theme.setFullscreen(true)
|
|
332
|
+
this.video.requestFullscreen()
|
|
333
|
+
}
|
|
887
334
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
const settings = new ThemeSettings()
|
|
893
|
-
document.body.appendChild(settings)
|
|
335
|
+
private exitFullscreen() {
|
|
336
|
+
theme.setFullscreen(false)
|
|
337
|
+
document.exitFullscreen()
|
|
338
|
+
}
|
|
894
339
|
}
|
|
895
340
|
```
|
|
896
341
|
|
|
897
|
-
##
|
|
898
|
-
|
|
899
|
-
### Common Issues
|
|
342
|
+
## Integration with Theme Component
|
|
900
343
|
|
|
901
|
-
|
|
902
|
-
2. **CSS variables undefined**: Check that schmancy-theme is imported before use
|
|
903
|
-
3. **Dark mode not working**: Verify `scheme="auto"` and system preferences
|
|
904
|
-
4. **Performance issues**: Use debouncing and avoid excessive nesting
|
|
905
|
-
5. **Colors not updating**: Ensure using CSS variables, not hardcoded values
|
|
344
|
+
The service works with `<schmancy-theme>` component:
|
|
906
345
|
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
-
|
|
911
|
-
|
|
912
|
-
- [Card](./card.md) - Themed content
|
|
913
|
-
|
|
914
|
-
## Use Cases
|
|
346
|
+
```html
|
|
347
|
+
<schmancy-theme color="#6750A4" scheme="auto">
|
|
348
|
+
<!-- Content -->
|
|
349
|
+
</schmancy-theme>
|
|
350
|
+
```
|
|
915
351
|
|
|
916
|
-
|
|
917
|
-
2. **White-Label**: Dynamic branding for multiple clients
|
|
918
|
-
3. **User Preferences**: Personalized themes saved per user
|
|
919
|
-
4. **Section Theming**: Different themes for app sections
|
|
920
|
-
5. **A/B Testing**: Theme variations for testing
|
|
921
|
-
6. **Accessibility**: High contrast modes for better readability
|
|
922
|
-
7. **Dark Mode**: Automatic or manual dark mode support
|
|
923
|
-
8. **Brand Compliance**: Enforce brand colors across components
|
|
352
|
+
Component automatically registers with service and syncs state bidirectionally.
|