agnosticui-core 2.0.0-alpha.21 → 2.0.0-alpha.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Checkbox/core/_Checkbox.d.ts +6 -0
- package/dist/components/Checkbox/core/_Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/core/_Checkbox.js +44 -36
- package/dist/components/Combobox/core/_Combobox.d.ts +19 -0
- package/dist/components/Combobox/core/_Combobox.d.ts.map +1 -1
- package/dist/components/Combobox/core/_Combobox.js +154 -122
- package/dist/components/Combobox/vue/VueCombobox.vue.d.ts +1 -1
- package/dist/components/Dialog/core/_dialog.d.ts.map +1 -1
- package/dist/components/Dialog/core/_dialog.js +176 -166
- package/dist/components/Dialog/react/ReactDialog.d.ts +27 -8
- package/dist/components/Dialog/react/ReactDialog.d.ts.map +1 -1
- package/dist/components/Dialog/react/ReactDialog.js +32 -10
- package/dist/components/Input/core/_Input.d.ts +19 -0
- package/dist/components/Input/core/_Input.d.ts.map +1 -1
- package/dist/components/Input/core/_Input.js +34 -9
- package/dist/components/Radio/core/_Radio.d.ts +5 -0
- package/dist/components/Radio/core/_Radio.d.ts.map +1 -1
- package/dist/components/Radio/core/_Radio.js +38 -31
- package/dist/components/Rating/core/_Rating.d.ts +18 -0
- package/dist/components/Rating/core/_Rating.d.ts.map +1 -1
- package/dist/components/Rating/core/_Rating.js +90 -68
- package/dist/components/Select/core/_Select.d.ts +19 -0
- package/dist/components/Select/core/_Select.d.ts.map +1 -1
- package/dist/components/Select/core/_Select.js +102 -65
- package/dist/components/SelectionButtonGroup/core/_SelectionButtonGroup.d.ts +18 -0
- package/dist/components/SelectionButtonGroup/core/_SelectionButtonGroup.d.ts.map +1 -1
- package/dist/components/SelectionButtonGroup/core/_SelectionButtonGroup.js +54 -32
- package/dist/components/SelectionCardGroup/core/_SelectionCardGroup.d.ts +18 -0
- package/dist/components/SelectionCardGroup/core/_SelectionCardGroup.d.ts.map +1 -1
- package/dist/components/SelectionCardGroup/core/_SelectionCardGroup.js +61 -39
- package/dist/components/Slider/core/_Slider.d.ts +20 -0
- package/dist/components/Slider/core/_Slider.d.ts.map +1 -1
- package/dist/components/Slider/core/_Slider.js +132 -104
- package/dist/components/Toggle/core/_Toggle.d.ts +6 -0
- package/dist/components/Toggle/core/_Toggle.d.ts.map +1 -1
- package/dist/components/Toggle/core/_Toggle.js +94 -86
- package/dist/shared/face-mixin.d.ts +5 -0
- package/dist/shared/face-mixin.d.ts.map +1 -1
- package/dist/shared/face-mixin.js +39 -25
- package/package.json +1 -1
- package/src/components/Checkbox/core/_Checkbox.ts +16 -0
- package/src/components/Combobox/core/_Combobox.ts +53 -0
- package/src/components/Dialog/core/_dialog.ts +19 -2
- package/src/components/Dialog/react/ReactDialog.tsx +60 -3
- package/src/components/Input/core/_Input.ts +47 -0
- package/src/components/Radio/core/_Radio.ts +14 -0
- package/src/components/Rating/core/_Rating.ts +42 -0
- package/src/components/Select/core/_Select.ts +57 -0
- package/src/components/SelectionButtonGroup/core/_SelectionButtonGroup.ts +48 -0
- package/src/components/SelectionCardGroup/core/_SelectionCardGroup.ts +48 -0
- package/src/components/Slider/core/_Slider.ts +53 -0
- package/src/components/Toggle/core/_Toggle.ts +15 -0
- package/src/shared/face-mixin.ts +48 -6
|
@@ -496,6 +496,40 @@ export class AgInput extends FaceMixin(LitElement) implements InputProps {
|
|
|
496
496
|
this.value = '';
|
|
497
497
|
this._internals.setFormValue('');
|
|
498
498
|
this._internals.setValidity({});
|
|
499
|
+
this._syncStates();
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* FACE lifecycle: called on session restore or browser autofill.
|
|
504
|
+
* Restores the input value from the previously saved form state.
|
|
505
|
+
*/
|
|
506
|
+
override formStateRestoreCallback(
|
|
507
|
+
state: File | string | FormData | null,
|
|
508
|
+
_mode: 'restore' | 'autocomplete'
|
|
509
|
+
): void {
|
|
510
|
+
this.value = typeof state === 'string' ? state : '';
|
|
511
|
+
this._internals.setFormValue(this.value);
|
|
512
|
+
this._syncValidity();
|
|
513
|
+
this._syncStates();
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Sync CustomStateSet states so :state() pseudo-classes work from external CSS.
|
|
518
|
+
*
|
|
519
|
+
* Must be called AFTER _syncValidity() so that :state(invalid) reads the
|
|
520
|
+
* freshly-updated _internals.validity.valid value.
|
|
521
|
+
*
|
|
522
|
+
* Exposed states:
|
|
523
|
+
* :state(disabled) — input is disabled
|
|
524
|
+
* :state(readonly) — input is read-only
|
|
525
|
+
* :state(required) — input is required
|
|
526
|
+
* :state(invalid) — FACE constraint validation is failing
|
|
527
|
+
*/
|
|
528
|
+
private _syncStates(): void {
|
|
529
|
+
this._setState('disabled', this.disabled);
|
|
530
|
+
this._setState('readonly', this.readonly);
|
|
531
|
+
this._setState('required', this.required);
|
|
532
|
+
this._setState('invalid', !this._internals.validity.valid);
|
|
499
533
|
}
|
|
500
534
|
|
|
501
535
|
/**
|
|
@@ -678,10 +712,23 @@ export class AgInput extends FaceMixin(LitElement) implements InputProps {
|
|
|
678
712
|
`;
|
|
679
713
|
}
|
|
680
714
|
|
|
715
|
+
override updated(changedProperties: Map<string, unknown>) {
|
|
716
|
+
super.updated(changedProperties);
|
|
717
|
+
if (
|
|
718
|
+
changedProperties.has('disabled') ||
|
|
719
|
+
changedProperties.has('readonly') ||
|
|
720
|
+
changedProperties.has('required') ||
|
|
721
|
+
changedProperties.has('invalid')
|
|
722
|
+
) {
|
|
723
|
+
this._syncStates();
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
681
727
|
override firstUpdated() {
|
|
682
728
|
// FACE: set initial form value and sync validity after first render
|
|
683
729
|
this._internals.setFormValue(this.value ?? '');
|
|
684
730
|
this._syncValidity();
|
|
731
|
+
this._syncStates();
|
|
685
732
|
|
|
686
733
|
// Initial check for slot content
|
|
687
734
|
setTimeout(() => {
|
|
@@ -405,6 +405,20 @@ export class AgRadio extends FaceMixin(LitElement) implements RadioProps {
|
|
|
405
405
|
this._syncStates();
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
+
/**
|
|
409
|
+
* FACE lifecycle: called on session restore or browser autofill.
|
|
410
|
+
* Restores checked state: checked when the saved state matches this radio's value.
|
|
411
|
+
*/
|
|
412
|
+
override formStateRestoreCallback(
|
|
413
|
+
state: File | string | FormData | null,
|
|
414
|
+
_mode: 'restore' | 'autocomplete'
|
|
415
|
+
): void {
|
|
416
|
+
this.checked = state === this.value;
|
|
417
|
+
this._syncFormValue();
|
|
418
|
+
this._syncValidity();
|
|
419
|
+
this._syncStates();
|
|
420
|
+
}
|
|
421
|
+
|
|
408
422
|
/**
|
|
409
423
|
* Sync CustomStateSet states so :state() pseudo-classes work from external CSS.
|
|
410
424
|
*
|
|
@@ -184,6 +184,7 @@ export class AgRating extends FaceMixin(LitElement) {
|
|
|
184
184
|
override firstUpdated() {
|
|
185
185
|
this._syncFormValue();
|
|
186
186
|
this._syncValidity();
|
|
187
|
+
this._syncStates();
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
override updated(changedProperties: Map<string, unknown>) {
|
|
@@ -192,6 +193,14 @@ export class AgRating extends FaceMixin(LitElement) {
|
|
|
192
193
|
this._syncFormValue();
|
|
193
194
|
this._syncValidity();
|
|
194
195
|
}
|
|
196
|
+
if (
|
|
197
|
+
changedProperties.has('value') ||
|
|
198
|
+
changedProperties.has('readonly') ||
|
|
199
|
+
changedProperties.has('required') ||
|
|
200
|
+
changedProperties.has('invalid')
|
|
201
|
+
) {
|
|
202
|
+
this._syncStates();
|
|
203
|
+
}
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
/**
|
|
@@ -202,6 +211,39 @@ export class AgRating extends FaceMixin(LitElement) {
|
|
|
202
211
|
this.value = 0;
|
|
203
212
|
this._internals.setFormValue(null);
|
|
204
213
|
this._internals.setValidity({});
|
|
214
|
+
this._syncStates();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* FACE lifecycle: called on session restore or browser autofill.
|
|
219
|
+
* Restores the rating value from the previously saved form state.
|
|
220
|
+
* The state is a numeric string (e.g. "3" or "3.5"), or null for no rating.
|
|
221
|
+
*/
|
|
222
|
+
override formStateRestoreCallback(
|
|
223
|
+
state: File | string | FormData | null,
|
|
224
|
+
_mode: 'restore' | 'autocomplete'
|
|
225
|
+
): void {
|
|
226
|
+
this.value = typeof state === 'string' ? parseFloat(state) : 0;
|
|
227
|
+
this._syncFormValue();
|
|
228
|
+
this._syncValidity();
|
|
229
|
+
this._syncStates();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Sync CustomStateSet states so :state() pseudo-classes work from external CSS.
|
|
234
|
+
*
|
|
235
|
+
* Must be called AFTER _syncValidity() so that :state(invalid) reads the
|
|
236
|
+
* freshly-updated _internals.validity.valid value.
|
|
237
|
+
*
|
|
238
|
+
* Exposed states:
|
|
239
|
+
* :state(readonly) — rating is read-only
|
|
240
|
+
* :state(required) — rating is required
|
|
241
|
+
* :state(invalid) — FACE constraint validation is failing
|
|
242
|
+
*/
|
|
243
|
+
private _syncStates(): void {
|
|
244
|
+
this._setState('readonly', this.readonly);
|
|
245
|
+
this._setState('required', this.required);
|
|
246
|
+
this._setState('invalid', !this._internals.validity.valid);
|
|
205
247
|
}
|
|
206
248
|
|
|
207
249
|
// ─── End FACE ─────────────────────────────────────────────────────────────
|
|
@@ -114,6 +114,51 @@ export class Select extends FaceMixin(LitElement) implements SelectProps {
|
|
|
114
114
|
}
|
|
115
115
|
this._syncFormValue();
|
|
116
116
|
this._internals.setValidity({});
|
|
117
|
+
this._syncStates();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* FACE lifecycle: called on session restore or browser autofill.
|
|
122
|
+
* Restores the selected option(s) from the previously saved form state.
|
|
123
|
+
* Uses updateComplete to ensure options are in the DOM before restoring.
|
|
124
|
+
*/
|
|
125
|
+
override formStateRestoreCallback(
|
|
126
|
+
state: File | string | FormData | null,
|
|
127
|
+
_mode: 'restore' | 'autocomplete'
|
|
128
|
+
): void {
|
|
129
|
+
this.updateComplete.then(() => {
|
|
130
|
+
if (!this.selectElement) return;
|
|
131
|
+
if (this.multiple && state instanceof FormData) {
|
|
132
|
+
const restored = new Set(Array.from(state.values()) as string[]);
|
|
133
|
+
Array.from(this.selectElement.options).forEach(opt => {
|
|
134
|
+
opt.selected = restored.has(opt.value);
|
|
135
|
+
});
|
|
136
|
+
} else if (typeof state === 'string') {
|
|
137
|
+
Array.from(this.selectElement.options).forEach(opt => {
|
|
138
|
+
opt.selected = opt.value === state;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
this._syncFormValue();
|
|
142
|
+
this._syncValidity();
|
|
143
|
+
this._syncStates();
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Sync CustomStateSet states so :state() pseudo-classes work from external CSS.
|
|
149
|
+
*
|
|
150
|
+
* Must be called AFTER _syncValidity() so that :state(invalid) reads the
|
|
151
|
+
* freshly-updated _internals.validity.valid value.
|
|
152
|
+
*
|
|
153
|
+
* Exposed states:
|
|
154
|
+
* :state(disabled) — select is disabled
|
|
155
|
+
* :state(required) — select is required
|
|
156
|
+
* :state(invalid) — FACE constraint validation is failing
|
|
157
|
+
*/
|
|
158
|
+
private _syncStates(): void {
|
|
159
|
+
this._setState('disabled', this.disabled);
|
|
160
|
+
this._setState('required', this.required);
|
|
161
|
+
this._setState('invalid', !this._internals.validity.valid);
|
|
117
162
|
}
|
|
118
163
|
|
|
119
164
|
/**
|
|
@@ -144,6 +189,17 @@ export class Select extends FaceMixin(LitElement) implements SelectProps {
|
|
|
144
189
|
|
|
145
190
|
// ─── End FACE ─────────────────────────────────────────────────────────────
|
|
146
191
|
|
|
192
|
+
override updated(changedProperties: Map<string, unknown>) {
|
|
193
|
+
super.updated(changedProperties);
|
|
194
|
+
if (
|
|
195
|
+
changedProperties.has('disabled') ||
|
|
196
|
+
changedProperties.has('required') ||
|
|
197
|
+
changedProperties.has('invalid')
|
|
198
|
+
) {
|
|
199
|
+
this._syncStates();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
147
203
|
protected firstUpdated() {
|
|
148
204
|
// Ensure options are moved after first render
|
|
149
205
|
this.handleSlotChange();
|
|
@@ -157,6 +213,7 @@ export class Select extends FaceMixin(LitElement) implements SelectProps {
|
|
|
157
213
|
// FACE: set initial form value and sync validity after options are in place
|
|
158
214
|
this._syncFormValue();
|
|
159
215
|
this._syncValidity();
|
|
216
|
+
this._syncStates();
|
|
160
217
|
}
|
|
161
218
|
|
|
162
219
|
private handleSlotChange() {
|
|
@@ -215,6 +215,46 @@ export class AgSelectionButtonGroup extends FaceMixin(LitElement) implements Sel
|
|
|
215
215
|
this._internals.setFormValue(null);
|
|
216
216
|
this._syncValidity();
|
|
217
217
|
this._syncChildButtons();
|
|
218
|
+
this._syncStates();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* FACE lifecycle: called on session restore or browser autofill.
|
|
223
|
+
* Restores selected value(s) from the previously saved form state.
|
|
224
|
+
* Radio mode: state is a single string. Checkbox mode: state is FormData.
|
|
225
|
+
*/
|
|
226
|
+
override formStateRestoreCallback(
|
|
227
|
+
state: File | string | FormData | null,
|
|
228
|
+
_mode: 'restore' | 'autocomplete'
|
|
229
|
+
): void {
|
|
230
|
+
if (state === null) {
|
|
231
|
+
this._internalSelectedValues = [];
|
|
232
|
+
} else if (state instanceof FormData) {
|
|
233
|
+
this._internalSelectedValues = Array.from(state.getAll(this.name)) as string[];
|
|
234
|
+
} else if (typeof state === 'string') {
|
|
235
|
+
this._internalSelectedValues = [state];
|
|
236
|
+
}
|
|
237
|
+
this._syncFormValue();
|
|
238
|
+
this._syncValidity();
|
|
239
|
+
this._syncChildButtons();
|
|
240
|
+
this._syncStates();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Sync CustomStateSet states so :state() pseudo-classes work from external CSS.
|
|
245
|
+
*
|
|
246
|
+
* Must be called AFTER _syncValidity() so that :state(invalid) reads the
|
|
247
|
+
* freshly-updated _internals.validity.valid value.
|
|
248
|
+
*
|
|
249
|
+
* Exposed states:
|
|
250
|
+
* :state(disabled) — group is disabled
|
|
251
|
+
* :state(required) — group is required
|
|
252
|
+
* :state(invalid) — FACE constraint validation is failing
|
|
253
|
+
*/
|
|
254
|
+
private _syncStates(): void {
|
|
255
|
+
this._setState('disabled', this.disabled);
|
|
256
|
+
this._setState('required', this.required);
|
|
257
|
+
this._setState('invalid', !this._internals.validity.valid);
|
|
218
258
|
}
|
|
219
259
|
|
|
220
260
|
// ─── End FACE ─────────────────────────────────────────────────────────────
|
|
@@ -260,12 +300,20 @@ export class AgSelectionButtonGroup extends FaceMixin(LitElement) implements Sel
|
|
|
260
300
|
} else if (changedProperties.has('required')) {
|
|
261
301
|
this._syncValidity();
|
|
262
302
|
}
|
|
303
|
+
if (
|
|
304
|
+
changedProperties.has('disabled') ||
|
|
305
|
+
changedProperties.has('required') ||
|
|
306
|
+
changedProperties.has('_internalSelectedValues')
|
|
307
|
+
) {
|
|
308
|
+
this._syncStates();
|
|
309
|
+
}
|
|
263
310
|
}
|
|
264
311
|
|
|
265
312
|
override firstUpdated() {
|
|
266
313
|
this._syncChildButtons();
|
|
267
314
|
this._syncFormValue();
|
|
268
315
|
this._syncValidity();
|
|
316
|
+
this._syncStates();
|
|
269
317
|
}
|
|
270
318
|
|
|
271
319
|
private _getButtons(): AgSelectionButton[] {
|
|
@@ -192,6 +192,46 @@ export class AgSelectionCardGroup extends FaceMixin(LitElement) implements Selec
|
|
|
192
192
|
this._internals.setFormValue(null);
|
|
193
193
|
this._syncValidity();
|
|
194
194
|
this._syncChildCards();
|
|
195
|
+
this._syncStates();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* FACE lifecycle: called on session restore or browser autofill.
|
|
200
|
+
* Restores selected value(s) from the previously saved form state.
|
|
201
|
+
* Radio mode: state is a single string. Checkbox mode: state is FormData.
|
|
202
|
+
*/
|
|
203
|
+
override formStateRestoreCallback(
|
|
204
|
+
state: File | string | FormData | null,
|
|
205
|
+
_mode: 'restore' | 'autocomplete'
|
|
206
|
+
): void {
|
|
207
|
+
if (state === null) {
|
|
208
|
+
this._internalSelectedValues = [];
|
|
209
|
+
} else if (state instanceof FormData) {
|
|
210
|
+
this._internalSelectedValues = Array.from(state.getAll(this.name)) as string[];
|
|
211
|
+
} else if (typeof state === 'string') {
|
|
212
|
+
this._internalSelectedValues = [state];
|
|
213
|
+
}
|
|
214
|
+
this._syncFormValue();
|
|
215
|
+
this._syncValidity();
|
|
216
|
+
this._syncChildCards();
|
|
217
|
+
this._syncStates();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Sync CustomStateSet states so :state() pseudo-classes work from external CSS.
|
|
222
|
+
*
|
|
223
|
+
* Must be called AFTER _syncValidity() so that :state(invalid) reads the
|
|
224
|
+
* freshly-updated _internals.validity.valid value.
|
|
225
|
+
*
|
|
226
|
+
* Exposed states:
|
|
227
|
+
* :state(disabled) — group is disabled
|
|
228
|
+
* :state(required) — group is required
|
|
229
|
+
* :state(invalid) — FACE constraint validation is failing
|
|
230
|
+
*/
|
|
231
|
+
private _syncStates(): void {
|
|
232
|
+
this._setState('disabled', this.disabled);
|
|
233
|
+
this._setState('required', this.required);
|
|
234
|
+
this._setState('invalid', !this._internals.validity.valid);
|
|
195
235
|
}
|
|
196
236
|
|
|
197
237
|
// ─── End FACE ─────────────────────────────────────────────────────────────
|
|
@@ -235,12 +275,20 @@ export class AgSelectionCardGroup extends FaceMixin(LitElement) implements Selec
|
|
|
235
275
|
} else if (changedProperties.has('required')) {
|
|
236
276
|
this._syncValidity();
|
|
237
277
|
}
|
|
278
|
+
if (
|
|
279
|
+
changedProperties.has('disabled') ||
|
|
280
|
+
changedProperties.has('required') ||
|
|
281
|
+
changedProperties.has('_internalSelectedValues')
|
|
282
|
+
) {
|
|
283
|
+
this._syncStates();
|
|
284
|
+
}
|
|
238
285
|
}
|
|
239
286
|
|
|
240
287
|
override firstUpdated() {
|
|
241
288
|
this._syncChildCards();
|
|
242
289
|
this._syncFormValue();
|
|
243
290
|
this._syncValidity();
|
|
291
|
+
this._syncStates();
|
|
244
292
|
}
|
|
245
293
|
|
|
246
294
|
private _getCards(): AgSelectionCard[] {
|
|
@@ -671,12 +671,25 @@ export class AgSlider extends FaceMixin(LitElement) implements SliderProps {
|
|
|
671
671
|
|
|
672
672
|
// ─── FACE ─────────────────────────────────────────────────────────────────
|
|
673
673
|
|
|
674
|
+
override updated(changedProperties: Map<string, unknown>) {
|
|
675
|
+
super.updated(changedProperties);
|
|
676
|
+
if (
|
|
677
|
+
changedProperties.has('disabled') ||
|
|
678
|
+
changedProperties.has('readonly') ||
|
|
679
|
+
changedProperties.has('required') ||
|
|
680
|
+
changedProperties.has('invalid')
|
|
681
|
+
) {
|
|
682
|
+
this._syncStates();
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
674
686
|
override firstUpdated() {
|
|
675
687
|
// Capture default value for formResetCallback, then set initial form value
|
|
676
688
|
this._defaultValue = Array.isArray(this.value)
|
|
677
689
|
? ([...this.value] as [number, number])
|
|
678
690
|
: this.value;
|
|
679
691
|
this._updateFormValue();
|
|
692
|
+
this._syncStates();
|
|
680
693
|
}
|
|
681
694
|
|
|
682
695
|
/**
|
|
@@ -688,6 +701,46 @@ export class AgSlider extends FaceMixin(LitElement) implements SliderProps {
|
|
|
688
701
|
? ([...this._defaultValue] as [number, number])
|
|
689
702
|
: this._defaultValue;
|
|
690
703
|
this._updateFormValue();
|
|
704
|
+
this._syncStates();
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* FACE lifecycle: called on session restore or browser autofill.
|
|
709
|
+
* Restores the slider value from the previously saved FormData.
|
|
710
|
+
* Single mode: one entry (name, valueStr). Dual mode: two entries.
|
|
711
|
+
*/
|
|
712
|
+
override formStateRestoreCallback(
|
|
713
|
+
state: File | string | FormData | null,
|
|
714
|
+
_mode: 'restore' | 'autocomplete'
|
|
715
|
+
): void {
|
|
716
|
+
if (!(state instanceof FormData) || !this.name) return;
|
|
717
|
+
const entries = Array.from(state.getAll(this.name)) as string[];
|
|
718
|
+
if (this.dual && entries.length === 2) {
|
|
719
|
+
this.value = [parseFloat(entries[0]), parseFloat(entries[1])];
|
|
720
|
+
} else if (entries.length === 1) {
|
|
721
|
+
this.value = parseFloat(entries[0]);
|
|
722
|
+
}
|
|
723
|
+
this._updateFormValue();
|
|
724
|
+
this._syncStates();
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Sync CustomStateSet states so :state() pseudo-classes work from external CSS.
|
|
729
|
+
*
|
|
730
|
+
* Must be called AFTER _updateFormValue() (which also calls setValidity) so
|
|
731
|
+
* that :state(invalid) reads the freshly-updated _internals.validity.valid value.
|
|
732
|
+
*
|
|
733
|
+
* Exposed states:
|
|
734
|
+
* :state(disabled) — slider is disabled
|
|
735
|
+
* :state(readonly) — slider is read-only
|
|
736
|
+
* :state(required) — slider is required
|
|
737
|
+
* :state(invalid) — FACE constraint validation is failing
|
|
738
|
+
*/
|
|
739
|
+
private _syncStates(): void {
|
|
740
|
+
this._setState('disabled', this.disabled);
|
|
741
|
+
this._setState('readonly', this.readonly);
|
|
742
|
+
this._setState('required', this.required);
|
|
743
|
+
this._setState('invalid', !this._internals.validity.valid);
|
|
691
744
|
}
|
|
692
745
|
|
|
693
746
|
// ─── End FACE ─────────────────────────────────────────────────────────────
|
|
@@ -396,6 +396,21 @@ export class AgToggle extends FaceMixin(LitElement) implements ToggleProps {
|
|
|
396
396
|
this._syncStates();
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
+
/**
|
|
400
|
+
* FACE lifecycle: called on session restore or browser autofill.
|
|
401
|
+
* Restores checked state from the previously saved form value.
|
|
402
|
+
* A non-null state means the toggle was on; null means it was off.
|
|
403
|
+
*/
|
|
404
|
+
override formStateRestoreCallback(
|
|
405
|
+
state: File | string | FormData | null,
|
|
406
|
+
_mode: 'restore' | 'autocomplete'
|
|
407
|
+
): void {
|
|
408
|
+
this.checked = state !== null;
|
|
409
|
+
this._internals.setFormValue(this.checked ? (this.value || 'on') : null);
|
|
410
|
+
this._syncValidity();
|
|
411
|
+
this._syncStates();
|
|
412
|
+
}
|
|
413
|
+
|
|
399
414
|
/**
|
|
400
415
|
* Sync validity state to ElementInternals.
|
|
401
416
|
* Toggle has no inner <input> to delegate to, so required validation
|
package/src/shared/face-mixin.ts
CHANGED
|
@@ -106,6 +106,11 @@ export declare class FaceMixinInterface {
|
|
|
106
106
|
formDisabledCallback(disabled: boolean): void;
|
|
107
107
|
/** FACE lifecycle — called on form reset; subclasses should override */
|
|
108
108
|
formResetCallback(): void;
|
|
109
|
+
/**
|
|
110
|
+
* FACE lifecycle — called when the browser restores session state or autofills.
|
|
111
|
+
* Subclasses should override to restore their own state from the saved value.
|
|
112
|
+
*/
|
|
113
|
+
formStateRestoreCallback(state: File | string | FormData | null, mode: 'restore' | 'autocomplete'): void;
|
|
109
114
|
/**
|
|
110
115
|
* Toggle a custom state in ElementInternals.states (CustomStateSet).
|
|
111
116
|
* Enables :state() pseudo-class targeting from external CSS.
|
|
@@ -135,6 +140,16 @@ export const FaceMixin = <T extends Constructor<LitElement>>(superClass: T) => {
|
|
|
135
140
|
*/
|
|
136
141
|
protected _internals!: ElementInternals;
|
|
137
142
|
|
|
143
|
+
/**
|
|
144
|
+
* The disabled state the user set on this element itself (via attribute or property),
|
|
145
|
+
* captured before a <fieldset disabled> ancestor overwrites it.
|
|
146
|
+
* Restored when the fieldset is re-enabled so the two sources don't stomp each other.
|
|
147
|
+
*/
|
|
148
|
+
private _ownDisabled = false;
|
|
149
|
+
|
|
150
|
+
/** True while a <fieldset disabled> ancestor is disabling this element. */
|
|
151
|
+
private _parentDisabled = false;
|
|
152
|
+
|
|
138
153
|
/**
|
|
139
154
|
* The name under which this control's value is submitted with the parent form.
|
|
140
155
|
* Mirrors the standard `name` attribute on native form controls.
|
|
@@ -182,14 +197,21 @@ export const FaceMixin = <T extends Constructor<LitElement>>(superClass: T) => {
|
|
|
182
197
|
|
|
183
198
|
/**
|
|
184
199
|
* FACE lifecycle: called when a <fieldset disabled> ancestor is toggled.
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* for the element's own `disabled` attribute — both paths must be handled.
|
|
200
|
+
* Separates parent-disabled state from the element's own `disabled` attribute
|
|
201
|
+
* so re-enabling a fieldset does not accidentally re-enable an intentionally
|
|
202
|
+
* disabled control.
|
|
189
203
|
*/
|
|
190
204
|
formDisabledCallback(disabled: boolean): void {
|
|
191
|
-
|
|
192
|
-
|
|
205
|
+
if (disabled) {
|
|
206
|
+
// Save the user's own disabled state before the fieldset takes over.
|
|
207
|
+
this._ownDisabled = (this as unknown as { disabled: boolean }).disabled;
|
|
208
|
+
this._parentDisabled = true;
|
|
209
|
+
(this as unknown as { disabled: boolean }).disabled = true;
|
|
210
|
+
} else {
|
|
211
|
+
this._parentDisabled = false;
|
|
212
|
+
// Restore only the user-set state — do not blindly set false.
|
|
213
|
+
(this as unknown as { disabled: boolean }).disabled = this._ownDisabled;
|
|
214
|
+
}
|
|
193
215
|
}
|
|
194
216
|
|
|
195
217
|
/**
|
|
@@ -201,6 +223,26 @@ export const FaceMixin = <T extends Constructor<LitElement>>(superClass: T) => {
|
|
|
201
223
|
// no-op default — override in subclass
|
|
202
224
|
}
|
|
203
225
|
|
|
226
|
+
/**
|
|
227
|
+
* FACE lifecycle: called when the browser restores form state from session history
|
|
228
|
+
* (back/forward navigation) or when the browser autofills the field.
|
|
229
|
+
*
|
|
230
|
+
* `state` is the value that was previously passed to setFormValue():
|
|
231
|
+
* - a string for single-value controls
|
|
232
|
+
* - a FormData for multi-value controls (multi-select, checkbox groups)
|
|
233
|
+
* - null if the control had no value
|
|
234
|
+
*
|
|
235
|
+
* `mode` is 'restore' for session-history restores and 'autocomplete' for autofill.
|
|
236
|
+
*
|
|
237
|
+
* Default is a no-op. Subclasses should override to restore their own state.
|
|
238
|
+
*/
|
|
239
|
+
formStateRestoreCallback(
|
|
240
|
+
_state: File | string | FormData | null,
|
|
241
|
+
_mode: 'restore' | 'autocomplete'
|
|
242
|
+
): void {
|
|
243
|
+
// no-op default — override in subclass
|
|
244
|
+
}
|
|
245
|
+
|
|
204
246
|
/**
|
|
205
247
|
* Toggle a custom state in ElementInternals.states (CustomStateSet).
|
|
206
248
|
*
|