@crowdstrike/glide-core 0.32.2 → 0.33.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 (59) hide show
  1. package/dist/accordion.js +3 -2
  2. package/dist/button-group.button.js +3 -2
  3. package/dist/button-group.js +3 -2
  4. package/dist/button.js +7 -11
  5. package/dist/button.styles.js +10 -8
  6. package/dist/checkbox-group.js +8 -7
  7. package/dist/checkbox.d.ts +1 -0
  8. package/dist/checkbox.js +26 -17
  9. package/dist/checkbox.styles.js +1 -1
  10. package/dist/drawer.js +3 -2
  11. package/dist/dropdown.js +19 -18
  12. package/dist/dropdown.option.d.ts +2 -0
  13. package/dist/dropdown.option.js +26 -25
  14. package/dist/form-controls-layout.js +3 -2
  15. package/dist/icon-button.js +2 -2
  16. package/dist/inline-alert.js +3 -2
  17. package/dist/input.js +9 -9
  18. package/dist/label.js +3 -2
  19. package/dist/library/assert-slot.js +2 -2
  20. package/dist/library/assert-slot.test.js +92 -0
  21. package/dist/link.js +2 -2
  22. package/dist/menu.js +83 -44
  23. package/dist/menu.styles.js +1 -0
  24. package/dist/modal.icon-button.js +3 -2
  25. package/dist/modal.js +3 -2
  26. package/dist/option.d.ts +5 -0
  27. package/dist/option.js +28 -5
  28. package/dist/options.d.ts +2 -0
  29. package/dist/options.group.js +3 -2
  30. package/dist/options.js +7 -8
  31. package/dist/options.styles.js +0 -6
  32. package/dist/popover.js +3 -2
  33. package/dist/radio-group.js +4 -3
  34. package/dist/radio-group.radio.js +3 -2
  35. package/dist/select.d.ts +90 -0
  36. package/dist/select.js +532 -0
  37. package/dist/slider.js +7 -7
  38. package/dist/spinner.js +2 -2
  39. package/dist/split-button.js +3 -2
  40. package/dist/split-button.primary-button.js +2 -2
  41. package/dist/split-button.primary-link.js +2 -2
  42. package/dist/split-button.secondary-button.js +2 -2
  43. package/dist/styles/opacity-and-scale-animation.js +2 -1
  44. package/dist/styles/variables.css +7 -4
  45. package/dist/tab.group.js +3 -2
  46. package/dist/tab.js +3 -2
  47. package/dist/tab.panel.js +3 -2
  48. package/dist/tag.js +2 -2
  49. package/dist/textarea.d.ts +1 -0
  50. package/dist/textarea.js +19 -10
  51. package/dist/toast.js +2 -2
  52. package/dist/toast.toasts.js +3 -2
  53. package/dist/toggle.d.ts +1 -0
  54. package/dist/toggle.js +13 -4
  55. package/dist/tooltip.container.js +3 -2
  56. package/dist/tooltip.js +4 -7
  57. package/package.json +4 -4
  58. package/dist/library/shadow-root-mode.d.ts +0 -2
  59. package/dist/library/shadow-root-mode.js +0 -4
package/dist/select.js ADDED
@@ -0,0 +1,532 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, LitElement } from 'lit';
8
+ import { createRef, ref } from 'lit/directives/ref.js';
9
+ import { customElement, property, state } from 'lit/decorators.js';
10
+ import packageJson from '../package.json' with { type: 'json' };
11
+ import assertSlot from './library/assert-slot.js';
12
+ import styles from './menu.styles.js';
13
+ import final from './library/final.js';
14
+ import Menu from './menu.js';
15
+ import Option from './option.js';
16
+ import Options from './options.js';
17
+ import OptionsGroup from './options.group.js';
18
+ /**
19
+ * @attr {boolean} [disabled=false]
20
+ * @attr {boolean} [loading=false]
21
+ * @attr {string} [name='']
22
+ * @attr {number} [offset=4]
23
+ * @attr {boolean} [open=false]
24
+ * @attr {'bottom'|'left'|'right'|'top'|'bottom-start'|'bottom-end'|'left-start'|'left-end'|'right-start'|'right-end'|'top-start'|'top-end'} [placement='bottom-start'] - Select will try to move itself to the opposite of this value if not doing so would result in overflow. For example, if "bottom" results in overflow Menu will try "top" but not "right" or "left".
25
+ * @attr {boolean} [required=false]
26
+ * @attr {string[]} [value=[]]
27
+ *
28
+ * @readonly
29
+ * @attr {string} [version]
30
+ *
31
+ * @slot {Element}
32
+ * @slot {Element} target - The element to which Select will anchor. Can be any focusable element. If you want Select to be filterable, put an Input in this slot. Listen for Input's "input" event, then add and remove Option(s) from Select's default slot based on Input's value.
33
+ *
34
+ * @fires {Event} change
35
+ * @fires {Event} input
36
+ *
37
+ * @readonly
38
+ * @prop {HTMLFormElement | null} form
39
+ *
40
+ * @readonly
41
+ * @prop {ValidityState} validity
42
+ *
43
+ * @method checkValidity
44
+ * @returns boolean
45
+ *
46
+ * @method formAssociatedCallback
47
+ * @method formResetCallback
48
+ *
49
+ * @method reportValidity
50
+ * @returns boolean
51
+ *
52
+ * @method setValidity
53
+ * @param {ValidityStateFlags} [flags]
54
+ */
55
+ let Select = class Select extends LitElement {
56
+ static { this.formAssociated = true; }
57
+ /* c8 ignore start */
58
+ static { this.shadowRootOptions = {
59
+ ...LitElement.shadowRootOptions,
60
+ mode: window.navigator.webdriver ? 'open' : 'closed',
61
+ }; }
62
+ /* c8 ignore end */
63
+ static { this.styles = styles; }
64
+ /**
65
+ * @default 4
66
+ */
67
+ get offset() {
68
+ return (this.#offset ??
69
+ Number.parseFloat(window
70
+ .getComputedStyle(document.body)
71
+ .getPropertyValue('--glide-core-spacing-base-xxs')) *
72
+ Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize));
73
+ }
74
+ /* v8 ignore start */
75
+ set offset(offset) {
76
+ this.#offset = offset;
77
+ }
78
+ /* v8 ignore end */
79
+ /**
80
+ * @default false
81
+ */
82
+ get open() {
83
+ return this.#isOpen;
84
+ }
85
+ set open(isOpen) {
86
+ this.#isOpen = isOpen;
87
+ if (this.#menuElementRef.value) {
88
+ this.#menuElementRef.value.open = isOpen;
89
+ }
90
+ }
91
+ /**
92
+ * @default false
93
+ */
94
+ get required() {
95
+ return this.#isRequired;
96
+ }
97
+ set required(isRequired) {
98
+ this.#isRequired = isRequired;
99
+ this.#setValidity();
100
+ }
101
+ /**
102
+ * @default []
103
+ */
104
+ get value() {
105
+ return this.#value;
106
+ }
107
+ set value(value) {
108
+ if (value.length > 1) {
109
+ throw this.#tooManySelectedOptionsError;
110
+ }
111
+ this.#value = value;
112
+ if (this.#optionElements) {
113
+ for (const option of this.#optionElements) {
114
+ this.#isSelectionFromValueSetter = true;
115
+ option.selected = false;
116
+ this.#isSelectionFromValueSetter = false;
117
+ }
118
+ }
119
+ for (const value$ of value) {
120
+ const option = this.#optionElements?.find((option) => option.value === value$);
121
+ if (option) {
122
+ this.#isSelectionFromValueSetter = true;
123
+ option.selected = true;
124
+ this.#isSelectionFromValueSetter = false;
125
+ }
126
+ }
127
+ this.#setValidity();
128
+ }
129
+ get form() {
130
+ return this.#internals.form;
131
+ }
132
+ checkValidity() {
133
+ this.isCheckingValidity = true;
134
+ const isValid = this.#internals.checkValidity();
135
+ this.isCheckingValidity = false;
136
+ return isValid;
137
+ }
138
+ firstUpdated() {
139
+ const options = this.querySelector('glide-core-options');
140
+ if (options) {
141
+ options.role = 'listbox';
142
+ }
143
+ const hasNoSelectedOptions = this.#optionElements?.every(({ selected }) => !selected);
144
+ // When `value` is set on initial render, its setter is called before
145
+ // `connectedCallback()` and thus before the default slot has any assigned
146
+ // elements. So we select options here after the initial render is complete
147
+ // and `this.#optionElements` isn't empty.
148
+ //
149
+ // Additionally, `#onDefaultSlotSlotChange()` is called after `firstUpdated()`
150
+ // and sets `value` based on which options are selected. And the initial `value`
151
+ // may conflict with the one derived from which options are selected.
152
+ //
153
+ // So we have a decision to make. On first render, do we defer to the initial
154
+ // `value` and select and deselect options below? Or do we defer to
155
+ // `#onDefaultSlotSlotChange()` and let that method change `value` from its initial
156
+ // value?
157
+ //
158
+ // It's largely a toss-up. But the latter seems like the logical choice given
159
+ // `#onDefaultSlotSlotChange()` is called after `firstUpdated()`. In other words,
160
+ // we defer to the lifecycle. `#onDefaultSlotSlotChange()` is called second. So
161
+ // it gets to override what `value` was initially.
162
+ //
163
+ // If no options are selected, then it's obvious that the consumer's intention is
164
+ // to select options based on the initial `value`. So we proceed.
165
+ if (hasNoSelectedOptions) {
166
+ if (this.value.length > 1) {
167
+ throw this.#tooManySelectedOptionsError;
168
+ }
169
+ for (const value of this.value) {
170
+ const option = this.#optionElements?.find((option) => option.value === value);
171
+ if (option) {
172
+ option.selected = true;
173
+ }
174
+ }
175
+ }
176
+ if (this.open && this.#menuElementRef.value) {
177
+ // Simply passing `this.open` to Menu in the template below would be more
178
+ // convenient. But, when an attribute's value is an expression, Lit will set the
179
+ // attribute on a slight delay, and that's a problem when a sub-Menu is also
180
+ // initially open because it means the sub-Menu wil be opened before the top-level
181
+ // Menu. So the top-level Menu below will be positioned underneath the sub-Menu.
182
+ this.#menuElementRef.value.open = true;
183
+ }
184
+ }
185
+ formAssociatedCallback() {
186
+ this.form?.addEventListener('formdata', this.#onFormdata);
187
+ }
188
+ formResetCallback() {
189
+ if (this.#optionElements) {
190
+ for (const option of this.#optionElements) {
191
+ option.selected = option.hasAttribute('selected');
192
+ if (option.selected) {
193
+ this.#value = [option.value];
194
+ }
195
+ }
196
+ }
197
+ }
198
+ render() {
199
+ // Lit-a11y doesn't know that we're not interested in certain keys being pressed.
200
+ //
201
+ /* eslint-disable lit-a11y/click-events-have-key-events */
202
+ return html `<glide-core-menu
203
+ offset=${this.offset}
204
+ placement=${this.placement}
205
+ ?loading=${this.loading}
206
+ @toggle=${this.#onMenuToggle}
207
+ ${ref(this.#menuElementRef)}
208
+ >
209
+ <slot
210
+ name="target"
211
+ slot="target"
212
+ @click=${this.#onTargetSlotClick}
213
+ @keydown=${this.#onTargetSlotKeyDown}
214
+ @slotchange=${this.#onTargetSlotChange}
215
+ ${assertSlot([Element])}
216
+ ${ref(this.#targetSlotElementRef)}
217
+ >
218
+ <!--
219
+ The element to which Select will anchor. Can be any focusable element.
220
+
221
+ If you want Select to be filterable, put an Input in this slot. Listen for Input's
222
+ "input" event, then add and remove Option(s) from Select's default slot based on
223
+ Input's value.
224
+
225
+ @required
226
+ @type {Element}
227
+ -->
228
+ </slot>
229
+
230
+ <slot
231
+ @click=${this.#onDefaultSlotClick}
232
+ @deselected=${this.#onDefaultSlotDeselected}
233
+ @disabled=${this.#onDefaultSlotDisabled}
234
+ @selected=${this.#onDefaultSlotSelected}
235
+ @slotchange=${this.#onDefaultSlotSlotChange}
236
+ ${ref(this.#defaultSlotElementRef)}
237
+ >
238
+ <!--
239
+ @required
240
+ @type {Element}
241
+ -->
242
+ </slot>
243
+ </glide-core-menu>`;
244
+ }
245
+ reportValidity() {
246
+ return this.#internals.reportValidity();
247
+ }
248
+ setValidity(flags) {
249
+ this.#hasCustomValidity = true;
250
+ this.#internals.setValidity(flags, ' ',
251
+ // `setValidity()` isn't typed for an SVG. But an SVG is valid as long as it's
252
+ // focusable. Thus the cast.
253
+ this.#targetElement);
254
+ }
255
+ get validity() {
256
+ return this.#internals.validity;
257
+ }
258
+ constructor() {
259
+ super();
260
+ this.disabled = false;
261
+ this.loading = false;
262
+ this.name = '';
263
+ /**
264
+ * Select will try to move itself to the opposite of this value if not doing so would result in overflow.
265
+ * For example, if "bottom" results in overflow Menu will try "top" but not "right" or "left".
266
+ */
267
+ this.placement = 'bottom-start';
268
+ this.version = packageJson.version;
269
+ this.isCheckingValidity = false;
270
+ this.#defaultSlotElementRef = createRef();
271
+ this.#hasCustomValidity = false;
272
+ this.#hasEmittedAnInvalidEvent = false;
273
+ this.#isOpen = false;
274
+ this.#isRequired = false;
275
+ this.#isSelectionFromValueSetter = false;
276
+ this.#isTargetClickViaEnter = false;
277
+ this.#menuElementRef = createRef();
278
+ this.#targetSlotElementRef = createRef();
279
+ this.#tooManySelectedOptionsError = new Error('Only one option may be selected at a time.');
280
+ this.#value = [];
281
+ // An arrow function field instead of a method so `this` is closed over and
282
+ // set to the component instead of the form.
283
+ this.#onFormdata = ({ formData }) => {
284
+ if (this.name && this.value.length > 0 && !this.disabled) {
285
+ formData.append(this.name, JSON.stringify(this.value));
286
+ }
287
+ };
288
+ this.#internals = this.attachInternals();
289
+ // Event handlers on the host aren't great because consumers can remove them.
290
+ // Unfortunately, the host is the only thing on which this event is dispatched
291
+ // because it's the host that is form-associated.
292
+ this.addEventListener('invalid', (event) => {
293
+ // Canceled so the native validation message isn't shown.
294
+ event.preventDefault();
295
+ if (this.isCheckingValidity) {
296
+ return;
297
+ }
298
+ this.#hasEmittedAnInvalidEvent = true;
299
+ const isFirstInvalidFormElement = this.form?.querySelector(':invalid') === this;
300
+ if (isFirstInvalidFormElement) {
301
+ // Canceling the event means the target won't get focus, even if we were to use
302
+ // `delegatesFocus`. So we have to it focus manually.
303
+ this.#targetElement?.focus();
304
+ }
305
+ if (this.#targetElement) {
306
+ this.#targetElement.ariaInvalid = this.validity.valid
307
+ ? 'false'
308
+ : 'true';
309
+ }
310
+ });
311
+ }
312
+ #defaultSlotElementRef;
313
+ #hasCustomValidity;
314
+ #hasEmittedAnInvalidEvent;
315
+ #internals;
316
+ #isOpen;
317
+ #isRequired;
318
+ #isSelectionFromValueSetter;
319
+ #isTargetClickViaEnter;
320
+ #menuElementRef;
321
+ #offset;
322
+ #targetSlotElementRef;
323
+ #tooManySelectedOptionsError;
324
+ #value;
325
+ get #optionElements() {
326
+ if (this.#optionsElement) {
327
+ return [...this.#optionsElement.children]
328
+ .filter((element) => {
329
+ return element instanceof Option || element instanceof OptionsGroup;
330
+ })
331
+ .flatMap((element) => {
332
+ return element instanceof OptionsGroup
333
+ ? [
334
+ ...element.querySelectorAll(':scope > glide-core-option'),
335
+ ]
336
+ : element;
337
+ });
338
+ }
339
+ }
340
+ get #optionsElement() {
341
+ const firstAssignedElement = this.#defaultSlotElementRef.value
342
+ ?.assignedElements({ flatten: true })
343
+ .at(0);
344
+ return firstAssignedElement instanceof Options
345
+ ? firstAssignedElement
346
+ : null;
347
+ }
348
+ // An arrow function field instead of a method so `this` is closed over and
349
+ // set to the component instead of the form.
350
+ #onFormdata;
351
+ #onDefaultSlotClick(event) {
352
+ const isSubMenuOption = this.#optionElements?.every((option) => option !== event.target);
353
+ if (isSubMenuOption) {
354
+ return;
355
+ }
356
+ if (event.target instanceof Option && !event.target.selected) {
357
+ if (this.#optionElements) {
358
+ for (const option of this.#optionElements) {
359
+ if (option.selected) {
360
+ option.selected = false;
361
+ }
362
+ }
363
+ }
364
+ if (this.#menuElementRef.value) {
365
+ // Menu waits a tick or so before closing after an Option is clicked to give its
366
+ // consumers a chance to cancel the event and prevent Menu from closing.
367
+ //
368
+ // When `selected` is set below, the Option will rerender to include a checkmark.
369
+ // If the Option has a sub-Menu, the Option will also move its sub-Menu target so
370
+ // it's to the left of the checkmark.
371
+ //
372
+ // Because Menu doesn't close immediately, the user will see the checkmark suddenly
373
+ // appear and the sub-Menu's target move moments before Menu closes.
374
+ //
375
+ // To avoid all that, we close Menu ourselves before setting `selected`.
376
+ this.#menuElementRef.value.open = false;
377
+ }
378
+ event.target.selected = true;
379
+ this.#value = [event.target.value];
380
+ this.dispatchEvent(new Event('input', {
381
+ bubbles: true,
382
+ composed: true,
383
+ }));
384
+ this.dispatchEvent(new Event('change', {
385
+ bubbles: true,
386
+ composed: true,
387
+ }));
388
+ }
389
+ }
390
+ #onDefaultSlotDeselected() {
391
+ if (this.#isSelectionFromValueSetter) {
392
+ return;
393
+ }
394
+ this.#value = [];
395
+ this.#setValidity();
396
+ }
397
+ #onDefaultSlotDisabled(event) {
398
+ if (event.target instanceof Option && event.target.selected) {
399
+ event.target.selected = false;
400
+ }
401
+ }
402
+ #onDefaultSlotSelected(event) {
403
+ if (this.#targetElement) {
404
+ // The `label` of the selected Option(s) should actually be read before the label
405
+ // or text content of the target. But we don't always know what the target's label
406
+ // is because the target is an arbitrary element.
407
+ //
408
+ // For example, it could be a custom element without `textContent`. Button is like
409
+ // this. Button doesn't have any `textContent` because nothing gets slotted into
410
+ // it. Yet it is labeled.
411
+ //
412
+ // So the best we can do is set `ariaDescription`.
413
+ this.#targetElement.ariaDescription = this.#optionElements
414
+ ? this.#optionElements
415
+ .filter(({ selected }) => selected)
416
+ .map(({ label }) => label)
417
+ .join(',')
418
+ : '';
419
+ }
420
+ if (this.#isSelectionFromValueSetter) {
421
+ return;
422
+ }
423
+ if (event.target instanceof Option && this.#optionElements) {
424
+ for (const option of this.#optionElements) {
425
+ if (option !== event.target) {
426
+ option.selected = false;
427
+ }
428
+ }
429
+ this.#value = [event.target.value];
430
+ }
431
+ this.#setValidity();
432
+ }
433
+ #onDefaultSlotSlotChange() {
434
+ const selectedOptions = this.#optionElements &&
435
+ this.#optionElements.filter(({ selected }) => selected);
436
+ if (selectedOptions && selectedOptions.length > 1) {
437
+ throw this.#tooManySelectedOptionsError;
438
+ }
439
+ const selectedOption = selectedOptions?.at(0);
440
+ if (selectedOption) {
441
+ this.#value = [selectedOption.value];
442
+ }
443
+ if (this.#optionElements) {
444
+ for (const option of this.#optionElements) {
445
+ option.role = 'option';
446
+ }
447
+ }
448
+ this.#setValidity();
449
+ }
450
+ #onMenuToggle(event) {
451
+ if (event.target instanceof Menu &&
452
+ event.target === this.#menuElementRef.value) {
453
+ this.open = event.target.open;
454
+ }
455
+ }
456
+ #onTargetSlotChange() {
457
+ if (this.#targetElement) {
458
+ this.#targetElement.ariaInvalid =
459
+ !this.#hasEmittedAnInvalidEvent || this.validity.valid
460
+ ? 'false'
461
+ : 'true';
462
+ }
463
+ }
464
+ #onTargetSlotClick(event) {
465
+ if (this.#isTargetClickViaEnter) {
466
+ this.#isTargetClickViaEnter = false;
467
+ event.preventDefault(); // Prevent Menu from opening.
468
+ }
469
+ }
470
+ #onTargetSlotKeyDown(event) {
471
+ if (event.key === 'Enter' && !this.open) {
472
+ this.#isTargetClickViaEnter = true;
473
+ this.form?.requestSubmit();
474
+ }
475
+ }
476
+ #setValidity() {
477
+ if (this.#hasCustomValidity) {
478
+ return;
479
+ }
480
+ if (this.required && this.value.length === 0) {
481
+ this.#internals.setValidity({ valueMissing: true }, ' ',
482
+ // `setValidity()` isn't typed for an SVG. But an SVG is valid as long as it's
483
+ // focusable. Thus the cast.
484
+ this.#targetElement);
485
+ return;
486
+ }
487
+ this.#internals.setValidity({});
488
+ }
489
+ get #targetElement() {
490
+ const element = this.#targetSlotElementRef.value
491
+ ?.assignedElements({ flatten: true })
492
+ .at(0);
493
+ if (element instanceof HTMLElement || element instanceof SVGElement) {
494
+ return element;
495
+ }
496
+ }
497
+ };
498
+ __decorate([
499
+ property({ type: Boolean, reflect: true })
500
+ ], Select.prototype, "disabled", void 0);
501
+ __decorate([
502
+ property({ reflect: true, type: Boolean })
503
+ ], Select.prototype, "loading", void 0);
504
+ __decorate([
505
+ property({ reflect: true, useDefault: true })
506
+ ], Select.prototype, "name", void 0);
507
+ __decorate([
508
+ property({ reflect: true, type: Number })
509
+ ], Select.prototype, "offset", null);
510
+ __decorate([
511
+ property({ type: Boolean, reflect: true })
512
+ ], Select.prototype, "open", null);
513
+ __decorate([
514
+ property({ reflect: true, useDefault: true })
515
+ ], Select.prototype, "placement", void 0);
516
+ __decorate([
517
+ property({ reflect: true, type: Boolean })
518
+ ], Select.prototype, "required", null);
519
+ __decorate([
520
+ property({ type: Array })
521
+ ], Select.prototype, "value", null);
522
+ __decorate([
523
+ property({ reflect: true })
524
+ ], Select.prototype, "version", void 0);
525
+ __decorate([
526
+ state()
527
+ ], Select.prototype, "isCheckingValidity", void 0);
528
+ Select = __decorate([
529
+ customElement('glide-core-select'),
530
+ final
531
+ ], Select);
532
+ export default Select;
package/dist/slider.js CHANGED
@@ -15,7 +15,6 @@ import { when } from 'lit/directives/when.js';
15
15
  import packageJson from '../package.json' with { type: 'json' };
16
16
  import { LocalizeController } from './library/localize.js';
17
17
  import styles from './slider.styles.js';
18
- import shadowRootMode from './library/shadow-root-mode.js';
19
18
  import final from './library/final.js';
20
19
  import required from './library/required.js';
21
20
  /**
@@ -68,9 +67,10 @@ import required from './library/required.js';
68
67
  */
69
68
  let Slider = class Slider extends LitElement {
70
69
  static { this.formAssociated = true; }
70
+ /* c8 ignore start */
71
71
  static { this.shadowRootOptions = {
72
72
  ...LitElement.shadowRootOptions,
73
- mode: shadowRootMode,
73
+ mode: window.navigator.webdriver ? 'open' : 'closed',
74
74
  delegatesFocus: true,
75
75
  }; }
76
76
  static { this.styles = styles; }
@@ -592,7 +592,7 @@ let Slider = class Slider extends LitElement {
592
592
  reportValidity() {
593
593
  this.isReportValidityOrSubmit = true;
594
594
  const isValid = this.#internals.reportValidity();
595
- // Ensures that getters referencing `this.validity.valid` are updated.
595
+ // Ensures getters referencing `this.validity.valid` re-run.
596
596
  this.requestUpdate();
597
597
  return isValid;
598
598
  }
@@ -801,8 +801,8 @@ let Slider = class Slider extends LitElement {
801
801
  const normalizedValue = Math.round(inputValue / this.step) * this.step;
802
802
  this.maximumValue = Math.min(Math.max(normalizedValue, this.minimumValue + this.step), this.max);
803
803
  this.#updateHandlesAndTrack();
804
- // Unlike "input" events, "change" events aren't composed. So
805
- // we have to manually dispatch them.
804
+ // Unlike "input" events, "change" events aren't composed. So we have to manually
805
+ // dispatch them.
806
806
  this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
807
807
  }
808
808
  }
@@ -842,8 +842,8 @@ let Slider = class Slider extends LitElement {
842
842
  // can't go higher than 70 (75-5).
843
843
  this.maximumValue - this.step);
844
844
  this.#updateHandlesAndTrack();
845
- // Unlike "input" events, "change" events aren't composed. So
846
- // we have to manually dispatch them.
845
+ // Unlike "input" events, "change" events aren't composed. So we have to manually
846
+ // dispatch them.
847
847
  this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
848
848
  }
849
849
  }
package/dist/spinner.js CHANGED
@@ -10,7 +10,6 @@ import { customElement, property } from 'lit/decorators.js';
10
10
  import { ifDefined } from 'lit/directives/if-defined.js';
11
11
  import packageJson from '../package.json' with { type: 'json' };
12
12
  import styles from './spinner.styles.js';
13
- import shadowRootMode from './library/shadow-root-mode.js';
14
13
  import final from './library/final.js';
15
14
  import required from './library/required.js';
16
15
  /**
@@ -26,10 +25,11 @@ let Spinner = class Spinner extends LitElement {
26
25
  this.size = 'medium';
27
26
  this.version = packageJson.version;
28
27
  }
28
+ /* c8 ignore start */
29
29
  static { this.shadowRootOptions = {
30
30
  ...LitElement.shadowRootOptions,
31
31
  delegatesFocus: true,
32
- mode: shadowRootMode,
32
+ mode: window.navigator.webdriver ? 'open' : 'closed',
33
33
  }; }
34
34
  static { this.styles = styles; }
35
35
  render() {
@@ -13,7 +13,6 @@ import SplitButtonPrimaryLink from './split-button.primary-link.js';
13
13
  import SplitButtonSecondaryButton from './split-button.secondary-button.js';
14
14
  import styles from './split-button.styles.js';
15
15
  import assertSlot from './library/assert-slot.js';
16
- import shadowRootMode from './library/shadow-root-mode.js';
17
16
  import final from './library/final.js';
18
17
  /**
19
18
  * @attr {'primary'|'secondary'} [variant='primary']
@@ -32,10 +31,12 @@ let SplitButton = class SplitButton extends LitElement {
32
31
  this.#secondaryButtonSlotElementRef = createRef();
33
32
  this.#variant = 'primary';
34
33
  }
34
+ /* c8 ignore start */
35
35
  static { this.shadowRootOptions = {
36
36
  ...LitElement.shadowRootOptions,
37
- mode: shadowRootMode,
37
+ mode: window.navigator.webdriver ? 'open' : 'closed',
38
38
  }; }
39
+ /* c8 ignore end */
39
40
  static { this.styles = styles; }
40
41
  /**
41
42
  * @default 'primary'
@@ -10,7 +10,6 @@ import { customElement, property } from 'lit/decorators.js';
10
10
  import { ifDefined } from 'lit/directives/if-defined.js';
11
11
  import packageJson from '../package.json' with { type: 'json' };
12
12
  import styles from './split-button.primary-button.styles.js';
13
- import shadowRootMode from './library/shadow-root-mode.js';
14
13
  import final from './library/final.js';
15
14
  import required from './library/required.js';
16
15
  /**
@@ -36,10 +35,11 @@ let SplitButtonPrimaryButton = class SplitButtonPrimaryButton extends LitElement
36
35
  this.privateVariant = 'primary';
37
36
  this.version = packageJson.version;
38
37
  }
38
+ /* c8 ignore start */
39
39
  static { this.shadowRootOptions = {
40
40
  ...LitElement.shadowRootOptions,
41
41
  delegatesFocus: true,
42
- mode: shadowRootMode,
42
+ mode: window.navigator.webdriver ? 'open' : 'closed',
43
43
  }; }
44
44
  static { this.styles = styles; }
45
45
  render() {
@@ -10,7 +10,6 @@ import { customElement, property } from 'lit/decorators.js';
10
10
  import { ifDefined } from 'lit/directives/if-defined.js';
11
11
  import packageJson from '../package.json' with { type: 'json' };
12
12
  import styles from './split-button.primary-button.styles.js';
13
- import shadowRootMode from './library/shadow-root-mode.js';
14
13
  import final from './library/final.js';
15
14
  import required from './library/required.js';
16
15
  /**
@@ -31,10 +30,11 @@ let SplitButtonPrimaryLink = class SplitButtonPrimaryLink extends LitElement {
31
30
  this.privateVariant = 'primary';
32
31
  this.version = packageJson.version;
33
32
  }
33
+ /* c8 ignore start */
34
34
  static { this.shadowRootOptions = {
35
35
  ...LitElement.shadowRootOptions,
36
36
  delegatesFocus: true,
37
- mode: shadowRootMode,
37
+ mode: window.navigator.webdriver ? 'open' : 'closed',
38
38
  }; }
39
39
  static { this.styles = styles; }
40
40
  render() {
@@ -15,7 +15,6 @@ import Menu from './menu.js';
15
15
  import chevronIcon from './icons/chevron.js';
16
16
  import styles from './split-button.secondary-button.styles.js';
17
17
  import assertSlot from './library/assert-slot.js';
18
- import shadowRootMode from './library/shadow-root-mode.js';
19
18
  import final from './library/final.js';
20
19
  import required from './library/required.js';
21
20
  import Option from './option.js';
@@ -42,10 +41,11 @@ let SplitButtonSecondaryButton = class SplitButtonSecondaryButton extends LitEle
42
41
  this.#buttonElementRef = createRef();
43
42
  this.#menuElementRef = createRef();
44
43
  }
44
+ /* c8 ignore start */
45
45
  static { this.shadowRootOptions = {
46
46
  ...LitElement.shadowRootOptions,
47
47
  delegatesFocus: true,
48
- mode: shadowRootMode,
48
+ mode: window.navigator.webdriver ? 'open' : 'closed',
49
49
  }; }
50
50
  static { this.styles = styles; }
51
51
  click() {