@material/web 2.4.2-nightly.2fe7e22.0 → 2.4.2-nightly.3758f46.0

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.
Files changed (198) hide show
  1. package/button/internal/button.d.ts +0 -4
  2. package/button/internal/button.js.map +1 -1
  3. package/checkbox/internal/checkbox.d.ts +2 -2
  4. package/checkbox/internal/checkbox.js.map +1 -1
  5. package/chips/internal/chip.d.ts +2 -0
  6. package/icon/internal/icon.d.ts +1 -1
  7. package/icon/internal/icon.js +1 -1
  8. package/icon/internal/icon.js.map +1 -1
  9. package/iconbutton/internal/icon-button.d.ts +0 -4
  10. package/iconbutton/internal/icon-button.js.map +1 -1
  11. package/internal/aria/aria.d.ts +1 -1
  12. package/internal/events/dispatch-hooks.js +31 -35
  13. package/internal/events/dispatch-hooks.js.map +1 -1
  14. package/labs/behaviors/form-associated.d.ts +0 -22
  15. package/labs/behaviors/form-associated.js +0 -11
  16. package/labs/behaviors/form-associated.js.map +1 -1
  17. package/labs/gb/components/button/_button-tokens.scss +30 -30
  18. package/labs/gb/components/button/button.css +1 -1
  19. package/labs/gb/components/button/button.css.map +1 -1
  20. package/labs/gb/components/button/button.cssresult.js +1 -1
  21. package/labs/gb/components/button/button.cssresult.js.map +1 -1
  22. package/labs/gb/components/button/button.d.ts +1 -16
  23. package/labs/gb/components/button/button.js +10 -33
  24. package/labs/gb/components/button/button.js.map +1 -1
  25. package/labs/gb/components/button/button.scss +25 -25
  26. package/labs/gb/components/button/md-button.d.ts +1 -1
  27. package/labs/gb/components/button/md-button.js +9 -9
  28. package/labs/gb/components/button/md-button.js.map +1 -1
  29. package/labs/gb/components/card/card.d.ts +1 -11
  30. package/labs/gb/components/card/card.js +6 -13
  31. package/labs/gb/components/card/card.js.map +1 -1
  32. package/labs/gb/components/card/md-card.js +6 -6
  33. package/labs/gb/components/card/md-card.js.map +1 -1
  34. package/labs/gb/components/checkbox/checkbox.css +1 -1
  35. package/labs/gb/components/checkbox/checkbox.css.map +1 -1
  36. package/labs/gb/components/checkbox/checkbox.cssresult.js +1 -1
  37. package/labs/gb/components/checkbox/checkbox.cssresult.js.map +1 -1
  38. package/labs/gb/components/checkbox/checkbox.d.ts +1 -16
  39. package/labs/gb/components/checkbox/checkbox.js +8 -31
  40. package/labs/gb/components/checkbox/checkbox.js.map +1 -1
  41. package/labs/gb/components/checkbox/checkbox.scss +13 -13
  42. package/labs/gb/components/checkbox/md-checkbox.d.ts +4 -4
  43. package/labs/gb/components/checkbox/md-checkbox.js +10 -10
  44. package/labs/gb/components/checkbox/md-checkbox.js.map +1 -1
  45. package/labs/gb/components/divider/divider.d.ts +1 -11
  46. package/labs/gb/components/divider/divider.js +4 -11
  47. package/labs/gb/components/divider/divider.js.map +1 -1
  48. package/labs/gb/components/fab/fab.d.ts +1 -16
  49. package/labs/gb/components/fab/fab.js +8 -31
  50. package/labs/gb/components/fab/fab.js.map +1 -1
  51. package/labs/gb/components/fab/md-fab.js +4 -4
  52. package/labs/gb/components/fab/md-fab.js.map +1 -1
  53. package/labs/gb/components/focus/focus-ring.js +1 -1
  54. package/labs/gb/components/focus/focus-ring.js.map +1 -1
  55. package/labs/gb/components/iconbutton/_icon-button-tokens.scss +202 -0
  56. package/labs/gb/components/iconbutton/icon-button.css +4 -0
  57. package/labs/gb/components/iconbutton/icon-button.css.map +1 -0
  58. package/labs/gb/components/iconbutton/icon-button.cssresult.d.ts +3 -0
  59. package/labs/gb/components/iconbutton/icon-button.cssresult.js +14 -0
  60. package/labs/gb/components/iconbutton/icon-button.cssresult.js.map +1 -0
  61. package/labs/gb/components/iconbutton/icon-button.d.ts +97 -0
  62. package/labs/gb/components/iconbutton/icon-button.js +122 -0
  63. package/labs/gb/components/iconbutton/icon-button.js.map +1 -0
  64. package/labs/gb/components/iconbutton/icon-button.scss +153 -0
  65. package/labs/gb/components/iconbutton/md-icon-button.d.ts +73 -0
  66. package/labs/gb/components/iconbutton/md-icon-button.js +176 -0
  67. package/labs/gb/components/iconbutton/md-icon-button.js.map +1 -0
  68. package/labs/gb/components/list/_list-tokens.scss +102 -0
  69. package/labs/gb/components/list/list.css +4 -0
  70. package/labs/gb/components/list/list.css.map +1 -0
  71. package/labs/gb/components/list/list.cssresult.d.ts +3 -0
  72. package/labs/gb/components/list/list.cssresult.js +14 -0
  73. package/labs/gb/components/list/list.cssresult.js.map +1 -0
  74. package/labs/gb/components/list/list.d.ts +103 -0
  75. package/labs/gb/components/list/list.js +109 -0
  76. package/labs/gb/components/list/list.js.map +1 -0
  77. package/labs/gb/components/list/list.scss +212 -0
  78. package/labs/gb/components/list/md-list-item.d.ts +44 -0
  79. package/labs/gb/components/list/md-list-item.js +122 -0
  80. package/labs/gb/components/list/md-list-item.js.map +1 -0
  81. package/labs/gb/components/list/md-list.d.ts +26 -0
  82. package/labs/gb/components/list/md-list.js +51 -0
  83. package/labs/gb/components/list/md-list.js.map +1 -0
  84. package/labs/gb/components/menu/_menu-tokens.scss +128 -0
  85. package/labs/gb/components/menu/md-menu-group.d.ts +26 -0
  86. package/labs/gb/components/menu/md-menu-group.js +65 -0
  87. package/labs/gb/components/menu/md-menu-group.js.map +1 -0
  88. package/labs/gb/components/menu/md-menu-item.d.ts +30 -0
  89. package/labs/gb/components/menu/md-menu-item.js +165 -0
  90. package/labs/gb/components/menu/md-menu-item.js.map +1 -0
  91. package/labs/gb/components/menu/md-menu.d.ts +28 -0
  92. package/labs/gb/components/menu/md-menu.js +141 -0
  93. package/labs/gb/components/menu/md-menu.js.map +1 -0
  94. package/labs/gb/components/menu/menu.css +4 -0
  95. package/labs/gb/components/menu/menu.css.map +1 -0
  96. package/labs/gb/components/menu/menu.cssresult.d.ts +3 -0
  97. package/labs/gb/components/menu/menu.cssresult.js +14 -0
  98. package/labs/gb/components/menu/menu.cssresult.js.map +1 -0
  99. package/labs/gb/components/menu/menu.d.ts +117 -0
  100. package/labs/gb/components/menu/menu.js +107 -0
  101. package/labs/gb/components/menu/menu.js.map +1 -0
  102. package/labs/gb/components/menu/menu.scss +171 -0
  103. package/labs/gb/components/radio/md-radio.d.ts +4 -4
  104. package/labs/gb/components/radio/md-radio.js +11 -11
  105. package/labs/gb/components/radio/md-radio.js.map +1 -1
  106. package/labs/gb/components/radio/radio.css +1 -1
  107. package/labs/gb/components/radio/radio.css.map +1 -1
  108. package/labs/gb/components/radio/radio.cssresult.js +1 -1
  109. package/labs/gb/components/radio/radio.cssresult.js.map +1 -1
  110. package/labs/gb/components/radio/radio.d.ts +1 -14
  111. package/labs/gb/components/radio/radio.js +8 -23
  112. package/labs/gb/components/radio/radio.js.map +1 -1
  113. package/labs/gb/components/radio/radio.scss +4 -5
  114. package/labs/gb/components/ripple/ripple.d.ts +1 -10
  115. package/labs/gb/components/ripple/ripple.js +28 -32
  116. package/labs/gb/components/ripple/ripple.js.map +1 -1
  117. package/labs/gb/components/shared/directives.d.ts +93 -0
  118. package/labs/gb/components/shared/directives.js +111 -0
  119. package/labs/gb/components/shared/directives.js.map +1 -0
  120. package/labs/gb/components/shared/has-slotted.d.ts +10 -0
  121. package/labs/gb/components/shared/has-slotted.js +19 -0
  122. package/labs/gb/components/shared/has-slotted.js.map +1 -0
  123. package/labs/gb/components/shared/pseudo-classes.d.ts +7 -0
  124. package/labs/gb/components/shared/pseudo-classes.js +9 -0
  125. package/labs/gb/components/shared/pseudo-classes.js.map +1 -1
  126. package/labs/gb/components/splitbutton/_split-button-tokens.scss +135 -0
  127. package/labs/gb/components/splitbutton/md-split-button.d.ts +26 -0
  128. package/labs/gb/components/splitbutton/md-split-button.js +119 -0
  129. package/labs/gb/components/splitbutton/md-split-button.js.map +1 -0
  130. package/labs/gb/components/splitbutton/split-button.css +4 -0
  131. package/labs/gb/components/splitbutton/split-button.css.map +1 -0
  132. package/labs/gb/components/splitbutton/split-button.cssresult.d.ts +3 -0
  133. package/labs/gb/components/splitbutton/split-button.cssresult.js +14 -0
  134. package/labs/gb/components/splitbutton/split-button.cssresult.js.map +1 -0
  135. package/labs/gb/components/splitbutton/split-button.d.ts +47 -0
  136. package/labs/gb/components/splitbutton/split-button.js +46 -0
  137. package/labs/gb/components/splitbutton/split-button.js.map +1 -0
  138. package/labs/gb/components/splitbutton/split-button.scss +164 -0
  139. package/labs/gb/components/switch/_switch-tokens.scss +56 -0
  140. package/labs/gb/components/switch/md-switch.d.ts +66 -0
  141. package/labs/gb/components/switch/md-switch.js +162 -0
  142. package/labs/gb/components/switch/md-switch.js.map +1 -0
  143. package/labs/gb/components/switch/switch.css +4 -0
  144. package/labs/gb/components/switch/switch.css.map +1 -0
  145. package/labs/gb/components/switch/switch.cssresult.d.ts +3 -0
  146. package/labs/gb/components/switch/switch.cssresult.js +14 -0
  147. package/labs/gb/components/switch/switch.cssresult.js.map +1 -0
  148. package/labs/gb/components/switch/switch.d.ts +54 -0
  149. package/labs/gb/components/switch/switch.js +85 -0
  150. package/labs/gb/components/switch/switch.js.map +1 -0
  151. package/labs/gb/components/switch/switch.scss +109 -0
  152. package/labs/gb/styles/icon/md-icon.css +1 -1
  153. package/labs/gb/styles/icon/md-icon.css.map +1 -1
  154. package/labs/gb/styles/icon/md-icon.cssresult.js +1 -1
  155. package/labs/gb/styles/icon/md-icon.cssresult.js.map +1 -1
  156. package/labs/gb/styles/icon/md-icon.d.ts +20 -0
  157. package/labs/gb/styles/icon/md-icon.js +24 -0
  158. package/labs/gb/styles/icon/md-icon.js.map +1 -0
  159. package/labs/gb/styles/icon/md-icon.scss +2 -1
  160. package/labs/gb/styles/m3.css +5 -2
  161. package/labs/gb/styles/m3.css.map +1 -1
  162. package/labs/gb/styles/m3.cssresult.js +5 -2
  163. package/labs/gb/styles/m3.cssresult.js.map +1 -1
  164. package/labs/gb/styles/m3.scss +1 -0
  165. package/labs/gb/styles/space/md-space-tokens.css +4 -0
  166. package/labs/gb/styles/space/md-space-tokens.css.map +1 -0
  167. package/labs/gb/styles/space/md-space-tokens.cssresult.d.ts +3 -0
  168. package/labs/gb/styles/space/md-space-tokens.cssresult.js +14 -0
  169. package/labs/gb/styles/space/md-space-tokens.cssresult.js.map +1 -0
  170. package/labs/gb/styles/space/md-space-tokens.scss +28 -0
  171. package/labs/gb/styles/tailwind.css +4 -0
  172. package/labs/gb/styles/tailwind.css.map +1 -0
  173. package/labs/gb/styles/tailwind.cssresult.d.ts +3 -0
  174. package/labs/gb/styles/tailwind.cssresult.js +14 -0
  175. package/labs/gb/styles/tailwind.cssresult.js.map +1 -0
  176. package/labs/gb/styles/tailwind.scss +250 -0
  177. package/labs/gb/styles/typography/internal/_typography-tokens.scss +85 -16
  178. package/labs/gb/styles/typography/md-typography-tokens.css +1 -1
  179. package/labs/gb/styles/typography/md-typography-tokens.css.map +1 -1
  180. package/labs/gb/styles/typography/md-typography-tokens.cssresult.js +1 -1
  181. package/labs/gb/styles/typography/md-typography-tokens.cssresult.js.map +1 -1
  182. package/list/internal/listitem/list-item.d.ts +2 -0
  183. package/menu/internal/menuitem/menu-item.d.ts +2 -0
  184. package/package.json +7 -3
  185. package/radio/internal/radio.d.ts +0 -2
  186. package/radio/internal/radio.js.map +1 -1
  187. package/select/internal/select.d.ts +2 -2
  188. package/select/internal/select.js.map +1 -1
  189. package/select/internal/selectoption/select-option.d.ts +2 -0
  190. package/slider/internal/slider.d.ts +0 -2
  191. package/slider/internal/slider.js.map +1 -1
  192. package/switch/internal/_switch.scss +1 -0
  193. package/switch/internal/switch-styles.css +1 -1
  194. package/switch/internal/switch-styles.css.map +1 -1
  195. package/switch/internal/switch-styles.cssresult.js +1 -1
  196. package/switch/internal/switch-styles.cssresult.js.map +1 -1
  197. package/switch/internal/switch.d.ts +0 -2
  198. package/switch/internal/switch.js.map +1 -1
@@ -0,0 +1,164 @@
1
+ /*!
2
+ * Copyright 2026 Google LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ // go/keep-sorted start by_regex='(.+) prefix_order=sass:
7
+ @use 'split-button-tokens';
8
+ // go/keep-sorted end
9
+
10
+ @layer md.sys, md.comp.ripple, md.comp.focus-ring, md.comp.button;
11
+ @layer md.comp.split-button {
12
+ .split-btn {
13
+ @include split-button-tokens.root;
14
+
15
+ .btn {
16
+ @include split-button-tokens.button;
17
+ }
18
+
19
+ .btn-xs {
20
+ @include split-button-tokens.button-xs;
21
+
22
+ &:where(:nth-child(1 of .btn)) {
23
+ @include split-button-tokens.button-xs-leading;
24
+ }
25
+
26
+ &:where(:nth-last-child(1 of .btn)) {
27
+ @include split-button-tokens.button-xs-trailing;
28
+ }
29
+
30
+ &:where(:hover, .hover) {
31
+ @include split-button-tokens.button-xs-hovered;
32
+ }
33
+
34
+ &:where(:active, .active) {
35
+ @include split-button-tokens.button-xs-pressed;
36
+ }
37
+ }
38
+
39
+ .btn-sm {
40
+ @include split-button-tokens.button-sm;
41
+
42
+ &:where(:nth-child(1 of .btn)) {
43
+ @include split-button-tokens.button-sm-leading;
44
+ }
45
+
46
+ &:where(:nth-last-child(1 of .btn)) {
47
+ @include split-button-tokens.button-sm-trailing;
48
+ }
49
+
50
+ &:where(:hover, .hover) {
51
+ @include split-button-tokens.button-sm-hovered;
52
+ }
53
+
54
+ &:where(:active, .active) {
55
+ @include split-button-tokens.button-sm-pressed;
56
+ }
57
+ }
58
+
59
+ .btn-md {
60
+ @include split-button-tokens.button-md;
61
+
62
+ &:where(:nth-child(1 of .btn)) {
63
+ @include split-button-tokens.button-md-leading;
64
+ }
65
+
66
+ &:where(:nth-last-child(1 of .btn)) {
67
+ @include split-button-tokens.button-md-trailing;
68
+ }
69
+
70
+ &:where(:hover, .hover) {
71
+ @include split-button-tokens.button-md-hovered;
72
+ }
73
+
74
+ &:where(:active, .active) {
75
+ @include split-button-tokens.button-md-pressed;
76
+ }
77
+ }
78
+
79
+ .btn-lg {
80
+ @include split-button-tokens.button-lg;
81
+
82
+ &:where(:nth-child(1 of .btn)) {
83
+ @include split-button-tokens.button-lg-leading;
84
+ }
85
+
86
+ &:where(:nth-last-child(1 of .btn)) {
87
+ @include split-button-tokens.button-lg-trailing;
88
+ }
89
+
90
+ &:where(:hover, .hover) {
91
+ @include split-button-tokens.button-lg-hovered;
92
+ }
93
+
94
+ &:where(:active, .active) {
95
+ @include split-button-tokens.button-lg-pressed;
96
+ }
97
+ }
98
+
99
+ .btn-xl {
100
+ @include split-button-tokens.button-xl;
101
+
102
+ &:where(:nth-child(1 of .btn)) {
103
+ @include split-button-tokens.button-xl-leading;
104
+ }
105
+
106
+ &:where(:nth-last-child(1 of .btn)) {
107
+ @include split-button-tokens.button-xl-trailing;
108
+ }
109
+
110
+ &:where(:hover, .hover) {
111
+ @include split-button-tokens.button-xl-hovered;
112
+ }
113
+
114
+ &:where(:active, .active) {
115
+ @include split-button-tokens.button-xl-pressed;
116
+ }
117
+ }
118
+
119
+ &:is(.split-btn-selected, :has(:popover-open)) {
120
+ :nth-last-child(1 of .btn) {
121
+ @include split-button-tokens.button-trailing-selected;
122
+ }
123
+ }
124
+ }
125
+
126
+ .split-btn {
127
+ & {
128
+ display: inline-flex;
129
+ align-items: center;
130
+ gap: var(--between-space);
131
+ }
132
+
133
+ :nth-child(1 of .btn) {
134
+ border-start-start-radius: var(--outer-corner-size);
135
+ border-end-start-radius: var(--outer-corner-size);
136
+ border-start-end-radius: var(--inner-corner-size);
137
+ border-end-end-radius: var(--inner-corner-size);
138
+ }
139
+
140
+ :nth-last-child(1 of .btn) {
141
+ border-start-start-radius: var(--inner-corner-size);
142
+ border-end-start-radius: var(--inner-corner-size);
143
+ border-start-end-radius: var(--outer-corner-size);
144
+ border-end-end-radius: var(--outer-corner-size);
145
+
146
+ &::before {
147
+ content: 'arrow_drop_down';
148
+ font: var(--md-icon-size) var(--md-icon-font);
149
+ display: flex;
150
+ align-items: center;
151
+ aspect-ratio: 1;
152
+ width: var(--md-icon-size);
153
+ overflow: hidden;
154
+ }
155
+ }
156
+
157
+ &:is(.split-btn-selected, :has(:popover-open))
158
+ :nth-last-child(1 of .btn)::before {
159
+ transform: rotate(180deg);
160
+ transition: transform var(--md-sys-motion-duration-short4)
161
+ var(--md-sys-motion-easing-standard);
162
+ }
163
+ }
164
+ }
@@ -0,0 +1,56 @@
1
+ //
2
+ // Copyright 2026 Google LLC
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ //
5
+
6
+ @mixin root {
7
+ --handle-color: var(--md-sys-color-outline);
8
+ --handle-size: 16px;
9
+ --with-icon-handle-size: 24px;
10
+ --icon-color: var(--md-sys-color-surface-container-highest);
11
+ --icon-size: 18px;
12
+ --state-layer-color: var(--md-sys-color-on-surface);
13
+ --state-layer-size: 40px;
14
+ --track-color: var(--md-sys-color-surface-container-highest);
15
+ --track-height: 32px;
16
+ --track-outline-color: var(--md-sys-color-outline);
17
+ --track-outline-width: 2px;
18
+ --track-width: 52px;
19
+ }
20
+
21
+ @mixin hovered {
22
+ --handle-color: var(--md-sys-color-on-surface-variant);
23
+ }
24
+
25
+ @mixin selected {
26
+ --track-color: var(--md-sys-color-primary);
27
+ --track-outline-color: transparent;
28
+ --handle-color: var(--md-sys-color-on-primary);
29
+ --handle-size: 24px;
30
+ --icon-color: var(--md-sys-color-on-primary-container);
31
+ --state-layer-color: var(--md-sys-color-primary);
32
+ }
33
+
34
+ @mixin selected-hovered {
35
+ --handle-color: var(--md-sys-color-primary-container);
36
+ }
37
+
38
+ @mixin pressed {
39
+ --handle-size: 28px;
40
+ }
41
+
42
+ @mixin disabled {
43
+ --handle-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);
44
+ --track-color: hsl(
45
+ from var(--md-sys-color-surface-container-highest) h s l / 12%
46
+ );
47
+ --track-outline-color: hsl(
48
+ from var(--md-sys-color-on-surface) h s l / 12%
49
+ );
50
+ }
51
+
52
+ @mixin disabled-selected {
53
+ --handle-color: var(--md-sys-color-surface);
54
+ --icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);
55
+ --track-color: hsl(from var(--md-sys-color-on-surface) h s l / 12%);
56
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { CSSResultOrNative, LitElement } from 'lit';
7
+ import { createValidator, getValidityAnchor } from '../../../behaviors/constraint-validation.js';
8
+ import { getFormState, getFormValue } from '../../../behaviors/form-associated.js';
9
+ import { CheckboxValidator } from '../../../behaviors/validators/checkbox-validator.js';
10
+ declare global {
11
+ interface HTMLElementTagNameMap {
12
+ /** A Material Design switch component. */
13
+ 'md-switch': Switch;
14
+ }
15
+ }
16
+ declare const baseClass: import("@material/web/labs/behaviors/mixin.js").MixinReturn<import("@material/web/labs/behaviors/mixin.js").MixinReturn<import("@material/web/labs/behaviors/mixin.js").MixinReturn<(abstract new (...args: any[]) => import("../../../behaviors/custom-state-set.js").WithCustomStateSet) & (abstract new (...args: any[]) => import("../../../behaviors/element-internals.js").WithElementInternals) & typeof LitElement & import("../../../behaviors/form-associated.js").FormAssociatedConstructor, import("../../../behaviors/form-associated.js").FormAssociated>, import("../../../behaviors/constraint-validation.js").ConstraintValidation>>;
17
+ /**
18
+ * A Material Design switch component.
19
+ */
20
+ export declare class Switch extends baseClass {
21
+ /** @nocollapse */
22
+ static shadowRootOptions: ShadowRootInit;
23
+ static styles: CSSResultOrNative[];
24
+ /**
25
+ * Puts the switch in the selected state and sets the form submission value to
26
+ * the `value` property.
27
+ */
28
+ get selected(): boolean;
29
+ set selected(value: boolean);
30
+ /**
31
+ * The default selected state of the switch.
32
+ */
33
+ get defaultSelected(): boolean;
34
+ set defaultSelected(value: boolean);
35
+ /**
36
+ * When true, require the switch to be selected when participating in
37
+ * form submission.
38
+ *
39
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#validation
40
+ */
41
+ required: boolean;
42
+ /**
43
+ * The value associated with this switch on form submission. `null` is
44
+ * submitted when `selected` is `false`.
45
+ */
46
+ value: string;
47
+ private readonly button;
48
+ /**
49
+ * Mimics the behavior of <input> dirty checkedness, where the `checked`
50
+ * attribute only updates the checked state if the checkbox has not been
51
+ * interacted with.
52
+ *
53
+ * @see https://html.spec.whatwg.org/multipage/input.html#concept-input-checked-dirty-flag
54
+ */
55
+ private dirtyCheckedness;
56
+ protected render(): import("lit-html").TemplateResult<1>;
57
+ private handleChange;
58
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
59
+ [getFormValue](): string;
60
+ [getFormState](): string;
61
+ formResetCallback(): void;
62
+ formStateRestoreCallback(state: string): void;
63
+ [createValidator](): CheckboxValidator;
64
+ [getValidityAnchor](): HTMLButtonElement;
65
+ }
66
+ export {};
@@ -0,0 +1,162 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { __decorate } from "tslib";
7
+ import { css, html, LitElement, nothing } from 'lit';
8
+ import { customElement, property, query } from 'lit/decorators.js';
9
+ import { mixinDelegatesAria } from '../../../../internal/aria/delegate.js';
10
+ import { redispatchEvent } from '../../../../internal/events/redispatch-event.js';
11
+ import { createValidator, getValidityAnchor, mixinConstraintValidation, } from '../../../behaviors/constraint-validation.js';
12
+ import { hasState, mixinCustomStateSet, toggleState, } from '../../../behaviors/custom-state-set.js';
13
+ import { mixinElementInternals } from '../../../behaviors/element-internals.js';
14
+ import { getFormState, getFormValue, mixinFormAssociated, } from '../../../behaviors/form-associated.js';
15
+ import { CheckboxValidator } from '../../../behaviors/validators/checkbox-validator.js';
16
+ import { hasSlotted } from '../shared/has-slotted.js';
17
+ import focusRingStyles from '../focus/focus-ring.css' with { type: 'css' }; // github-only
18
+ // import focusRingStyles from '../focus/focus-ring.cssresult.js'; // google3-only
19
+ import rippleStyles from '../ripple/ripple.css' with { type: 'css' }; // github-only
20
+ // import rippleStyles from '../ripple/ripple.cssresult.js'; // google3-only
21
+ import switchStyles from './switch.css' with { type: 'css' }; // github-only
22
+ // import switchStyles from './switch.cssresult.js'; // google3-only
23
+ import { switchToggle } from './switch.js';
24
+ // Separate variable needed for closure.
25
+ const baseClass = mixinDelegatesAria(mixinConstraintValidation(mixinFormAssociated(mixinCustomStateSet(mixinElementInternals(LitElement)))));
26
+ /**
27
+ * A Material Design switch component.
28
+ */
29
+ let Switch = class Switch extends baseClass {
30
+ constructor() {
31
+ super(...arguments);
32
+ /**
33
+ * When true, require the switch to be selected when participating in
34
+ * form submission.
35
+ *
36
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#validation
37
+ */
38
+ this.required = false;
39
+ /**
40
+ * The value associated with this switch on form submission. `null` is
41
+ * submitted when `selected` is `false`.
42
+ */
43
+ this.value = 'on';
44
+ /**
45
+ * Mimics the behavior of <input> dirty checkedness, where the `checked`
46
+ * attribute only updates the checked state if the checkbox has not been
47
+ * interacted with.
48
+ *
49
+ * @see https://html.spec.whatwg.org/multipage/input.html#concept-input-checked-dirty-flag
50
+ */
51
+ this.dirtyCheckedness = false;
52
+ }
53
+ /**
54
+ * Puts the switch in the selected state and sets the form submission value to
55
+ * the `value` property.
56
+ */
57
+ get selected() {
58
+ return this[hasState]('selected');
59
+ }
60
+ set selected(value) {
61
+ this[toggleState]('selected', value);
62
+ }
63
+ /**
64
+ * The default selected state of the switch.
65
+ */
66
+ get defaultSelected() {
67
+ return this.hasAttribute('selected');
68
+ }
69
+ set defaultSelected(value) {
70
+ this.toggleAttribute('selected', value || false);
71
+ }
72
+ render() {
73
+ const { ariaLabel } = this;
74
+ return html `
75
+ <button
76
+ role="switch"
77
+ part="switch"
78
+ class="${switchToggle()}"
79
+ aria-checked="${this.selected ? 'true' : 'false'}"
80
+ aria-label=${ariaLabel || nothing}
81
+ ?disabled=${this.disabled}
82
+ @change=${this.handleChange}>
83
+ <slot name="off-icon" class="switch-icon-off" ${hasSlotted()}></slot>
84
+ <slot name="on-icon" class="switch-icon-on"></slot>
85
+ </button>
86
+ `;
87
+ }
88
+ handleChange(event) {
89
+ this.dirtyCheckedness = true;
90
+ this.selected = this.button?.ariaChecked === 'true';
91
+ // Change event is not composed, re-dispatch it.
92
+ redispatchEvent(this, event);
93
+ }
94
+ attributeChangedCallback(name, oldValue, newValue) {
95
+ if (name === 'selected' && this.dirtyCheckedness) {
96
+ // The 'selected' attribute does not update switches that have been
97
+ // interacted with.
98
+ return;
99
+ }
100
+ super.attributeChangedCallback(name, oldValue, newValue);
101
+ }
102
+ [getFormValue]() {
103
+ return this.selected ? this.value : null;
104
+ }
105
+ [getFormState]() {
106
+ return String(this.selected);
107
+ }
108
+ formResetCallback() {
109
+ this.dirtyCheckedness = false;
110
+ this.selected = this.defaultSelected;
111
+ }
112
+ formStateRestoreCallback(state) {
113
+ this.selected = state === 'true';
114
+ }
115
+ [createValidator]() {
116
+ return new CheckboxValidator(() => ({
117
+ checked: this.selected,
118
+ required: this.required,
119
+ }));
120
+ }
121
+ [getValidityAnchor]() {
122
+ return this.button;
123
+ }
124
+ };
125
+ /** @nocollapse */
126
+ Switch.shadowRootOptions = {
127
+ mode: 'open',
128
+ delegatesFocus: true,
129
+ };
130
+ Switch.styles = [
131
+ focusRingStyles,
132
+ rippleStyles,
133
+ switchStyles,
134
+ css `
135
+ :host {
136
+ display: inline-flex;
137
+ }
138
+ .switch {
139
+ flex: 1;
140
+ }
141
+ ::slotted(*) {
142
+ grid-area: handle;
143
+ }
144
+ `,
145
+ ];
146
+ __decorate([
147
+ property({ type: Boolean })
148
+ ], Switch.prototype, "selected", null);
149
+ __decorate([
150
+ property({ type: Boolean })
151
+ ], Switch.prototype, "required", void 0);
152
+ __decorate([
153
+ property()
154
+ ], Switch.prototype, "value", void 0);
155
+ __decorate([
156
+ query('button', true)
157
+ ], Switch.prototype, "button", void 0);
158
+ Switch = __decorate([
159
+ customElement('md-switch')
160
+ ], Switch);
161
+ export { Switch };
162
+ //# sourceMappingURL=md-switch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md-switch.js","sourceRoot":"","sources":["md-switch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {css, CSSResultOrNative, html, LitElement, nothing} from 'lit';\nimport {customElement, property, query} from 'lit/decorators.js';\nimport {ARIAMixinStrict} from '../../../../internal/aria/aria.js';\nimport {mixinDelegatesAria} from '../../../../internal/aria/delegate.js';\nimport {redispatchEvent} from '../../../../internal/events/redispatch-event.js';\nimport {\n createValidator,\n getValidityAnchor,\n mixinConstraintValidation,\n} from '../../../behaviors/constraint-validation.js';\nimport {\n hasState,\n mixinCustomStateSet,\n toggleState,\n} from '../../../behaviors/custom-state-set.js';\nimport {mixinElementInternals} from '../../../behaviors/element-internals.js';\nimport {\n getFormState,\n getFormValue,\n mixinFormAssociated,\n} from '../../../behaviors/form-associated.js';\nimport {CheckboxValidator} from '../../../behaviors/validators/checkbox-validator.js';\nimport {hasSlotted} from '../shared/has-slotted.js';\n\nimport focusRingStyles from '../focus/focus-ring.css' with {type: 'css'}; // github-only\n// import focusRingStyles from '../focus/focus-ring.cssresult.js'; // google3-only\nimport rippleStyles from '../ripple/ripple.css' with {type: 'css'}; // github-only\n// import rippleStyles from '../ripple/ripple.cssresult.js'; // google3-only\nimport switchStyles from './switch.css' with {type: 'css'}; // github-only\n// import switchStyles from './switch.cssresult.js'; // google3-only\n\nimport {switchToggle} from './switch.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n /** A Material Design switch component. */\n 'md-switch': Switch;\n }\n}\n\n// Separate variable needed for closure.\nconst baseClass = mixinDelegatesAria(\n mixinConstraintValidation(\n mixinFormAssociated(mixinCustomStateSet(mixinElementInternals(LitElement))),\n ),\n);\n\n/**\n * A Material Design switch component.\n */\n@customElement('md-switch')\nexport class Switch extends baseClass {\n /** @nocollapse */\n static override shadowRootOptions: ShadowRootInit = {\n mode: 'open',\n delegatesFocus: true,\n };\n\n static override styles: CSSResultOrNative[] = [\n focusRingStyles,\n rippleStyles,\n switchStyles,\n css`\n :host {\n display: inline-flex;\n }\n .switch {\n flex: 1;\n }\n ::slotted(*) {\n grid-area: handle;\n }\n `,\n ];\n\n /**\n * Puts the switch in the selected state and sets the form submission value to\n * the `value` property.\n */\n @property({type: Boolean})\n get selected() {\n return this[hasState]('selected');\n }\n set selected(value: boolean) {\n this[toggleState]('selected', value);\n }\n\n /**\n * The default selected state of the switch.\n */\n get defaultSelected(): boolean {\n return this.hasAttribute('selected');\n }\n set defaultSelected(value: boolean) {\n this.toggleAttribute('selected', value || false);\n }\n\n /**\n * When true, require the switch to be selected when participating in\n * form submission.\n *\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#validation\n */\n @property({type: Boolean}) required = false;\n\n /**\n * The value associated with this switch on form submission. `null` is\n * submitted when `selected` is `false`.\n */\n @property() value = 'on';\n\n @query('button', true)\n private readonly button!: HTMLButtonElement | null;\n\n /**\n * Mimics the behavior of <input> dirty checkedness, where the `checked`\n * attribute only updates the checked state if the checkbox has not been\n * interacted with.\n *\n * @see https://html.spec.whatwg.org/multipage/input.html#concept-input-checked-dirty-flag\n */\n private dirtyCheckedness = false;\n\n protected override render() {\n const {ariaLabel} = this as ARIAMixinStrict;\n return html`\n <button\n role=\"switch\"\n part=\"switch\"\n class=\"${switchToggle()}\"\n aria-checked=\"${this.selected ? 'true' : 'false'}\"\n aria-label=${ariaLabel || nothing}\n ?disabled=${this.disabled}\n @change=${this.handleChange}>\n <slot name=\"off-icon\" class=\"switch-icon-off\" ${hasSlotted()}></slot>\n <slot name=\"on-icon\" class=\"switch-icon-on\"></slot>\n </button>\n `;\n }\n\n private handleChange(event: Event) {\n this.dirtyCheckedness = true;\n this.selected = this.button?.ariaChecked === 'true';\n // Change event is not composed, re-dispatch it.\n redispatchEvent(this, event);\n }\n\n override attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string | null,\n ) {\n if (name === 'selected' && this.dirtyCheckedness) {\n // The 'selected' attribute does not update switches that have been\n // interacted with.\n return;\n }\n\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n override [getFormValue]() {\n return this.selected ? this.value : null;\n }\n\n override [getFormState]() {\n return String(this.selected);\n }\n\n override formResetCallback() {\n this.dirtyCheckedness = false;\n this.selected = this.defaultSelected;\n }\n\n override formStateRestoreCallback(state: string) {\n this.selected = state === 'true';\n }\n\n override [createValidator]() {\n return new CheckboxValidator(() => ({\n checked: this.selected,\n required: this.required,\n }));\n }\n\n override [getValidityAnchor]() {\n return this.button;\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ /*!
2
+ * Copyright 2026 Google LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */@layer md.sys, md.comp.ripple, md.comp.focus-ring;@layer md.comp.switch{.switch{--handle-color: var(--md-sys-color-outline);--handle-size: 16px;--with-icon-handle-size: 24px;--icon-color: var(--md-sys-color-surface-container-highest);--icon-size: 18px;--state-layer-color: var(--md-sys-color-on-surface);--state-layer-size: 40px;--track-color: var(--md-sys-color-surface-container-highest);--track-height: 32px;--track-outline-color: var(--md-sys-color-outline);--track-outline-width: 2px;--track-width: 52px}.switch:is(:hover,.hover){--handle-color: var(--md-sys-color-on-surface-variant)}.switch:is(:checked,.checked,[aria-checked=true]){--track-color: var(--md-sys-color-primary);--track-outline-color: transparent;--handle-color: var(--md-sys-color-on-primary);--handle-size: 24px;--icon-color: var(--md-sys-color-on-primary-container);--state-layer-color: var(--md-sys-color-primary)}.switch:is(:checked,.checked,[aria-checked=true]):where(:hover,.hover){--handle-color: var(--md-sys-color-primary-container)}.switch:is(:active,.active):where(:not(:disabled,.disabled)){--handle-size: 28px}.switch:is(:disabled,.disabled){--handle-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--track-color: hsl( from var(--md-sys-color-surface-container-highest) h s l / 12% );--track-outline-color: hsl( from var(--md-sys-color-on-surface) h s l / 12% )}.switch:is(:disabled,.disabled):where(:checked,.checked,[aria-checked=true]){--handle-color: var(--md-sys-color-surface);--icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--track-color: hsl(from var(--md-sys-color-on-surface) h s l / 12%)}.switch{display:inline-grid;grid-template:". handle ." 1fr/0fr min-content 1fr;place-items:center;appearance:none;background:var(--track-color);border:var(--track-outline-width) solid var(--track-outline-color);border-radius:calc(var(--track-height)/2);width:var(--track-width);height:var(--track-height);margin:0;padding:0;transition:grid-template-columns 75ms cubic-bezier(0.4, 0, 0.2, 1);isolation:isolate;position:relative;color:var(--icon-color);--md-icon-size: var(--icon-size);--icon: ""}.switch:is(:checked,.checked,[aria-checked=true]){grid-template-columns:1fr min-content 0fr}.switch::before{--_handle-size: if( style(--icon: ""): var(--handle-size); else: max(var(--handle-size), var(--with-icon-handle-size)); );content:var(--icon);font:var(--md-icon-size) var(--md-icon-font);display:grid;place-items:center;z-index:-1;grid-area:handle;aspect-ratio:1;height:100%;clip-path:circle(calc(var(--_handle-size) / 2));transition:clip-path 75ms cubic-bezier(0.4, 0, 0.2, 1);border-radius:50%;background:var(--handle-color)}.switch::after{content:"";z-index:-1;position:absolute;grid-area:handle;background-image:var(--ripple);aspect-ratio:1;width:var(--state-layer-size);border-radius:50%;color:var(--state-layer-color);transition:var(--ripple-transition);animation:var(--ripple-animation)}.switch:has(.switch-icon-off:not(slot),.switch-icon-off.has-slotted){--icon: " "}.switch .switch-icon-off:not(slot),.switch .switch-icon-off::slotted(*),.switch .switch-icon-on:not(slot),.switch .switch-icon-on::slotted(*){grid-area:handle}.switch:is(:checked,.checked,[aria-checked=true]) .switch-icon-off,.switch:not(:checked,.checked,[aria-checked=true]) .switch-icon-on{display:none}}/*# sourceMappingURL=switch.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sourceRoot":"","sources":["switch.scss","_switch-tokens.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA,GASA,kDACA,sBAEI,QCNF,4CACA,oBACA,8BACA,4DACA,kBACA,oDACA,yBACA,6DACA,qBACA,mDACA,2BACA,oBDFE,0BCMF,uDDHE,kDCOF,2CACA,mCACA,+CACA,oBACA,uDACA,iDDVI,uECcJ,sDDVE,6DCcF,oBDXE,gCCeF,qEACA,qFAGA,8EDjBI,6ECuBJ,4CACA,mEACA,oEDpBE,QACE,oBACA,mDACA,mBACA,gBACA,8BACA,mEACA,0CACA,yBACA,2BACA,SACA,UACA,mEACA,kBACA,kBACA,wBACA,iCACA,WAEA,kDACE,0CAGF,gBACE,0HAIA,oBACA,6CACA,aACA,mBACA,WACA,iBACA,eACA,YACA,gDACA,uDACA,kBACA,+BAGF,eACE,WACA,WACA,kBACA,iBACA,+BACA,eACA,8BACA,kBACA,+BACA,oCACA,kCAIJ,qEACE,YAKA,8IAEE,iBAIJ,sIAEE","file":"switch.css"}
@@ -0,0 +1,3 @@
1
+ export declare const styles: import("lit").CSSResult;
2
+ declare const _default: CSSStyleSheet;
3
+ export default _default;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ // Generated stylesheet for ./labs/gb/components/switch/switch.css.
7
+ import { css } from 'lit';
8
+ export const styles = css `/*!
9
+ * Copyright 2026 Google LLC
10
+ * SPDX-License-Identifier: Apache-2.0
11
+ */@layer md.sys, md.comp.ripple, md.comp.focus-ring;@layer md.comp.switch{.switch{--handle-color: var(--md-sys-color-outline);--handle-size: 16px;--with-icon-handle-size: 24px;--icon-color: var(--md-sys-color-surface-container-highest);--icon-size: 18px;--state-layer-color: var(--md-sys-color-on-surface);--state-layer-size: 40px;--track-color: var(--md-sys-color-surface-container-highest);--track-height: 32px;--track-outline-color: var(--md-sys-color-outline);--track-outline-width: 2px;--track-width: 52px}.switch:is(:hover,.hover){--handle-color: var(--md-sys-color-on-surface-variant)}.switch:is(:checked,.checked,[aria-checked=true]){--track-color: var(--md-sys-color-primary);--track-outline-color: transparent;--handle-color: var(--md-sys-color-on-primary);--handle-size: 24px;--icon-color: var(--md-sys-color-on-primary-container);--state-layer-color: var(--md-sys-color-primary)}.switch:is(:checked,.checked,[aria-checked=true]):where(:hover,.hover){--handle-color: var(--md-sys-color-primary-container)}.switch:is(:active,.active):where(:not(:disabled,.disabled)){--handle-size: 28px}.switch:is(:disabled,.disabled){--handle-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--track-color: hsl( from var(--md-sys-color-surface-container-highest) h s l / 12% );--track-outline-color: hsl( from var(--md-sys-color-on-surface) h s l / 12% )}.switch:is(:disabled,.disabled):where(:checked,.checked,[aria-checked=true]){--handle-color: var(--md-sys-color-surface);--icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--track-color: hsl(from var(--md-sys-color-on-surface) h s l / 12%)}.switch{display:inline-grid;grid-template:". handle ." 1fr/0fr min-content 1fr;place-items:center;appearance:none;background:var(--track-color);border:var(--track-outline-width) solid var(--track-outline-color);border-radius:calc(var(--track-height)/2);width:var(--track-width);height:var(--track-height);margin:0;padding:0;transition:grid-template-columns 75ms cubic-bezier(0.4, 0, 0.2, 1);isolation:isolate;position:relative;color:var(--icon-color);--md-icon-size: var(--icon-size);--icon: ""}.switch:is(:checked,.checked,[aria-checked=true]){grid-template-columns:1fr min-content 0fr}.switch::before{--_handle-size: if( style(--icon: ""): var(--handle-size); else: max(var(--handle-size), var(--with-icon-handle-size)); );content:var(--icon);font:var(--md-icon-size) var(--md-icon-font);display:grid;place-items:center;z-index:-1;grid-area:handle;aspect-ratio:1;height:100%;clip-path:circle(calc(var(--_handle-size) / 2));transition:clip-path 75ms cubic-bezier(0.4, 0, 0.2, 1);border-radius:50%;background:var(--handle-color)}.switch::after{content:"";z-index:-1;position:absolute;grid-area:handle;background-image:var(--ripple);aspect-ratio:1;width:var(--state-layer-size);border-radius:50%;color:var(--state-layer-color);transition:var(--ripple-transition);animation:var(--ripple-animation)}.switch:has(.switch-icon-off:not(slot),.switch-icon-off.has-slotted){--icon: " "}.switch .switch-icon-off:not(slot),.switch .switch-icon-off::slotted(*),.switch .switch-icon-on:not(slot),.switch .switch-icon-on::slotted(*){grid-area:handle}.switch:is(:checked,.checked,[aria-checked=true]) .switch-icon-off,.switch:not(:checked,.checked,[aria-checked=true]) .switch-icon-on{display:none}}
12
+ `;
13
+ export default styles.styleSheet;
14
+ //# sourceMappingURL=switch.cssresult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switch.cssresult.js","sourceRoot":"","sources":["switch.cssresult.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,mEAAmE;AACnE,OAAO,EAAC,GAAG,EAAC,MAAM,KAAK,CAAC;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;CAIxB,CAAC;AACF,eAAe,MAAM,CAAC,UAAW,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n// Generated stylesheet for ./labs/gb/components/switch/switch.css.\nimport {css} from 'lit';\nexport const styles = css`/*!\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */@layer md.sys, md.comp.ripple, md.comp.focus-ring;@layer md.comp.switch{.switch{--handle-color: var(--md-sys-color-outline);--handle-size: 16px;--with-icon-handle-size: 24px;--icon-color: var(--md-sys-color-surface-container-highest);--icon-size: 18px;--state-layer-color: var(--md-sys-color-on-surface);--state-layer-size: 40px;--track-color: var(--md-sys-color-surface-container-highest);--track-height: 32px;--track-outline-color: var(--md-sys-color-outline);--track-outline-width: 2px;--track-width: 52px}.switch:is(:hover,.hover){--handle-color: var(--md-sys-color-on-surface-variant)}.switch:is(:checked,.checked,[aria-checked=true]){--track-color: var(--md-sys-color-primary);--track-outline-color: transparent;--handle-color: var(--md-sys-color-on-primary);--handle-size: 24px;--icon-color: var(--md-sys-color-on-primary-container);--state-layer-color: var(--md-sys-color-primary)}.switch:is(:checked,.checked,[aria-checked=true]):where(:hover,.hover){--handle-color: var(--md-sys-color-primary-container)}.switch:is(:active,.active):where(:not(:disabled,.disabled)){--handle-size: 28px}.switch:is(:disabled,.disabled){--handle-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--track-color: hsl( from var(--md-sys-color-surface-container-highest) h s l / 12% );--track-outline-color: hsl( from var(--md-sys-color-on-surface) h s l / 12% )}.switch:is(:disabled,.disabled):where(:checked,.checked,[aria-checked=true]){--handle-color: var(--md-sys-color-surface);--icon-color: hsl(from var(--md-sys-color-on-surface) h s l / 38%);--track-color: hsl(from var(--md-sys-color-on-surface) h s l / 12%)}.switch{display:inline-grid;grid-template:\". handle .\" 1fr/0fr min-content 1fr;place-items:center;appearance:none;background:var(--track-color);border:var(--track-outline-width) solid var(--track-outline-color);border-radius:calc(var(--track-height)/2);width:var(--track-width);height:var(--track-height);margin:0;padding:0;transition:grid-template-columns 75ms cubic-bezier(0.4, 0, 0.2, 1);isolation:isolate;position:relative;color:var(--icon-color);--md-icon-size: var(--icon-size);--icon: \"\"}.switch:is(:checked,.checked,[aria-checked=true]){grid-template-columns:1fr min-content 0fr}.switch::before{--_handle-size: if( style(--icon: \"\"): var(--handle-size); else: max(var(--handle-size), var(--with-icon-handle-size)); );content:var(--icon);font:var(--md-icon-size) var(--md-icon-font);display:grid;place-items:center;z-index:-1;grid-area:handle;aspect-ratio:1;height:100%;clip-path:circle(calc(var(--_handle-size) / 2));transition:clip-path 75ms cubic-bezier(0.4, 0, 0.2, 1);border-radius:50%;background:var(--handle-color)}.switch::after{content:\"\";z-index:-1;position:absolute;grid-area:handle;background-image:var(--ripple);aspect-ratio:1;width:var(--state-layer-size);border-radius:50%;color:var(--state-layer-color);transition:var(--ripple-transition);animation:var(--ripple-animation)}.switch:has(.switch-icon-off:not(slot),.switch-icon-off.has-slotted){--icon: \" \"}.switch .switch-icon-off:not(slot),.switch .switch-icon-off::slotted(*),.switch .switch-icon-on:not(slot),.switch .switch-icon-on::slotted(*){grid-area:handle}.switch:is(:checked,.checked,[aria-checked=true]) .switch-icon-off,.switch:not(:checked,.checked,[aria-checked=true]) .switch-icon-on{display:none}}\n`;\nexport default styles.styleSheet!;\n"]}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type ClassInfo } from 'lit/directives/class-map.js';
7
+ /** Switch classes. */
8
+ export declare const SWITCH_CLASSES: {
9
+ readonly switch: "switch";
10
+ readonly checked: string;
11
+ readonly hover: string;
12
+ readonly active: string;
13
+ readonly disabled: string;
14
+ };
15
+ /** The state provided to the `switchClasses()` function. */
16
+ export interface SwitchClassesState {
17
+ /** Emulates `:checked`. */
18
+ checked?: boolean;
19
+ /** Emulates `:hover`. */
20
+ hover?: boolean;
21
+ /** Emulates `:active`. */
22
+ active?: boolean;
23
+ /** Emulates `:disabled`. */
24
+ disabled?: boolean;
25
+ }
26
+ /**
27
+ * Returns the switch classes to apply to an element based on the given state.
28
+ *
29
+ * @param state The state of the switch.
30
+ * @return An object of class names and truthy values if they apply.
31
+ */
32
+ export declare function switchClasses({ checked, hover, active, disabled, }?: SwitchClassesState): ClassInfo;
33
+ /**
34
+ * Sets up switch functionality for the given element.
35
+ *
36
+ * @param switchEl The element on which to set up switch functionality.
37
+ * @param opts Setup options, supports a cleanup `signal`.
38
+ */
39
+ export declare function setupSwitch(switchEl: HTMLElement, opts?: {
40
+ signal?: AbortSignal;
41
+ }): void;
42
+ /**
43
+ * A Lit directive that adds switch styling and functionality to its element.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * html`
48
+ * <input role="switch" type="checkbox" class="${switchToggle()}">
49
+ *
50
+ * <button role="switch" aria-checked="false" class="${switchToggle()}"></button>
51
+ * `;
52
+ * ```
53
+ */
54
+ export declare const switchToggle: (state?: SwitchClassesState & import("../shared/directives.js").AdditionalClasses) => import("lit-html/directive.js").DirectiveResult;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { afterDispatch, setupDispatchHooks, } from '../../../../internal/events/dispatch-hooks.js';
7
+ import { focusRingClasses } from '../focus/focus-ring.js';
8
+ import { rippleClasses, setupRipple } from '../ripple/ripple.js';
9
+ import { createClassMapDirective } from '../shared/directives.js';
10
+ import { PSEUDO_CLASSES, isDisabled } from '../shared/pseudo-classes.js';
11
+ /** Switch classes. */
12
+ export const SWITCH_CLASSES = {
13
+ switch: 'switch',
14
+ checked: PSEUDO_CLASSES.checked,
15
+ hover: PSEUDO_CLASSES.hover,
16
+ active: PSEUDO_CLASSES.active,
17
+ disabled: PSEUDO_CLASSES.disabled,
18
+ };
19
+ /**
20
+ * Returns the switch classes to apply to an element based on the given state.
21
+ *
22
+ * @param state The state of the switch.
23
+ * @return An object of class names and truthy values if they apply.
24
+ */
25
+ export function switchClasses({ checked = false, hover = false, active = false, disabled = false, } = {}) {
26
+ return {
27
+ ...rippleClasses(),
28
+ ...focusRingClasses(),
29
+ [SWITCH_CLASSES.switch]: true,
30
+ [SWITCH_CLASSES.checked]: checked,
31
+ [SWITCH_CLASSES.hover]: hover,
32
+ [SWITCH_CLASSES.active]: active,
33
+ [SWITCH_CLASSES.disabled]: disabled,
34
+ };
35
+ }
36
+ /**
37
+ * Sets up switch functionality for the given element.
38
+ *
39
+ * @param switchEl The element on which to set up switch functionality.
40
+ * @param opts Setup options, supports a cleanup `signal`.
41
+ */
42
+ export function setupSwitch(switchEl, opts) {
43
+ const isButton = switchEl.matches('button');
44
+ if (isButton) {
45
+ // Only setup dispatch hooks if we add a button click listener, but call it
46
+ // before setupRipple() adds its click listener.
47
+ setupDispatchHooks(switchEl, 'click');
48
+ }
49
+ setupRipple(switchEl, opts);
50
+ if (!isButton)
51
+ return;
52
+ // Support toggling <button role="switch" aria-checked="">
53
+ switchEl.addEventListener('click', (event) => {
54
+ if (isDisabled(switchEl))
55
+ return;
56
+ const wasChecked = switchEl.ariaChecked === 'true';
57
+ switchEl.ariaChecked = String(!wasChecked);
58
+ afterDispatch(event, () => {
59
+ if (event.defaultPrevented) {
60
+ switchEl.ariaChecked = String(wasChecked);
61
+ return;
62
+ }
63
+ // Mimic native browser input and change event behavior.
64
+ switchEl.dispatchEvent(new InputEvent('input', { bubbles: true, composed: true }));
65
+ switchEl.dispatchEvent(new Event('change', { bubbles: true }));
66
+ });
67
+ }, opts);
68
+ }
69
+ /**
70
+ * A Lit directive that adds switch styling and functionality to its element.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * html`
75
+ * <input role="switch" type="checkbox" class="${switchToggle()}">
76
+ *
77
+ * <button role="switch" aria-checked="false" class="${switchToggle()}"></button>
78
+ * `;
79
+ * ```
80
+ */
81
+ export const switchToggle = createClassMapDirective({
82
+ getClasses: switchClasses,
83
+ setupElement: setupSwitch,
84
+ });
85
+ //# sourceMappingURL=switch.js.map