@lmvz-ds/components 0.36.0 → 0.36.1
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/CHANGELOG.md +8 -0
- package/cjs/aria.constants-DPK5mQEL.js +65 -0
- package/cjs/{stencil.util-TjS8_DoU.js → async.util-Dnl6c82X.js} +1 -13
- package/cjs/{directional-focus-controller-3uDoin45.js → directional-focus-controller-8Xd_7MHT.js} +1 -1
- package/cjs/{element-activation-controller-BWtUKzu2.js → element-activation-controller-DzTUocEO.js} +1 -1
- package/cjs/{element.util-CctmBvUY.js → element.util-BlhcwmfR.js} +2 -62
- package/cjs/lmvz-action-list.cjs.entry.js +3 -2
- package/cjs/lmvz-button-group.cjs.entry.js +2 -1
- package/cjs/lmvz-button_2.cjs.entry.js +3 -2
- package/cjs/lmvz-checkbox.cjs.entry.js +38 -4
- package/cjs/lmvz-components.cjs.js +1 -1
- package/cjs/lmvz-datepicker.cjs.entry.js +10 -3
- package/cjs/lmvz-header_2.cjs.entry.js +4 -3
- package/cjs/lmvz-input.cjs.entry.js +242 -0
- package/cjs/lmvz-menuitem.cjs.entry.js +3 -2
- package/cjs/lmvz-modal.cjs.entry.js +2 -1
- package/cjs/{lmvz-input_2.cjs.entry.js → lmvz-popover.cjs.entry.js} +24 -228
- package/cjs/lmvz-radio.cjs.entry.js +61 -3
- package/cjs/lmvz-select.cjs.entry.js +423 -16
- package/cjs/lmvz-snackbar.cjs.entry.js +1 -1
- package/cjs/lmvz-spinner.cjs.entry.js +1 -1
- package/cjs/lmvz-tab.cjs.entry.js +1 -1
- package/cjs/lmvz-tabs.cjs.entry.js +4 -3
- package/cjs/lmvz-toggle.cjs.entry.js +7 -3
- package/cjs/loader.cjs.js +1 -1
- package/cjs/stencil.util-CBrPLd-F.js +17 -0
- package/collection/components/lmvz-checkbox/lmvz-checkbox.css +4 -2
- package/collection/components/lmvz-checkbox/lmvz-checkbox.js +68 -8
- package/collection/components/lmvz-datepicker/lmvz-datepicker.css +0 -5
- package/collection/components/lmvz-datepicker/lmvz-datepicker.js +17 -3
- package/collection/components/lmvz-input/lmvz-input.css +1 -1
- package/collection/components/lmvz-input/lmvz-input.js +47 -12
- package/collection/components/lmvz-popover/lmvz-popover.css +1 -1
- package/collection/components/lmvz-popover/lmvz-popover.js +45 -5
- package/collection/components/lmvz-radio/lmvz-radio.js +77 -9
- package/collection/components/lmvz-select/lmvz-select.css +96 -34
- package/collection/components/lmvz-select/lmvz-select.js +412 -21
- package/collection/components/lmvz-snackbar/lmvz-snackbar.js +1 -1
- package/collection/components/lmvz-spinner/lmvz-spinner.js +1 -1
- package/collection/components/lmvz-tab/lmvz-tab.js +1 -1
- package/collection/components/lmvz-tabs/lmvz-tabs.js +1 -1
- package/collection/components/lmvz-toggle/lmvz-toggle.js +21 -1
- package/collection/integration/header-integration/header-integration.js +1 -1
- package/collection/styles/fragments/_focus-within.css +2 -2
- package/collection/utils/aria/listbox-controller.js +154 -0
- package/collection/utils/radio/radio-group-controller.js +17 -0
- package/components/lmvz-checkbox.js +1 -1
- package/components/lmvz-datepicker.js +1 -1
- package/components/lmvz-input.js +1 -1
- package/components/lmvz-popover.js +1 -1
- package/components/lmvz-radio.js +1 -1
- package/components/lmvz-select.js +1 -1
- package/components/lmvz-snackbar.js +1 -1
- package/components/lmvz-spinner.js +1 -1
- package/components/lmvz-tab.js +1 -1
- package/components/lmvz-tabs.js +1 -1
- package/components/lmvz-toggle.js +1 -1
- package/components/p-BApwCp0R.js +1 -0
- package/components/p-C5gRiLRR.js +1 -0
- package/esm/aria.constants-DIyiticz.js +62 -0
- package/esm/{stencil.util-C3QOYC8E.js → async.util-DZj20TV1.js} +1 -13
- package/esm/{directional-focus-controller-Bhu7RqYE.js → directional-focus-controller-QukTTWBE.js} +1 -1
- package/esm/{element-activation-controller-BuwyVq4A.js → element-activation-controller-dxJZKMag.js} +1 -1
- package/esm/{element.util-Bd9JyKJZ.js → element.util-3ydVsxUW.js} +2 -61
- package/esm/lmvz-action-list.entry.js +3 -2
- package/esm/lmvz-button-group.entry.js +2 -1
- package/esm/lmvz-button_2.entry.js +3 -2
- package/esm/lmvz-checkbox.entry.js +38 -4
- package/esm/lmvz-components.js +1 -1
- package/esm/lmvz-datepicker.entry.js +10 -3
- package/esm/lmvz-header_2.entry.js +4 -3
- package/esm/lmvz-input.entry.js +240 -0
- package/esm/lmvz-menuitem.entry.js +3 -2
- package/esm/lmvz-modal.entry.js +2 -1
- package/esm/{lmvz-input_2.entry.js → lmvz-popover.entry.js} +23 -226
- package/esm/lmvz-radio.entry.js +61 -3
- package/esm/lmvz-select.entry.js +423 -16
- package/esm/lmvz-snackbar.entry.js +1 -1
- package/esm/lmvz-spinner.entry.js +1 -1
- package/esm/lmvz-tab.entry.js +1 -1
- package/esm/lmvz-tabs.entry.js +4 -3
- package/esm/lmvz-toggle.entry.js +7 -3
- package/esm/loader.js +1 -1
- package/esm/stencil.util-D2-5rsN3.js +15 -0
- package/hydrate/index.js +625 -68
- package/hydrate/index.mjs +625 -68
- package/lmvz-components/lmvz-components.esm.js +1 -1
- package/lmvz-components/{p-544e3ccb.entry.js → p-0f65d001.entry.js} +1 -1
- package/lmvz-components/p-137b1fe1.entry.js +1 -0
- package/lmvz-components/p-26dd9684.entry.js +1 -0
- package/lmvz-components/p-36f44108.entry.js +1 -0
- package/lmvz-components/p-398b5cf4.entry.js +1 -0
- package/lmvz-components/p-3a396fc8.entry.js +1 -0
- package/lmvz-components/p-40716828.entry.js +1 -0
- package/lmvz-components/p-70f1e31a.entry.js +1 -0
- package/lmvz-components/p-71d06d1d.entry.js +1 -0
- package/lmvz-components/{p-d280d21a.entry.js → p-88661c50.entry.js} +1 -1
- package/lmvz-components/p-91eb71bb.entry.js +1 -0
- package/lmvz-components/p-BA3wizqg.js +1 -0
- package/lmvz-components/{p-GGkwaiT6.js → p-CHxiS3ja.js} +1 -1
- package/lmvz-components/{p-UhNgD4L3.js → p-CPSyM_e-.js} +1 -1
- package/lmvz-components/p-DIyiticz.js +1 -0
- package/lmvz-components/p-DZj20TV1.js +1 -0
- package/lmvz-components/p-a680a7b2.entry.js +1 -0
- package/lmvz-components/{p-d48203f9.entry.js → p-a6fe9b61.entry.js} +1 -1
- package/lmvz-components/{p-dbfbcb74.entry.js → p-a99acb02.entry.js} +1 -1
- package/lmvz-components/p-bh9cItsP.js +1 -0
- package/lmvz-components/p-f16a19fc.entry.js +1 -0
- package/lmvz-components/p-f3f0ed49.entry.js +1 -0
- package/lmvz-components/p-f516a949.entry.js +1 -0
- package/manifest.json +366 -30
- package/package.json +1 -1
- package/types/api/ds.types.d.ts +1 -0
- package/types/components/lmvz-checkbox/lmvz-checkbox.d.ts +9 -1
- package/types/components/lmvz-datepicker/lmvz-datepicker.d.ts +2 -0
- package/types/components/lmvz-input/lmvz-input.d.ts +3 -0
- package/types/components/lmvz-popover/lmvz-popover.d.ts +2 -0
- package/types/components/lmvz-radio/lmvz-radio.d.ts +12 -2
- package/types/components/lmvz-select/lmvz-select.d.ts +53 -4
- package/types/components/lmvz-toggle/lmvz-toggle.d.ts +1 -0
- package/types/components.d.ts +96 -12
- package/types/utils/aria/listbox-controller.d.ts +42 -0
- package/types/utils/radio/radio-group-controller.d.ts +3 -0
- package/components/p-CPuI0_r_.js +0 -1
- package/components/p-CWpl0WaZ.js +0 -1
- package/lmvz-components/p-63f6a596.entry.js +0 -1
- package/lmvz-components/p-8022c6dc.entry.js +0 -1
- package/lmvz-components/p-Bd9JyKJZ.js +0 -1
- package/lmvz-components/p-C3QOYC8E.js +0 -1
- package/lmvz-components/p-a611c110.entry.js +0 -1
- package/lmvz-components/p-b1bb4393.entry.js +0 -1
- package/lmvz-components/p-b50b1cb5.entry.js +0 -1
- package/lmvz-components/p-b932cf91.entry.js +0 -1
- package/lmvz-components/p-bff115d4.entry.js +0 -1
- package/lmvz-components/p-d9aede81.entry.js +0 -1
- package/lmvz-components/p-f0e28f3a.entry.js +0 -1
- package/lmvz-components/p-f853faae.entry.js +0 -1
- package/lmvz-components/p-fa2efc42.entry.js +0 -1
- package/lmvz-components/p-fe6f5bdc.entry.js +0 -1
|
@@ -22,7 +22,14 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
22
22
|
name;
|
|
23
23
|
disabled = false;
|
|
24
24
|
required = false;
|
|
25
|
-
|
|
25
|
+
nativeError = false;
|
|
26
|
+
errorFromProp = false;
|
|
27
|
+
get error() {
|
|
28
|
+
return this.errorFromProp || this.nativeError;
|
|
29
|
+
}
|
|
30
|
+
set error(value) {
|
|
31
|
+
this.errorFromProp = value;
|
|
32
|
+
}
|
|
26
33
|
helperText;
|
|
27
34
|
form;
|
|
28
35
|
autofocus = false;
|
|
@@ -30,6 +37,7 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
30
37
|
_handlingFormReset = false;
|
|
31
38
|
handleCheckedChange(newVal, oldVal) {
|
|
32
39
|
this.internals.setFormValue?.(newVal ? this.value : null);
|
|
40
|
+
this.updateValidity();
|
|
33
41
|
if (!newVal && oldVal && !this._handlingNativeChange && !this._handlingFormReset) {
|
|
34
42
|
this.lmvzChange.emit(false);
|
|
35
43
|
}
|
|
@@ -37,6 +45,9 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
37
45
|
this.lmvzChange.emit(true);
|
|
38
46
|
}
|
|
39
47
|
}
|
|
48
|
+
handleRequiredChange() {
|
|
49
|
+
this.updateValidity();
|
|
50
|
+
}
|
|
40
51
|
handleValueChange(newVal) {
|
|
41
52
|
if (this.checked) {
|
|
42
53
|
this.internals.setFormValue?.(newVal);
|
|
@@ -58,6 +69,9 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
58
69
|
async reportValidity() {
|
|
59
70
|
return this.internals?.reportValidity() ?? true;
|
|
60
71
|
}
|
|
72
|
+
async getValidationMessage() {
|
|
73
|
+
return this.internals?.validationMessage ?? '';
|
|
74
|
+
}
|
|
61
75
|
constructor() {
|
|
62
76
|
super();
|
|
63
77
|
this.addController(new AriaValidationController(this, {
|
|
@@ -69,8 +83,13 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
69
83
|
componentWillLoad() {
|
|
70
84
|
this.initialChecked = this.checked;
|
|
71
85
|
this.internals.setFormValue?.(this.checked ? this.value : null);
|
|
86
|
+
this.updateValidity();
|
|
72
87
|
super.componentWillLoad();
|
|
73
88
|
}
|
|
89
|
+
componentDidLoad() {
|
|
90
|
+
this.updateValidity();
|
|
91
|
+
super.componentDidLoad();
|
|
92
|
+
}
|
|
74
93
|
formAssociatedCallback() {
|
|
75
94
|
this.internals.setFormValue?.(this.checked ? this.value : null);
|
|
76
95
|
}
|
|
@@ -82,6 +101,8 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
82
101
|
finally {
|
|
83
102
|
this._handlingFormReset = false;
|
|
84
103
|
}
|
|
104
|
+
this.updateValidity();
|
|
105
|
+
this.radioGroupController.refreshValidity();
|
|
85
106
|
}
|
|
86
107
|
formStateRestoreCallback(state) {
|
|
87
108
|
if (typeof state !== 'string')
|
|
@@ -94,6 +115,20 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
94
115
|
this._handlingFormReset = false;
|
|
95
116
|
}
|
|
96
117
|
}
|
|
118
|
+
isAnyInGroupChecked() {
|
|
119
|
+
return this.radioGroupController.isAnyChecked();
|
|
120
|
+
}
|
|
121
|
+
updateValidity() {
|
|
122
|
+
if (this.required && !this.isAnyInGroupChecked()) {
|
|
123
|
+
this.internals.setValidity?.({ valueMissing: true }, 'Please select an option.', this.nativeInput);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.internals.setValidity?.({});
|
|
127
|
+
this.nativeError = false;
|
|
128
|
+
}
|
|
129
|
+
handleInvalid() {
|
|
130
|
+
this.nativeError = true;
|
|
131
|
+
}
|
|
97
132
|
handleChange = (event) => {
|
|
98
133
|
this._handlingNativeChange = true;
|
|
99
134
|
try {
|
|
@@ -136,8 +171,11 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
136
171
|
return;
|
|
137
172
|
this.radioGroupController.setFocused(target);
|
|
138
173
|
}
|
|
174
|
+
retargetInnerClicks() {
|
|
175
|
+
this.nativeInput?.click();
|
|
176
|
+
}
|
|
139
177
|
render() {
|
|
140
|
-
return (h(Host, { key: '
|
|
178
|
+
return (h(Host, { key: 'f1fdc1167c4e59c2524e1e545c3382ca32853788' }, h("input", { key: 'c1b711444475ed401766cc5827eeaec0c46b62cf', type: "radio", id: this.radioId, value: this.value, checked: this.checked, disabled: this.disabled, autoFocus: this.autofocus, "aria-required": this.required ? 'true' : 'false', "aria-invalid": this.error ? 'true' : undefined, "aria-describedby": this.helperId, ref: (el) => (this.nativeInput = el), onChange: this.handleChange }), h("span", { key: 'b25e623269df05bdf8159e72da4df2e0bfb5d7bc', class: "circle", "aria-hidden": "true" }, this.checked && h("span", { key: '93d12890c7ba0abe203c63953ea1115aee37d7a0', class: "dot" })), h("span", { key: '44dcfdc4e7ee3820624b0d02a438139f45bb8733', class: "content" }, h("label", { key: 'd0547cd5e79642b298da155c9937715224b52cae', htmlFor: this.radioId }, this.label), h("span", { key: 'a9df5dd8a775a2f7422d5bac296869f88553e33f', onClick: this.retargetInnerClicks.bind(this), "aria-live": "polite", class: "helper-text", id: this.helperId }, this.helperText))));
|
|
141
179
|
}
|
|
142
180
|
static get is() { return "lmvz-radio"; }
|
|
143
181
|
static get encapsulation() { return "scoped"; }
|
|
@@ -232,13 +270,13 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
232
270
|
"docs": {
|
|
233
271
|
"tags": [{
|
|
234
272
|
"name": "remarks",
|
|
235
|
-
"text": "A value of `\"\"` (empty string) is
|
|
273
|
+
"text": "A value of `\"\"` (empty string) is treated as unnamed by `RadioGroupController` \u2014\nno group coordination occurs between radios with `name=\"\"`."
|
|
236
274
|
}],
|
|
237
|
-
"text": "Name attribute for form submission via ElementInternals.\n\
|
|
275
|
+
"text": "Name attribute for form submission via ElementInternals.\n\nThe `name` is NOT forwarded to the native `<input type=\"radio\">` \u2014 this component\nrenders in `scoped` (light DOM) mode, so a native `name` attribute would make the\ninner `<input>` an independent, genuinely form-associated element of the outer\n`<form>`, submitting a duplicate value alongside the host's own `ElementInternals`\nparticipation. Instead, `name` is used purely as a JS-level grouping key: the\n`RadioGroupController` tracks all `lmvz-radio` hosts sharing the same `name` and form\nscope in an internal registry and enforces mutual exclusion itself (via\n`RadioGroup.select()`, which sets `checked = false` on every other host in the group).\nIf a radio is outside any form, its scope defaults to the document level \u2014 same-name\nradios outside forms form a document-scoped group. Radios with the same `name` in\ndifferent forms are independent groups.\n\nThe `RadioGroupController` also manages roving tabindex (only the checked radio has\n`tabindex=\"0\"`) and keyboard navigation (Arrow keys, Home, End) within the group."
|
|
238
276
|
},
|
|
239
277
|
"getter": false,
|
|
240
278
|
"setter": false,
|
|
241
|
-
"reflect":
|
|
279
|
+
"reflect": true,
|
|
242
280
|
"attribute": "name"
|
|
243
281
|
},
|
|
244
282
|
"disabled": {
|
|
@@ -304,11 +342,10 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
304
342
|
}],
|
|
305
343
|
"text": "Whether the radio is in an error state."
|
|
306
344
|
},
|
|
307
|
-
"getter":
|
|
308
|
-
"setter":
|
|
345
|
+
"getter": true,
|
|
346
|
+
"setter": true,
|
|
309
347
|
"reflect": true,
|
|
310
|
-
"attribute": "error"
|
|
311
|
-
"defaultValue": "false"
|
|
348
|
+
"attribute": "error"
|
|
312
349
|
},
|
|
313
350
|
"helperText": {
|
|
314
351
|
"type": "string",
|
|
@@ -373,6 +410,11 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
373
410
|
}
|
|
374
411
|
};
|
|
375
412
|
}
|
|
413
|
+
static get states() {
|
|
414
|
+
return {
|
|
415
|
+
"nativeError": {}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
376
418
|
static get events() {
|
|
377
419
|
return [{
|
|
378
420
|
"method": "lmvzChange",
|
|
@@ -458,6 +500,23 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
458
500
|
"text": "Reports validation errors to the user.",
|
|
459
501
|
"tags": []
|
|
460
502
|
}
|
|
503
|
+
},
|
|
504
|
+
"getValidationMessage": {
|
|
505
|
+
"complexType": {
|
|
506
|
+
"signature": "() => Promise<string>",
|
|
507
|
+
"parameters": [],
|
|
508
|
+
"references": {
|
|
509
|
+
"Promise": {
|
|
510
|
+
"location": "global",
|
|
511
|
+
"id": "global::Promise"
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
"return": "Promise<string>"
|
|
515
|
+
},
|
|
516
|
+
"docs": {
|
|
517
|
+
"text": "Returns the current validation message, if any.",
|
|
518
|
+
"tags": []
|
|
519
|
+
}
|
|
461
520
|
}
|
|
462
521
|
};
|
|
463
522
|
}
|
|
@@ -466,6 +525,9 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
466
525
|
return [{
|
|
467
526
|
"propName": "checked",
|
|
468
527
|
"methodName": "handleCheckedChange"
|
|
528
|
+
}, {
|
|
529
|
+
"propName": "required",
|
|
530
|
+
"methodName": "handleRequiredChange"
|
|
469
531
|
}, {
|
|
470
532
|
"propName": "value",
|
|
471
533
|
"methodName": "handleValueChange"
|
|
@@ -476,6 +538,12 @@ export class LmvzRadio extends ReactiveControllerHost {
|
|
|
476
538
|
}
|
|
477
539
|
static get listeners() {
|
|
478
540
|
return [{
|
|
541
|
+
"name": "invalid",
|
|
542
|
+
"method": "handleInvalid",
|
|
543
|
+
"target": undefined,
|
|
544
|
+
"capture": false,
|
|
545
|
+
"passive": false
|
|
546
|
+
}, {
|
|
479
547
|
"name": "keydown",
|
|
480
548
|
"method": "handleKeydown",
|
|
481
549
|
"target": undefined,
|
|
@@ -43,12 +43,9 @@
|
|
|
43
43
|
/* Extra top space to accommodate the floating label */
|
|
44
44
|
|
|
45
45
|
--lmvz-internal-select-floating-label-top-offset: 0.375rem;
|
|
46
|
-
|
|
47
|
-
padding-top: var(--lmvz-internal-select-floating-label-top-offset);
|
|
48
|
-
|
|
49
46
|
--lmvz-select-radius: var(--lmvz-component-input-radius-default, 999px);
|
|
50
47
|
--lmvz-select-bg: var(--lmvz-semantic-color-surface-input-primary, #ffffff);
|
|
51
|
-
--lmvz-select-border-color: var(--lmvz-semantic-color-border-
|
|
48
|
+
--lmvz-select-border-color: var(--lmvz-semantic-color-border-alternate, #c7c7c7);
|
|
52
49
|
--lmvz-select-border-color-hover: var(--lmvz-semantic-color-border-hover, #a1a1a1);
|
|
53
50
|
--lmvz-select-border-width: var(--lmvz-semantic-border-width-default, 1px);
|
|
54
51
|
--lmvz-select-text-color: var(--lmvz-semantic-color-on-surface-input-primary, #000000);
|
|
@@ -63,6 +60,8 @@
|
|
|
63
60
|
--lmvz-select-helper-color: var(--lmvz-semantic-color-on-surface-input-secondary, #545454);
|
|
64
61
|
--lmvz-select-focus-color: var(--lmvz-semantic-color-status-on-active, #0e7ab4);
|
|
65
62
|
--lmvz-select-error-color: var(--lmvz-semantic-color-status-on-danger, #a31419);
|
|
63
|
+
|
|
64
|
+
padding-top: var(--lmvz-internal-select-floating-label-top-offset);
|
|
66
65
|
}
|
|
67
66
|
.select-wrapper {
|
|
68
67
|
position: relative;
|
|
@@ -101,19 +100,20 @@ label.floating-label {
|
|
|
101
100
|
font-weight: 500;
|
|
102
101
|
}
|
|
103
102
|
label > span[aria-hidden='true'],
|
|
104
|
-
|
|
103
|
+
.select-trigger > span:first-child > span[aria-hidden='true'] {
|
|
105
104
|
color: var(--lmvz-select-error-color);
|
|
106
105
|
margin-left: 2px;
|
|
107
106
|
display: inline-block;
|
|
108
107
|
line-height: 0;
|
|
109
108
|
vertical-align: middle;
|
|
110
109
|
}
|
|
111
|
-
/*
|
|
112
|
-
|
|
110
|
+
/* Combobox trigger — the accessible, interactive control (role="combobox") */
|
|
111
|
+
.select-trigger {
|
|
113
112
|
display: flex;
|
|
114
113
|
align-items: center;
|
|
115
114
|
gap: var(--lmvz-select-gap);
|
|
116
115
|
height: 100%;
|
|
116
|
+
width: 100%;
|
|
117
117
|
padding: 0 var(--lmvz-select-padding-x);
|
|
118
118
|
border-radius: var(--lmvz-select-radius);
|
|
119
119
|
background-color: var(--lmvz-select-bg);
|
|
@@ -124,26 +124,29 @@ div[aria-hidden] {
|
|
|
124
124
|
z-index: 1;
|
|
125
125
|
transition: border-color 0.15s ease;
|
|
126
126
|
}
|
|
127
|
-
:host(:not([disabled], [highlighted])) .select-wrapper:hover
|
|
127
|
+
:host(:not([disabled], [highlighted], [error])) .select-wrapper:hover .select-trigger {
|
|
128
128
|
border-color: var(--lmvz-select-border-color-hover);
|
|
129
129
|
}
|
|
130
|
-
:host([
|
|
130
|
+
:host([error]) .select-trigger {
|
|
131
|
+
border-color: var(--lmvz-select-error-color);
|
|
132
|
+
}
|
|
133
|
+
:host([highlighted]) .select-trigger {
|
|
131
134
|
background-color: var(--lmvz-semantic-color-status-active-alternate, #0f8acc);
|
|
132
135
|
border-color: var(--lmvz-semantic-color-border-active, #0f8acc);
|
|
133
136
|
color: var(--lmvz-semantic-color-status-on-active-alternate, #ffffff);
|
|
134
137
|
}
|
|
135
|
-
:host([highlighted])
|
|
138
|
+
:host([highlighted]) .select-trigger > span:first-child {
|
|
136
139
|
color: var(--lmvz-semantic-color-status-on-active-alternate, #ffffff);
|
|
137
140
|
}
|
|
138
141
|
:host([highlighted]) label.floating-label {
|
|
139
142
|
background-color: var(--lmvz-semantic-color-status-active-alternate, #0f8acc);
|
|
140
143
|
color: var(--lmvz-semantic-color-status-on-active-alternate, #ffffff);
|
|
141
144
|
}
|
|
142
|
-
|
|
145
|
+
:host:has(:focus-visible) .select-trigger {
|
|
143
146
|
outline: var(--lmvz-ds-outline, 1px solid #0e7ab4);
|
|
144
147
|
outline-offset: var(--lmvz-ds-outline-offset, clamp(0.25rem, 0.19rem + 0.26vw, 0.5rem));
|
|
145
148
|
}
|
|
146
|
-
|
|
149
|
+
.select-trigger > span:first-child {
|
|
147
150
|
flex: 1 0 0;
|
|
148
151
|
font: var(--lmvz-typography-body-md-strong, 500 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
|
|
149
152
|
Router);
|
|
@@ -151,36 +154,26 @@ div[aria-hidden] > span:first-child {
|
|
|
151
154
|
overflow: hidden;
|
|
152
155
|
text-overflow: ellipsis;
|
|
153
156
|
white-space: nowrap;
|
|
157
|
+
text-align: left;
|
|
154
158
|
}
|
|
155
159
|
/* Active-selected text color: when a value is selected (not applicable in highlighted state) */
|
|
156
|
-
:host(:not([highlighted])) .select-wrapper.has-value
|
|
160
|
+
:host(:not([highlighted])) .select-wrapper.has-value .select-trigger > span:first-child {
|
|
157
161
|
color: var(--lmvz-semantic-color-int-on-secondary-active, #000000);
|
|
158
162
|
}
|
|
159
|
-
|
|
163
|
+
.select-trigger > span:last-child {
|
|
160
164
|
flex-shrink: 0;
|
|
161
165
|
display: flex;
|
|
162
166
|
align-items: center;
|
|
163
167
|
justify-content: center;
|
|
164
168
|
}
|
|
165
|
-
|
|
169
|
+
.select-trigger svg {
|
|
166
170
|
width: var(--lmvz-component-icon-size-2xs, clamp(0.63rem, 0.59rem + 0.13vw, 0.75rem));
|
|
167
171
|
height: var(--lmvz-component-icon-size-2xs, clamp(0.63rem, 0.59rem + 0.13vw, 0.75rem));
|
|
168
172
|
flex-shrink: 0;
|
|
169
173
|
}
|
|
170
|
-
/* Native
|
|
171
|
-
select {
|
|
172
|
-
|
|
173
|
-
position: absolute;
|
|
174
|
-
inset: 0;
|
|
175
|
-
width: 100%;
|
|
176
|
-
height: 100%;
|
|
177
|
-
opacity: 0;
|
|
178
|
-
cursor: pointer;
|
|
179
|
-
z-index: 2;
|
|
180
|
-
border: none;
|
|
181
|
-
background: transparent;
|
|
182
|
-
margin: 0;
|
|
183
|
-
padding: 0;
|
|
174
|
+
/* Native <option>/<optgroup> markup is only a data source for the internal listbox; never shown. */
|
|
175
|
+
.lmvz-select-native-options {
|
|
176
|
+
display: none;
|
|
184
177
|
}
|
|
185
178
|
:host([disabled]) .select-wrapper {
|
|
186
179
|
opacity: var(--lmvz-select-disabled-opacity);
|
|
@@ -188,22 +181,29 @@ select {
|
|
|
188
181
|
cursor: not-allowed;
|
|
189
182
|
}
|
|
190
183
|
[role='status'] {
|
|
191
|
-
|
|
184
|
+
padding-top: var(--lmvz-dimension-8-6, clamp(0.38rem, 0.34rem + 0.13vw, 0.5rem));
|
|
192
185
|
padding-left: var(--lmvz-select-padding-x);
|
|
193
186
|
font-size: var(--lmvz-select-label-font-size);
|
|
194
187
|
color: var(--lmvz-select-helper-color);
|
|
195
188
|
line-height: normal;
|
|
196
189
|
}
|
|
190
|
+
[role='alert'] {
|
|
191
|
+
padding-top: var(--lmvz-dimension-8-6, clamp(0.38rem, 0.34rem + 0.13vw, 0.5rem));
|
|
192
|
+
padding-left: var(--lmvz-select-padding-x);
|
|
193
|
+
font-size: var(--lmvz-component-body-sm-font-size, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem));
|
|
194
|
+
color: var(--lmvz-select-error-color);
|
|
195
|
+
line-height: normal;
|
|
196
|
+
}
|
|
197
197
|
:host([size='small']) {
|
|
198
198
|
--lmvz-select-height: var(--lmvz-component-input-size-sm, clamp(2rem, 1.94rem + 0.26vw, 2.25rem));
|
|
199
199
|
--lmvz-select-padding-x: var(--lmvz-component-input-padding-sm, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem));
|
|
200
200
|
--lmvz-select-gap: var(--lmvz-component-input-gap-sm, clamp(0.38rem, 0.31rem + 0.26vw, 0.63rem));
|
|
201
201
|
--lmvz-select-label-font-size: var(--lmvz-component-body-2xs-font-size, clamp(0.5rem, 0.47rem + 0.13vw, 0.63rem));
|
|
202
202
|
}
|
|
203
|
-
:host([size='small'])
|
|
203
|
+
:host([size='small']) .select-trigger > span:first-child {
|
|
204
204
|
font-size: var(--lmvz-component-body-sm-font-size, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem));
|
|
205
205
|
}
|
|
206
|
-
:host([size='small'])
|
|
206
|
+
:host([size='small']) .select-trigger svg {
|
|
207
207
|
width: var(--lmvz-component-icon-size-4xs, clamp(0.5rem, 0.47rem + 0.13vw, 0.63rem));
|
|
208
208
|
height: var(--lmvz-component-icon-size-4xs, clamp(0.5rem, 0.47rem + 0.13vw, 0.63rem));
|
|
209
209
|
}
|
|
@@ -213,10 +213,72 @@ select {
|
|
|
213
213
|
--lmvz-select-gap: var(--lmvz-component-input-gap-lg, clamp(0.75rem, 0.69rem + 0.26vw, 1rem));
|
|
214
214
|
--lmvz-select-label-font-size: var(--lmvz-component-body-sm-font-size, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem));
|
|
215
215
|
}
|
|
216
|
-
:host([size='large'])
|
|
216
|
+
:host([size='large']) .select-trigger > span:first-child {
|
|
217
217
|
font-size: var(--lmvz-component-body-lg-font-size, clamp(1rem, 0.97rem + 0.13vw, 1.13rem));
|
|
218
218
|
}
|
|
219
|
-
:host([size='large'])
|
|
219
|
+
:host([size='large']) .select-trigger svg {
|
|
220
220
|
width: var(--lmvz-component-icon-size-xs, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem));
|
|
221
221
|
height: var(--lmvz-component-icon-size-xs, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem));
|
|
222
222
|
}
|
|
223
|
+
/*
|
|
224
|
+
* Option-list item styling for the `role="option"` elements rendered inside the
|
|
225
|
+
* `lmvz-popover` (containerRole="listbox") popup. The token set mirrors the states
|
|
226
|
+
* `lmvz-action-list` applies to its `<lmvz-button>`/`<button>` items (tertiary variant),
|
|
227
|
+
* so the listbox looks visually identical to an action-list item:
|
|
228
|
+
* - default: --lmvz-semantic-color-int-tertiary / --lmvz-semantic-color-int-on-tertiary
|
|
229
|
+
* - hover: --lmvz-semantic-color-int-tertiary-hover / --lmvz-semantic-color-int-on-tertiary-hover
|
|
230
|
+
* - active: --lmvz-semantic-color-int-tertiary-active / --lmvz-semantic-color-int-on-tertiary-active
|
|
231
|
+
* - disabled: --lmvz-component-input-disabled-opacity (opacity, same token as lib-styles buttons fragment)
|
|
232
|
+
* - focus: --lmvz-ds-outline / --lmvz-ds-outline-offset (same as lib-styles buttons fragment focus-visible)
|
|
233
|
+
* "selected" has no action-list equivalent (action-list is a menu, not a listbox), so it
|
|
234
|
+
* reuses this component's own highlighted-state tokens for consistency with the trigger.
|
|
235
|
+
* "active" (`data-active="true"`) is this component's own addition: since the combobox uses
|
|
236
|
+
* the activedescendant model, the highlighted option never receives real DOM focus, so
|
|
237
|
+
* `:hover`/`:focus-visible` cannot indicate it to sighted keyboard users — `data-active` is
|
|
238
|
+
* set by the host from `ListboxController`'s active id and styled the same as hover/focus.
|
|
239
|
+
*/
|
|
240
|
+
.lmvz-select-option {
|
|
241
|
+
--lmvz-select-option-background: var(--lmvz-semantic-color-int-tertiary, #ffffff);
|
|
242
|
+
--lmvz-select-option-color: var(--lmvz-semantic-color-int-on-tertiary, #000000);
|
|
243
|
+
|
|
244
|
+
display: flex;
|
|
245
|
+
align-items: center;
|
|
246
|
+
gap: var(--lmvz-select-gap);
|
|
247
|
+
padding: var(--lmvz-component-input-padding-sm, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem));
|
|
248
|
+
border-radius: var(--lmvz-semantic-border-radius-md, 6px);
|
|
249
|
+
background-color: var(--lmvz-select-option-background);
|
|
250
|
+
color: var(--lmvz-select-option-color);
|
|
251
|
+
cursor: pointer;
|
|
252
|
+
font: var(--lmvz-typography-body-md-strong, 500 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
|
|
253
|
+
Router);
|
|
254
|
+
transition:
|
|
255
|
+
background-color 0.15s ease,
|
|
256
|
+
color 0.15s ease;
|
|
257
|
+
}
|
|
258
|
+
.lmvz-select-option:not([aria-disabled='true']):hover {
|
|
259
|
+
--lmvz-select-option-background: var(--lmvz-semantic-color-int-tertiary-hover, #f0f0f0);
|
|
260
|
+
--lmvz-select-option-color: var(--lmvz-semantic-color-int-on-tertiary-hover, #000000);
|
|
261
|
+
}
|
|
262
|
+
.lmvz-select-option:not([aria-disabled='true']):active {
|
|
263
|
+
--lmvz-select-option-background: var(--lmvz-semantic-color-int-tertiary-active, #e0e0e0);
|
|
264
|
+
--lmvz-select-option-color: var(--lmvz-semantic-color-int-on-tertiary-active, #000000);
|
|
265
|
+
}
|
|
266
|
+
.lmvz-select-option:focus-visible {
|
|
267
|
+
outline: var(--lmvz-ds-outline, 1px solid #0e7ab4);
|
|
268
|
+
outline-offset: var(--lmvz-ds-outline-offset, clamp(0.25rem, 0.19rem + 0.26vw, 0.5rem));
|
|
269
|
+
position: relative;
|
|
270
|
+
z-index: 1;
|
|
271
|
+
}
|
|
272
|
+
.lmvz-select-option[data-active='true']:not([aria-disabled='true']) {
|
|
273
|
+
--lmvz-select-option-background: var(--lmvz-semantic-color-int-tertiary-hover, #f0f0f0);
|
|
274
|
+
--lmvz-select-option-color: var(--lmvz-semantic-color-int-on-tertiary-hover, #000000);
|
|
275
|
+
}
|
|
276
|
+
.lmvz-select-option[aria-selected='true'] {
|
|
277
|
+
--lmvz-select-option-background: var(--lmvz-semantic-color-status-active-alternate, #0f8acc);
|
|
278
|
+
--lmvz-select-option-color: var(--lmvz-semantic-color-status-on-active-alternate, #ffffff);
|
|
279
|
+
}
|
|
280
|
+
.lmvz-select-option[aria-disabled='true'] {
|
|
281
|
+
cursor: not-allowed;
|
|
282
|
+
pointer-events: none;
|
|
283
|
+
opacity: var(--lmvz-component-input-disabled-opacity, 40%);
|
|
284
|
+
}
|