@@ -18,11 +18,25 @@ import {
18
18
isActivationClick ,
19
19
redispatchEvent ,
20
20
} from '../../internal/controller/events.js' ;
21
+ import {
22
+ internals ,
23
+ mixinElementInternals ,
24
+ } from '../../labs/behaviors/element-internals.js' ;
25
+ import {
26
+ getFormState ,
27
+ getFormValue ,
28
+ mixinFormAssociated ,
29
+ } from '../../labs/behaviors/form-associated.js' ;
30
+
31
+ // Separate variable needed for closure.
32
+ const checkboxBaseClass = mixinFormAssociated (
33
+ mixinElementInternals ( LitElement ) ,
34
+ ) ;
21
35
22
36
/**
23
37
* A checkbox component.
24
38
*/
25
- export class Checkbox extends LitElement {
39
+ export class Checkbox extends checkboxBaseClass {
26
40
static {
27
41
requestUpdateOnAriaChange ( Checkbox ) ;
28
42
}
@@ -33,19 +47,11 @@ export class Checkbox extends LitElement {
33
47
delegatesFocus : true ,
34
48
} ;
35
49
36
- /** @nocollapse */
37
- static readonly formAssociated = true ;
38
-
39
50
/**
40
51
* Whether or not the checkbox is selected.
41
52
*/
42
53
@property ( { type : Boolean } ) checked = false ;
43
54
44
- /**
45
- * Whether or not the checkbox is disabled.
46
- */
47
- @property ( { type : Boolean , reflect : true } ) disabled = false ;
48
-
49
55
/**
50
56
* Whether or not the checkbox is indeterminate.
51
57
*
@@ -68,30 +74,6 @@ export class Checkbox extends LitElement {
68
74
*/
69
75
@property ( ) value = 'on' ;
70
76
71
- /**
72
- * The HTML name to use in form submission.
73
- */
74
- get name ( ) {
75
- return this . getAttribute ( 'name' ) ?? '' ;
76
- }
77
- set name ( name : string ) {
78
- this . setAttribute ( 'name' , name ) ;
79
- }
80
-
81
- /**
82
- * The associated form element with which this element's value will submit.
83
- */
84
- get form ( ) {
85
- return this . internals . form ;
86
- }
87
-
88
- /**
89
- * The labels this element is associated with.
90
- */
91
- get labels ( ) {
92
- return this . internals . labels ;
93
- }
94
-
95
77
/**
96
78
* Returns a ValidityState object that represents the validity states of the
97
79
* checkbox.
@@ -103,7 +85,7 @@ export class Checkbox extends LitElement {
103
85
*/
104
86
get validity ( ) {
105
87
this . syncValidity ( ) ;
106
- return this . internals . validity ;
88
+ return this [ internals ] . validity ;
107
89
}
108
90
109
91
/**
@@ -113,7 +95,7 @@ export class Checkbox extends LitElement {
113
95
*/
114
96
get validationMessage ( ) {
115
97
this . syncValidity ( ) ;
116
- return this . internals . validationMessage ;
98
+ return this [ internals ] . validationMessage ;
117
99
}
118
100
119
101
/**
@@ -124,18 +106,16 @@ export class Checkbox extends LitElement {
124
106
*/
125
107
get willValidate ( ) {
126
108
this . syncValidity ( ) ;
127
- return this . internals . willValidate ;
109
+ return this [ internals ] . willValidate ;
128
110
}
129
111
130
112
@state ( ) private prevChecked = false ;
131
113
@state ( ) private prevDisabled = false ;
132
114
@state ( ) private prevIndeterminate = false ;
133
115
@query ( 'input' ) private readonly input ! : HTMLInputElement | null ;
134
116
// Needed for Safari, see https://bugs.webkit.org/show_bug.cgi?id=261432
135
- // Replace with this. internals.validity.customError when resolved.
117
+ // Replace with this[ internals] .validity.customError when resolved.
136
118
private hasCustomValidityError = false ;
137
- // Cast needed for closure
138
- private readonly internals = ( this as HTMLElement ) . attachInternals ( ) ;
139
119
140
120
constructor ( ) {
141
121
super ( ) ;
@@ -162,7 +142,7 @@ export class Checkbox extends LitElement {
162
142
*/
163
143
checkValidity ( ) {
164
144
this . syncValidity ( ) ;
165
- return this . internals . checkValidity ( ) ;
145
+ return this [ internals ] . checkValidity ( ) ;
166
146
}
167
147
168
148
/**
@@ -180,7 +160,7 @@ export class Checkbox extends LitElement {
180
160
*/
181
161
reportValidity ( ) {
182
162
this . syncValidity ( ) ;
183
- return this . internals . reportValidity ( ) ;
163
+ return this [ internals ] . reportValidity ( ) ;
184
164
}
185
165
186
166
/**
@@ -196,7 +176,7 @@ export class Checkbox extends LitElement {
196
176
*/
197
177
setCustomValidity ( error : string ) {
198
178
this . hasCustomValidityError = ! ! error ;
199
- this . internals . setValidity ( { customError : ! ! error } , error , this . getInput ( ) ) ;
179
+ this [ internals ] . setValidity ( { customError : ! ! error } , error , this . getInput ( ) ) ;
200
180
}
201
181
202
182
protected override update ( changed : PropertyValues < Checkbox > ) {
@@ -211,9 +191,6 @@ export class Checkbox extends LitElement {
211
191
changed . get ( 'indeterminate' ) ?? this . indeterminate ;
212
192
}
213
193
214
- const shouldAddFormValue = this . checked && ! this . indeterminate ;
215
- const state = String ( this . checked ) ;
216
- this . internals . setFormValue ( shouldAddFormValue ? this . value : null , state ) ;
217
194
super . update ( changed ) ;
218
195
}
219
196
@@ -285,12 +262,12 @@ export class Checkbox extends LitElement {
285
262
// validity. We do this to re-use native `<input>` validation messages.
286
263
const input = this . getInput ( ) ;
287
264
if ( this . hasCustomValidityError ) {
288
- input . setCustomValidity ( this . internals . validationMessage ) ;
265
+ input . setCustomValidity ( this [ internals ] . validationMessage ) ;
289
266
} else {
290
267
input . setCustomValidity ( '' ) ;
291
268
}
292
269
293
- this . internals . setValidity (
270
+ this [ internals ] . setValidity (
294
271
input . validity ,
295
272
input . validationMessage ,
296
273
this . getInput ( ) ,
@@ -314,15 +291,29 @@ export class Checkbox extends LitElement {
314
291
return this . input ! ;
315
292
}
316
293
317
- /** @private */
318
- formResetCallback ( ) {
294
+ // Writable mixin properties for lit-html binding, needed for lit-analyzer
295
+ declare disabled : boolean ;
296
+ declare name : string ;
297
+
298
+ override [ getFormValue ] ( ) {
299
+ if ( ! this . checked || this . indeterminate ) {
300
+ return null ;
301
+ }
302
+
303
+ return this . value ;
304
+ }
305
+
306
+ override [ getFormState ] ( ) {
307
+ return String ( this . checked ) ;
308
+ }
309
+
310
+ override formResetCallback ( ) {
319
311
// The checked property does not reflect, so the original attribute set by
320
312
// the user is used to determine the default value.
321
313
this . checked = this . hasAttribute ( 'checked' ) ;
322
314
}
323
315
324
- /** @private */
325
- formStateRestoreCallback ( state : string ) {
316
+ override formStateRestoreCallback ( state : string ) {
326
317
this . checked = state === 'true' ;
327
318
}
328
319
}
0 commit comments