@lmvz-ds/components 0.24.0 → 0.26.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 (140) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/cjs/{ds.constants-DSnxZ3ia.js → ds.constants-8fh6ItAF.js} +1 -1
  3. package/cjs/{index-lW-SEvL7.js → index-BCFBLj0e.js} +1 -1
  4. package/cjs/index.cjs.js +196 -2
  5. package/cjs/lmvz-action.cjs.entry.js +1 -1
  6. package/cjs/lmvz-button-group.cjs.entry.js +183 -0
  7. package/cjs/lmvz-button_2.cjs.entry.js +198 -0
  8. package/cjs/lmvz-card.cjs.entry.js +2 -2
  9. package/cjs/lmvz-checkbox.cjs.entry.js +5 -5
  10. package/cjs/lmvz-chip.cjs.entry.js +4 -4
  11. package/cjs/lmvz-components.cjs.js +3 -3
  12. package/cjs/lmvz-header_2.cjs.entry.js +2 -2
  13. package/cjs/lmvz-input.cjs.entry.js +3 -3
  14. package/cjs/lmvz-menuitem.cjs.entry.js +3 -3
  15. package/cjs/lmvz-modal.cjs.entry.js +5 -5
  16. package/cjs/lmvz-radio.cjs.entry.js +334 -0
  17. package/cjs/lmvz-select.cjs.entry.js +4 -4
  18. package/cjs/lmvz-snackbar.cjs.entry.js +83 -0
  19. package/cjs/lmvz-toggle.cjs.entry.js +7 -5
  20. package/cjs/loader.cjs.js +2 -2
  21. package/cjs/{reactive-controller-host-BOFg4vL-.js → reactive-controller-host-DrtMkMd7.js} +1 -1
  22. package/collection/api/ds.constants.js +4 -1
  23. package/collection/collection-manifest.json +3 -1
  24. package/collection/components/lmvz-button/lmvz-button.css +8 -8
  25. package/collection/components/lmvz-button-group/lmvz-button-group.css +1 -1
  26. package/collection/components/lmvz-card/lmvz-card.css +11 -11
  27. package/collection/components/lmvz-checkbox/lmvz-checkbox.css +8 -11
  28. package/collection/components/lmvz-checkbox/lmvz-checkbox.js +2 -2
  29. package/collection/components/lmvz-chip/lmvz-chip.css +3 -3
  30. package/collection/components/lmvz-icon/lmvz-icon.js +1 -1
  31. package/collection/components/lmvz-input/lmvz-input.css +5 -9
  32. package/collection/components/lmvz-menuitem/lmvz-menuitem.css +3 -3
  33. package/collection/components/lmvz-modal/lmvz-modal.css +21 -15
  34. package/collection/components/lmvz-modal/lmvz-modal.js +2 -2
  35. package/collection/components/lmvz-radio/lmvz-radio.css +182 -0
  36. package/collection/components/lmvz-radio/lmvz-radio.js +487 -0
  37. package/collection/components/lmvz-select/lmvz-select.css +3 -3
  38. package/collection/components/lmvz-select/lmvz-select.js +1 -1
  39. package/collection/components/lmvz-snackbar/lmvz-snackbar.css +101 -0
  40. package/collection/components/lmvz-snackbar/lmvz-snackbar.js +266 -0
  41. package/collection/components/lmvz-snackbar/public.js +1 -0
  42. package/collection/components/lmvz-snackbar/snackbar-controller.js +194 -0
  43. package/collection/components/lmvz-toggle/lmvz-toggle.css +4 -9
  44. package/collection/components/lmvz-toggle/lmvz-toggle.js +3 -3
  45. package/collection/index.js +1 -0
  46. package/collection/integration/header-integration/header-integration.js +1 -1
  47. package/collection/styles/fragments/_focus-within.css +13 -0
  48. package/collection/utils/radio/radio-group-controller.js +160 -0
  49. package/components/index.d.ts +4 -0
  50. package/components/index.d.ts.bak +4 -0
  51. package/components/index.js +1 -1
  52. package/components/lmvz-action.js +1 -1
  53. package/components/lmvz-button-group.js +1 -1
  54. package/components/lmvz-button.js +1 -1
  55. package/components/lmvz-card.js +1 -1
  56. package/components/lmvz-checkbox.js +1 -1
  57. package/components/lmvz-chip.js +1 -1
  58. package/components/lmvz-header.js +1 -1
  59. package/components/lmvz-icon.js +1 -1
  60. package/components/lmvz-input.js +1 -1
  61. package/components/lmvz-menuitem.js +1 -1
  62. package/components/lmvz-modal.js +1 -1
  63. package/components/lmvz-radio.d.ts +11 -0
  64. package/components/lmvz-radio.d.ts.bak +11 -0
  65. package/components/lmvz-radio.js +1 -0
  66. package/components/lmvz-select.js +1 -1
  67. package/components/lmvz-snackbar.d.ts +11 -0
  68. package/components/lmvz-snackbar.d.ts.bak +11 -0
  69. package/components/lmvz-snackbar.js +1 -0
  70. package/components/lmvz-toggle.js +1 -1
  71. package/components/{p-slgmfnHm.js → p-BOzeYzKk.js} +1 -1
  72. package/components/{p-Cg2XX_J-.js → p-DYa3zcGE.js} +1 -1
  73. package/components/{p-DOTK1OW3.js → p-JAKQdFhF.js} +1 -1
  74. package/components/{p-CcnyKhAw.js → p-WLZ7VWNX.js} +1 -1
  75. package/components/{p-CK8cAKcB.js → p-c7OzBK8f.js} +1 -1
  76. package/components/{p-DSvYtVoD.js → p-lsUdmjdw.js} +1 -1
  77. package/esm/{ds.constants-Bmi89ll1.js → ds.constants-BOOwq5dE.js} +1 -1
  78. package/esm/{index-Aa_425iY.js → index-CKYszC64.js} +1 -1
  79. package/esm/index.js +198 -1
  80. package/esm/lmvz-action.entry.js +1 -1
  81. package/esm/lmvz-button-group.entry.js +181 -0
  82. package/esm/lmvz-button_2.entry.js +195 -0
  83. package/esm/lmvz-card.entry.js +2 -2
  84. package/esm/lmvz-checkbox.entry.js +5 -5
  85. package/esm/lmvz-chip.entry.js +4 -4
  86. package/esm/lmvz-components.js +4 -4
  87. package/esm/lmvz-header_2.entry.js +2 -2
  88. package/esm/lmvz-input.entry.js +3 -3
  89. package/esm/lmvz-menuitem.entry.js +3 -3
  90. package/esm/lmvz-modal.entry.js +5 -5
  91. package/esm/lmvz-radio.entry.js +332 -0
  92. package/esm/lmvz-select.entry.js +4 -4
  93. package/esm/lmvz-snackbar.entry.js +81 -0
  94. package/esm/lmvz-toggle.entry.js +7 -5
  95. package/esm/loader.js +3 -3
  96. package/esm/{reactive-controller-host-CroMsXdS.js → reactive-controller-host-ZrGf1F2-.js} +1 -1
  97. package/hydrate/index.js +467 -19
  98. package/hydrate/index.mjs +467 -19
  99. package/lmvz-components/index.esm.js +1 -1
  100. package/lmvz-components/lmvz-components.esm.js +1 -1
  101. package/lmvz-components/{p-d1dacf7e.entry.js → p-01aeca60.entry.js} +1 -1
  102. package/lmvz-components/p-0a37e0f2.entry.js +1 -0
  103. package/lmvz-components/p-14c3d837.entry.js +1 -0
  104. package/lmvz-components/{p-4263c9b2.entry.js → p-24e63b0a.entry.js} +1 -1
  105. package/lmvz-components/p-25f045b2.entry.js +1 -0
  106. package/lmvz-components/{p-f6d1d9df.entry.js → p-3da301a6.entry.js} +1 -1
  107. package/lmvz-components/p-40228d48.entry.js +1 -0
  108. package/lmvz-components/p-4da9073a.entry.js +1 -0
  109. package/lmvz-components/p-6de9981f.entry.js +1 -0
  110. package/lmvz-components/{p-6f8cbc4f.entry.js → p-758078db.entry.js} +1 -1
  111. package/lmvz-components/{p-88adb9fa.entry.js → p-8dae99f1.entry.js} +1 -1
  112. package/lmvz-components/p-BOOwq5dE.js +1 -0
  113. package/lmvz-components/{p-BRl6zKXT.js → p-CwX1wKkM.js} +1 -1
  114. package/lmvz-components/{p-a7c3074a.entry.js → p-e1eaa7a2.entry.js} +1 -1
  115. package/lmvz-components/p-f5cece32.entry.js +1 -0
  116. package/lmvz-components/p-fe607f10.entry.js +1 -0
  117. package/manifest.json +892 -205
  118. package/package.json +9 -1
  119. package/types/api/ds.constants.d.ts +9 -1
  120. package/types/components/lmvz-radio/lmvz-radio.d.ts +42 -0
  121. package/types/components/lmvz-snackbar/lmvz-snackbar.d.ts +21 -0
  122. package/types/components/lmvz-snackbar/public.d.ts +2 -0
  123. package/types/components/lmvz-snackbar/snackbar-controller.d.ts +32 -0
  124. package/types/components.d.ts +237 -1
  125. package/types/index.d.ts +1 -0
  126. package/types/stencil-public-runtime.d.ts +1 -0
  127. package/types/utils/radio/radio-group-controller.d.ts +26 -0
  128. package/assets/icons/checkmark.svg +0 -4
  129. package/assets/icons/close-sm.svg +0 -3
  130. package/cjs/lmvz-button_3.cjs.entry.js +0 -375
  131. package/collection/assets/icons/checkmark.svg +0 -4
  132. package/collection/assets/icons/close-sm.svg +0 -3
  133. package/esm/lmvz-button_3.entry.js +0 -371
  134. package/lmvz-components/p-2824a56b.entry.js +0 -1
  135. package/lmvz-components/p-3846ba08.entry.js +0 -1
  136. package/lmvz-components/p-4f5c3c4a.entry.js +0 -1
  137. package/lmvz-components/p-Bmi89ll1.js +0 -1
  138. package/lmvz-components/p-b3b04d46.entry.js +0 -1
  139. package/lmvz-components/p-fefefc54.entry.js +0 -1
  140. /package/lmvz-components/{p-Aa_425iY.js → p-CKYszC64.js} +0 -0
@@ -0,0 +1,487 @@
1
+ import { h, Host } from "@stencil/core";
2
+ import { AriaValidationController } from "../../utils/aria/aria-validation-controller";
3
+ import { RadioGroupController } from "../../utils/radio/radio-group-controller";
4
+ import { ReactiveControllerHost } from "../../utils/reactive-controller-host";
5
+ let radioIdCounter = 0;
6
+ export class LmvzRadio extends ReactiveControllerHost {
7
+ el;
8
+ get validationEl() {
9
+ return this.el;
10
+ }
11
+ internals;
12
+ nativeInput;
13
+ radioId = `lmvz-radio-${radioIdCounter++}`;
14
+ initialChecked = false;
15
+ radioGroupController;
16
+ get helperId() {
17
+ return this.helperText ? `${this.radioId}-helper` : undefined;
18
+ }
19
+ label;
20
+ checked = false;
21
+ value = 'on';
22
+ name;
23
+ disabled = false;
24
+ required = false;
25
+ error = false;
26
+ helperText;
27
+ form;
28
+ autofocus = false;
29
+ _handlingNativeChange = false;
30
+ _handlingFormReset = false;
31
+ handleCheckedChange(newVal, oldVal) {
32
+ this.internals.setFormValue?.(newVal ? this.value : null);
33
+ if (!newVal && oldVal && !this._handlingNativeChange && !this._handlingFormReset) {
34
+ this.lmvzChange.emit(false);
35
+ }
36
+ if (newVal && !oldVal && !this._handlingNativeChange && !this._handlingFormReset) {
37
+ this.lmvzChange.emit(true);
38
+ }
39
+ }
40
+ handleValueChange(newVal) {
41
+ if (this.checked) {
42
+ this.internals.setFormValue?.(newVal);
43
+ }
44
+ }
45
+ handleLabelChange(newVal) {
46
+ if (!newVal) {
47
+ console.warn('[lmvz-radio] label prop is required and must not be empty');
48
+ }
49
+ }
50
+ lmvzChange;
51
+ lmvzActivation;
52
+ async focusInput() {
53
+ this.nativeInput?.focus();
54
+ }
55
+ async checkValidity() {
56
+ return this.internals?.checkValidity() ?? true;
57
+ }
58
+ async reportValidity() {
59
+ return this.internals?.reportValidity() ?? true;
60
+ }
61
+ constructor() {
62
+ super();
63
+ this.addController(new AriaValidationController(this, {
64
+ reValidateOnPropChanges: true,
65
+ }));
66
+ this.radioGroupController = new RadioGroupController(this);
67
+ this.addController(this.radioGroupController);
68
+ }
69
+ componentWillLoad() {
70
+ this.initialChecked = this.checked;
71
+ this.internals.setFormValue?.(this.checked ? this.value : null);
72
+ super.componentWillLoad();
73
+ }
74
+ formAssociatedCallback() {
75
+ this.internals.setFormValue?.(this.checked ? this.value : null);
76
+ }
77
+ formResetCallback() {
78
+ this._handlingFormReset = true;
79
+ try {
80
+ this.checked = this.initialChecked;
81
+ }
82
+ finally {
83
+ this._handlingFormReset = false;
84
+ }
85
+ }
86
+ formStateRestoreCallback(state) {
87
+ if (typeof state !== 'string')
88
+ return;
89
+ this._handlingFormReset = true;
90
+ try {
91
+ this.checked = state === this.value;
92
+ }
93
+ finally {
94
+ this._handlingFormReset = false;
95
+ }
96
+ }
97
+ handleChange = (event) => {
98
+ this._handlingNativeChange = true;
99
+ try {
100
+ const input = event.target;
101
+ this.checked = input.checked;
102
+ this.lmvzChange.emit(this.checked);
103
+ this.radioGroupController.select(this);
104
+ this.lmvzActivation.emit();
105
+ }
106
+ finally {
107
+ this._handlingNativeChange = false;
108
+ }
109
+ };
110
+ handleKeydown(event) {
111
+ const { key } = event;
112
+ if (!['ArrowDown', 'ArrowRight', 'ArrowUp', 'ArrowLeft', 'Home', 'End'].includes(key))
113
+ return;
114
+ event.preventDefault();
115
+ const radios = this.radioGroupController.sortedEnabled;
116
+ if (radios.length === 0)
117
+ return;
118
+ const currentIndex = radios.indexOf(this);
119
+ if (currentIndex === -1)
120
+ return;
121
+ let targetIndex;
122
+ if (key === 'ArrowDown' || key === 'ArrowRight') {
123
+ targetIndex = (currentIndex + 1) % radios.length;
124
+ }
125
+ else if (key === 'ArrowUp' || key === 'ArrowLeft') {
126
+ targetIndex = (currentIndex - 1 + radios.length) % radios.length;
127
+ }
128
+ else if (key === 'Home') {
129
+ targetIndex = 0;
130
+ }
131
+ else {
132
+ targetIndex = radios.length - 1;
133
+ }
134
+ const target = radios[targetIndex];
135
+ if (!target)
136
+ return;
137
+ this.radioGroupController.setFocused(target);
138
+ }
139
+ render() {
140
+ return (h(Host, { key: '0226e313fcf4fe3c3cf343cfe0776cf71da169a6' }, h("input", { key: '5bb1f733d2f29217bc7544d8fd24f6b21bedc654', type: "radio", id: this.radioId, name: this.name ?? undefined, value: this.value, checked: this.checked, disabled: this.disabled, required: this.required, autoFocus: this.autofocus, "aria-invalid": this.error ? 'true' : undefined, "aria-describedby": this.helperId, ref: (el) => (this.nativeInput = el), onChange: this.handleChange }), h("span", { key: 'ae18f49167d1a2e8e6ec4ceca435e69e3d79f593', class: "circle", "aria-hidden": "true" }, this.checked && h("span", { key: '5dfb65105831a672f2a47952aff987cd45e9b178', class: "dot" })), h("span", { key: 'df148ca52be7e580226d94ff9aef4e3cf5a6182c', class: "content" }, h("label", { key: 'e042c57755eadb64692ace49204dccb1ee03ed1c', htmlFor: this.radioId }, this.label), h("span", { key: 'a90b0bef927dddb39f9e6357adf888e0818a3c5a', "aria-live": "polite", class: "helper-text", id: this.helperId }, this.helperText))));
141
+ }
142
+ static get is() { return "lmvz-radio"; }
143
+ static get encapsulation() { return "scoped"; }
144
+ static get formAssociated() { return true; }
145
+ static get originalStyleUrls() {
146
+ return {
147
+ "$": ["./lmvz-radio.css", "../../styles/fragments/_focus-within.css"]
148
+ };
149
+ }
150
+ static get styleUrls() {
151
+ return {
152
+ "$": ["lmvz-radio.css", "../../styles/fragments/_focus-within.css"]
153
+ };
154
+ }
155
+ static get properties() {
156
+ return {
157
+ "label": {
158
+ "type": "string",
159
+ "mutable": false,
160
+ "complexType": {
161
+ "original": "string",
162
+ "resolved": "string",
163
+ "references": {}
164
+ },
165
+ "required": true,
166
+ "optional": false,
167
+ "docs": {
168
+ "tags": [],
169
+ "text": "Label text for the radio. Required for accessibility."
170
+ },
171
+ "getter": false,
172
+ "setter": false,
173
+ "reflect": false,
174
+ "attribute": "label"
175
+ },
176
+ "checked": {
177
+ "type": "boolean",
178
+ "mutable": true,
179
+ "complexType": {
180
+ "original": "boolean",
181
+ "resolved": "boolean",
182
+ "references": {}
183
+ },
184
+ "required": false,
185
+ "optional": false,
186
+ "docs": {
187
+ "tags": [{
188
+ "name": "default",
189
+ "text": "false"
190
+ }],
191
+ "text": "Whether the radio is checked.\n\nSetting this prop programmatically (e.g. `element.checked = true`) fires `lmvzChange`\nwith the new value, unless the change occurs during native form lifecycle callbacks\n(`formResetCallback` or `formStateRestoreCallback`), in which case emission is suppressed\nto match native `<input type=\"radio\">` behavior. Internal form state is always updated\nregardless of emission suppression."
192
+ },
193
+ "getter": false,
194
+ "setter": false,
195
+ "reflect": true,
196
+ "attribute": "checked",
197
+ "defaultValue": "false"
198
+ },
199
+ "value": {
200
+ "type": "string",
201
+ "mutable": false,
202
+ "complexType": {
203
+ "original": "string",
204
+ "resolved": "string",
205
+ "references": {}
206
+ },
207
+ "required": false,
208
+ "optional": false,
209
+ "docs": {
210
+ "tags": [{
211
+ "name": "default",
212
+ "text": "'on'"
213
+ }],
214
+ "text": "Form submission value when checked."
215
+ },
216
+ "getter": false,
217
+ "setter": false,
218
+ "reflect": false,
219
+ "attribute": "value",
220
+ "defaultValue": "'on'"
221
+ },
222
+ "name": {
223
+ "type": "string",
224
+ "mutable": false,
225
+ "complexType": {
226
+ "original": "string",
227
+ "resolved": "string | undefined",
228
+ "references": {}
229
+ },
230
+ "required": false,
231
+ "optional": true,
232
+ "docs": {
233
+ "tags": [{
234
+ "name": "remarks",
235
+ "text": "A value of `\"\"` (empty string) is forwarded to the native `<input>`, but\n`RadioGroupController` treats it as unnamed \u2014 no group coordination occurs between\nradios with `name=\"\"`."
236
+ }],
237
+ "text": "Name attribute for form submission via ElementInternals.\n\nWhen multiple `lmvz-radio` elements share the same `name` and form scope,\nthe `name` is forwarded directly to the native `<input type=\"radio\">`,\nenabling browser-native mutual exclusion: selecting one radio automatically\ndeselects all others with the same name in that form. If a radio is outside\nany form, its scope defaults to the document level \u2014 same-name radios\noutside forms form a document-scoped group. Radios with the same `name` in\ndifferent forms are independent groups.\n\nThe `RadioGroupController` automatically manages roving tabindex (only the\nchecked radio has `tabindex=\"0\"`) and keyboard navigation (Arrow keys, Home, End)\nwithin the form-scoped group."
238
+ },
239
+ "getter": false,
240
+ "setter": false,
241
+ "reflect": false,
242
+ "attribute": "name"
243
+ },
244
+ "disabled": {
245
+ "type": "boolean",
246
+ "mutable": false,
247
+ "complexType": {
248
+ "original": "boolean",
249
+ "resolved": "boolean",
250
+ "references": {}
251
+ },
252
+ "required": false,
253
+ "optional": false,
254
+ "docs": {
255
+ "tags": [{
256
+ "name": "default",
257
+ "text": "false"
258
+ }],
259
+ "text": "Whether the radio is disabled."
260
+ },
261
+ "getter": false,
262
+ "setter": false,
263
+ "reflect": true,
264
+ "attribute": "disabled",
265
+ "defaultValue": "false"
266
+ },
267
+ "required": {
268
+ "type": "boolean",
269
+ "mutable": false,
270
+ "complexType": {
271
+ "original": "boolean",
272
+ "resolved": "boolean",
273
+ "references": {}
274
+ },
275
+ "required": false,
276
+ "optional": false,
277
+ "docs": {
278
+ "tags": [{
279
+ "name": "default",
280
+ "text": "false"
281
+ }],
282
+ "text": "Whether the radio is required."
283
+ },
284
+ "getter": false,
285
+ "setter": false,
286
+ "reflect": true,
287
+ "attribute": "required",
288
+ "defaultValue": "false"
289
+ },
290
+ "error": {
291
+ "type": "boolean",
292
+ "mutable": false,
293
+ "complexType": {
294
+ "original": "boolean",
295
+ "resolved": "boolean",
296
+ "references": {}
297
+ },
298
+ "required": false,
299
+ "optional": false,
300
+ "docs": {
301
+ "tags": [{
302
+ "name": "default",
303
+ "text": "false"
304
+ }],
305
+ "text": "Whether the radio is in an error state."
306
+ },
307
+ "getter": false,
308
+ "setter": false,
309
+ "reflect": true,
310
+ "attribute": "error",
311
+ "defaultValue": "false"
312
+ },
313
+ "helperText": {
314
+ "type": "string",
315
+ "mutable": false,
316
+ "complexType": {
317
+ "original": "string",
318
+ "resolved": "string | undefined",
319
+ "references": {}
320
+ },
321
+ "required": false,
322
+ "optional": true,
323
+ "docs": {
324
+ "tags": [],
325
+ "text": "Helper / description text displayed below the label."
326
+ },
327
+ "getter": false,
328
+ "setter": false,
329
+ "reflect": false,
330
+ "attribute": "helper-text"
331
+ },
332
+ "form": {
333
+ "type": "string",
334
+ "mutable": false,
335
+ "complexType": {
336
+ "original": "string",
337
+ "resolved": "string | undefined",
338
+ "references": {}
339
+ },
340
+ "required": false,
341
+ "optional": true,
342
+ "docs": {
343
+ "tags": [],
344
+ "text": "Form id to associate with (for out-of-form usage).\nReflected to the host attribute so both HTML attribute and programmatic assignment work."
345
+ },
346
+ "getter": false,
347
+ "setter": false,
348
+ "reflect": true,
349
+ "attribute": "form"
350
+ },
351
+ "autofocus": {
352
+ "type": "boolean",
353
+ "mutable": false,
354
+ "complexType": {
355
+ "original": "boolean",
356
+ "resolved": "boolean",
357
+ "references": {}
358
+ },
359
+ "required": false,
360
+ "optional": false,
361
+ "docs": {
362
+ "tags": [{
363
+ "name": "default",
364
+ "text": "false"
365
+ }],
366
+ "text": "Whether the radio should autofocus."
367
+ },
368
+ "getter": false,
369
+ "setter": false,
370
+ "reflect": false,
371
+ "attribute": "autofocus",
372
+ "defaultValue": "false"
373
+ }
374
+ };
375
+ }
376
+ static get events() {
377
+ return [{
378
+ "method": "lmvzChange",
379
+ "name": "lmvzChange",
380
+ "bubbles": true,
381
+ "cancelable": true,
382
+ "composed": true,
383
+ "docs": {
384
+ "tags": [],
385
+ "text": "Emitted whenever the radio checked state changes.\nEvent detail contains the new checked boolean value.\n\nEmission contract:\n- Fires `true` on user selection (native `change` event).\n- Fires on programmatic external prop transitions: `true \u2192 false` (emits `false`) and\n `false \u2192 true` (emits `true`), e.g. `element.checked = false` or `element.checked = true`.\n- Does NOT fire during browser-driven form lifecycle callbacks: `formResetCallback` and\n `formStateRestoreCallback` (autofill / session restore). This matches native `<input type=\"radio\">`\n behaviour, which does not fire `change` on form reset. Note that internal form state\n (`ElementInternals.setFormValue`) is always updated regardless of suppression \u2014 only the\n event channel is silenced.\n- Does NOT re-fire from the `@Watch('checked')` watcher during the same tick as the native\n `change` handler, preventing a double-emission when the user clicks the radio."
386
+ },
387
+ "complexType": {
388
+ "original": "boolean",
389
+ "resolved": "boolean",
390
+ "references": {}
391
+ }
392
+ }, {
393
+ "method": "lmvzActivation",
394
+ "name": "lmvzActivation",
395
+ "bubbles": true,
396
+ "cancelable": true,
397
+ "composed": true,
398
+ "docs": {
399
+ "tags": [],
400
+ "text": "Fired on every explicit user activation of this radio \u2014 via click or Space key on the\nnative input. Fires even when the radio is already checked (re-activation). Use this\nevent to react to user intent; use `lmvzChange` to react to state transitions."
401
+ },
402
+ "complexType": {
403
+ "original": "void",
404
+ "resolved": "void",
405
+ "references": {}
406
+ }
407
+ }];
408
+ }
409
+ static get methods() {
410
+ return {
411
+ "focusInput": {
412
+ "complexType": {
413
+ "signature": "() => Promise<void>",
414
+ "parameters": [],
415
+ "references": {
416
+ "Promise": {
417
+ "location": "global",
418
+ "id": "global::Promise"
419
+ }
420
+ },
421
+ "return": "Promise<void>"
422
+ },
423
+ "docs": {
424
+ "text": "Sets focus on the native radio input.",
425
+ "tags": []
426
+ }
427
+ },
428
+ "checkValidity": {
429
+ "complexType": {
430
+ "signature": "() => Promise<boolean>",
431
+ "parameters": [],
432
+ "references": {
433
+ "Promise": {
434
+ "location": "global",
435
+ "id": "global::Promise"
436
+ }
437
+ },
438
+ "return": "Promise<boolean>"
439
+ },
440
+ "docs": {
441
+ "text": "Returns whether the radio satisfies its validation constraints.",
442
+ "tags": []
443
+ }
444
+ },
445
+ "reportValidity": {
446
+ "complexType": {
447
+ "signature": "() => Promise<boolean>",
448
+ "parameters": [],
449
+ "references": {
450
+ "Promise": {
451
+ "location": "global",
452
+ "id": "global::Promise"
453
+ }
454
+ },
455
+ "return": "Promise<boolean>"
456
+ },
457
+ "docs": {
458
+ "text": "Reports validation errors to the user.",
459
+ "tags": []
460
+ }
461
+ }
462
+ };
463
+ }
464
+ static get elementRef() { return "el"; }
465
+ static get watchers() {
466
+ return [{
467
+ "propName": "checked",
468
+ "methodName": "handleCheckedChange"
469
+ }, {
470
+ "propName": "value",
471
+ "methodName": "handleValueChange"
472
+ }, {
473
+ "propName": "label",
474
+ "methodName": "handleLabelChange"
475
+ }];
476
+ }
477
+ static get listeners() {
478
+ return [{
479
+ "name": "keydown",
480
+ "method": "handleKeydown",
481
+ "target": undefined,
482
+ "capture": false,
483
+ "passive": false
484
+ }];
485
+ }
486
+ static get attachInternalsMemberName() { return "internals"; }
487
+ }
@@ -59,7 +59,7 @@
59
59
  --lmvz-select-label-top-offset: calc(var(--lmvz-internal-select-floating-label-top-offset) * -1);
60
60
  --lmvz-select-label-minimized-padding-x: 4px;
61
61
  --lmvz-select-disabled-opacity: var(--lmvz-component-input-disabled-opacity, 40%);
62
- --lmvz-select-helper-color: var(--lmvz-semantic-color-on-surface-input-secondary, #7a7a7a);
62
+ --lmvz-select-helper-color: var(--lmvz-semantic-color-on-surface-input-secondary, #545454);
63
63
  --lmvz-select-focus-color: var(--lmvz-semantic-color-status-on-active, #0e7ab4);
64
64
  --lmvz-select-error-color: var(--lmvz-semantic-color-status-on-danger, #e52a31);
65
65
  }
@@ -125,8 +125,8 @@ div[aria-hidden] {
125
125
  background-color: var(--lmvz-select-bg-hover);
126
126
  }
127
127
  .select-wrapper:focus-within div[aria-hidden] {
128
- outline: 2px solid var(--lmvz-select-focus-color);
129
- outline-offset: 2px;
128
+ outline: var(--lmvz-ds-outline, 1px solid #0e7ab4);
129
+ outline-offset: var(--lmvz-ds-outline-offset, clamp(0.25rem, 0.19rem + 0.26vw, 0.5rem));
130
130
  }
131
131
  div[aria-hidden] > span:first-child {
132
132
  flex: 1 0 0;
@@ -50,7 +50,7 @@ export class LmvzSelect extends ReactiveControllerHost {
50
50
  render() {
51
51
  const hasValue = this.hasValue;
52
52
  const shouldShowLabel = hasValue;
53
- return (h(Host, { key: 'f4d3104f4022581e4661f2181eec5d56ac7027af' }, h("div", { key: '1f8b1fdf7c6d8c65390298e0cd9dca24ef4903d7', class: "select-wrapper" }, h("label", { key: 'ff7a2e509c637424387b38b163739183deda3cba', htmlFor: this.selectId, class: shouldShowLabel ? 'floating-label' : 'assistive-label' }, this.label, this.required && shouldShowLabel && h("span", { key: '7e3c03652d16dd1a20628d800ccae4221062d4b8', "aria-hidden": "true" }, " *")), h("div", { key: 'a2ee01b6ddfa98565fc1c41c9b9391091d254daf', "aria-hidden": "true" }, h("span", { key: 'c96a6960f693baca0ba48b44e569ad87c1bbc980' }, hasValue ? this.selectedLabel : this.label, this.required && !hasValue && h("span", { key: '4631b13509919f7bfd0e5a1287334cd3a8412e50', "aria-hidden": "true" }, " *")), h("span", { key: '4781647ee3a6a780e4253b9f92738c4645e20578' }, h("img", { key: 'c83dab75df9ff20ec40b63f45cbe8262d1c71d7d', src: chevronDownSvg, alt: "" }))), h("select", { key: '035b19878300ac1f7b04b61157e39587782b44f7', id: this.selectId, ref: (el) => (this.nativeSelectEl = el), name: this.name, disabled: this.disabled, required: this.required, "aria-label": this.label, onChange: this.handleChange }, !hasValue && h("option", { key: 'da76b299a1df9da8475e115b82d7e427cc659bfa', value: "", disabled: true, selected: true, hidden: true }), h("slot", { key: '1a91b540bc8ab97723df24c9c77d2bd52d941c92' }))), this.helperText && h("div", { key: '347fe4d805a58e03f2cb2ef427b0dba0b805e8be', role: "status" }, this.helperText)));
53
+ return (h(Host, { key: '597245455ffb9b5f83472a7970fb1c6c92017fd2' }, h("div", { key: 'edeb4d02d5a5291e60fd2d26d16edc500a355b63', class: "select-wrapper" }, h("label", { key: 'd0068817bb3586467d73284cecc03de393c37589', htmlFor: this.selectId, class: shouldShowLabel ? 'floating-label' : 'assistive-label' }, this.label, this.required && shouldShowLabel && h("span", { key: '624ee28842aed8c01651c7758099bccc446840d6', "aria-hidden": "true" }, " *")), h("div", { key: '184591bc8ac11e9eed17795ce21319591e6d4211', "aria-hidden": "true" }, h("span", { key: '53e673521ed26125c24fb529d6016e3827b47a44' }, hasValue ? this.selectedLabel : this.label, this.required && !hasValue && h("span", { key: '7af1a756e3343701ad066f3c107b2028126c5f09', "aria-hidden": "true" }, " *")), h("span", { key: '6210f2069758f8579f67780530fd294210875b3f' }, h("img", { key: '05aa6cf110ba0c7eacd36f59525144c61f0705d9', src: chevronDownSvg, alt: "" }))), h("select", { key: 'dc9dfe93226858f73f1d5a655388b9ce3a5e4037', id: this.selectId, ref: (el) => (this.nativeSelectEl = el), name: this.name, disabled: this.disabled, required: this.required, "aria-label": this.label, onChange: this.handleChange }, !hasValue && h("option", { key: '38ffb95d089932d0ce0c6a5629004679d3f7f857', value: "", disabled: true, selected: true, hidden: true }), h("slot", { key: '51b96884bb010b0a93f24b8b2f3f91a7b040e220' }))), this.helperText && h("div", { key: 'f7149a48024e87d2a3843d96674e45cb91fd9cf4', role: "status" }, this.helperText)));
54
54
  }
55
55
  static get is() { return "lmvz-select"; }
56
56
  static get encapsulation() { return "scoped"; }
@@ -0,0 +1,101 @@
1
+ :host {
2
+ position: fixed;
3
+ bottom: var(--lmvz-dimension-16-20, clamp(1rem, 0.94rem + 0.26vw, 1.25rem));
4
+ left: 50%;
5
+ transform: translateX(-50%);
6
+ z-index: 2147483000; /* TODO(tokens): promote to design-token */
7
+
8
+ width: max-content;
9
+ border: 1px solid transparent;
10
+ border-radius: var(--lmvz-semantic-border-radius-lg, 14px);
11
+ padding: var(--lmvz-dimension-10-12, clamp(0.63rem, 0.59rem + 0.13vw, 0.75rem)) var(--lmvz-dimension-12-14, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem));
12
+
13
+ display: flex;
14
+ flex-direction: row;
15
+ align-items: center;
16
+ justify-content: center;
17
+ gap: var(--lmvz-dimension-8-12, clamp(0.5rem, 0.44rem + 0.26vw, 0.75rem));
18
+
19
+ pointer-events: auto;
20
+ font: var(--lmvz-typography-body-md-strong, 500 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
21
+ Router);
22
+
23
+ /* this will be picked up by lmvz-icon as well */
24
+ --lmvz-component-color: var(--lmvz-semantic-color-status-on-success, #37867c);
25
+
26
+ color: var(--lmvz-component-color);
27
+ }
28
+
29
+ :host([status='success']) {
30
+ background-color: var(--lmvz-semantic-color-status-success, #f1f9f8);
31
+ border-color: var(--lmvz-semantic-color-status-on-success-subtle, #a5dad3);
32
+ --lmvz-component-color: var(--lmvz-semantic-color-status-on-success, #37867c);
33
+ }
34
+
35
+ :host([status='warning']) {
36
+ background-color: var(--lmvz-semantic-color-status-warning, #fffbf0);
37
+ border-color: var(--lmvz-semantic-color-status-on-warning-subtle, #ffdf75);
38
+ --lmvz-component-color: var(--lmvz-semantic-color-status-on-warning, #7a5e00);
39
+ }
40
+
41
+ :host([status='error']) {
42
+ background-color: var(--lmvz-semantic-color-status-danger, #fdf1f2);
43
+ border-color: var(--lmvz-semantic-color-status-on-danger-subtle, #f7bfc2);
44
+ --lmvz-component-color: var(--lmvz-semantic-color-status-on-danger, #e52a31);
45
+ }
46
+
47
+ lmvz-icon {
48
+ flex-shrink: 0;
49
+ }
50
+
51
+ .message {
52
+ white-space: nowrap;
53
+ }
54
+
55
+ @keyframes snackbar-enter {
56
+ from {
57
+ transform: translateX(-50%) translateY(100%);
58
+ opacity: 0;
59
+ }
60
+ to {
61
+ transform: translateX(-50%) translateY(0);
62
+ opacity: 1;
63
+ }
64
+ }
65
+
66
+ @keyframes snackbar-leave {
67
+ from {
68
+ transform: translateX(-50%) translateY(0);
69
+ opacity: 1;
70
+ }
71
+ to {
72
+ transform: translateX(-50%) translateY(100%);
73
+ opacity: 0;
74
+ }
75
+ }
76
+
77
+ /* var(--lmvz-global-duration-fast, 200ms) — token is unitless integer; separate ticket filed against packages/design-tokens */
78
+
79
+ :host(.entering) {
80
+ animation: snackbar-enter 200ms cubic-bezier(0, 0, 0.2, 1) forwards;
81
+ }
82
+
83
+ :host(.leaving) {
84
+ pointer-events: none;
85
+ animation: snackbar-leave 200ms cubic-bezier(0.4, 0, 1, 1) forwards;
86
+ }
87
+
88
+ @media (prefers-reduced-motion: reduce) {
89
+ :host(.entering) {
90
+ animation: none;
91
+ transition: opacity 80ms ease;
92
+ opacity: 1;
93
+ }
94
+
95
+ :host(.leaving) {
96
+ pointer-events: none;
97
+ animation: none;
98
+ transition: opacity 80ms ease;
99
+ opacity: 0;
100
+ }
101
+ }