@crowdstrike/glide-core 0.9.6 → 0.10.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 (207) hide show
  1. package/README.md +17 -53
  2. package/dist/accordion.d.ts +10 -10
  3. package/dist/accordion.js +1 -1
  4. package/dist/accordion.stories.d.ts +0 -1
  5. package/dist/accordion.styles.js +36 -38
  6. package/dist/accordion.test.basics.js +13 -95
  7. package/dist/accordion.test.events.js +21 -33
  8. package/dist/accordion.test.focus.d.ts +1 -0
  9. package/dist/accordion.test.focus.js +11 -0
  10. package/dist/accordion.test.interactions.d.ts +1 -0
  11. package/dist/accordion.test.interactions.js +75 -0
  12. package/dist/button-group.button.d.ts +2 -4
  13. package/dist/button-group.button.js +1 -1
  14. package/dist/button-group.button.styles.js +6 -14
  15. package/dist/button-group.button.test.basics.js +8 -17
  16. package/dist/button-group.button.test.interactions.js +4 -4
  17. package/dist/button-group.d.ts +0 -2
  18. package/dist/button-group.test.basics.js +10 -10
  19. package/dist/button-group.test.events.js +2 -2
  20. package/dist/button-group.test.interactions.js +1 -1
  21. package/dist/button.d.ts +7 -10
  22. package/dist/button.js +1 -1
  23. package/dist/button.styles.js +4 -7
  24. package/dist/button.test.basics.js +10 -26
  25. package/dist/button.test.events.js +9 -9
  26. package/dist/checkbox-group.d.ts +3 -4
  27. package/dist/checkbox-group.js +1 -1
  28. package/dist/checkbox-group.styles.js +13 -1
  29. package/dist/checkbox-group.test.basics.js +8 -12
  30. package/dist/checkbox-group.test.focus.js +7 -7
  31. package/dist/checkbox-group.test.interactions.d.ts +1 -0
  32. package/dist/checkbox-group.test.interactions.js +82 -0
  33. package/dist/checkbox.d.ts +5 -4
  34. package/dist/checkbox.js +1 -1
  35. package/dist/checkbox.styles.js +35 -15
  36. package/dist/checkbox.test.basics.js +6 -15
  37. package/dist/checkbox.test.focus.js +4 -2
  38. package/dist/checkbox.test.interactions.js +11 -11
  39. package/dist/drawer.d.ts +2 -5
  40. package/dist/drawer.js +1 -1
  41. package/dist/drawer.test.accessibility.js +8 -8
  42. package/dist/drawer.test.basics.js +16 -16
  43. package/dist/drawer.test.closing.js +18 -16
  44. package/dist/drawer.test.events.js +13 -24
  45. package/dist/drawer.test.methods.js +22 -22
  46. package/dist/dropdown.d.ts +7 -5
  47. package/dist/dropdown.js +1 -1
  48. package/dist/dropdown.option.d.ts +1 -3
  49. package/dist/dropdown.option.js +1 -1
  50. package/dist/dropdown.option.styles.js +31 -19
  51. package/dist/dropdown.option.test.basics.js +4 -4
  52. package/dist/dropdown.styles.js +39 -3
  53. package/dist/dropdown.test.basics.js +8 -13
  54. package/dist/dropdown.test.basics.multiple.js +63 -31
  55. package/dist/dropdown.test.basics.single.js +49 -0
  56. package/dist/dropdown.test.focus.filterable.js +12 -3
  57. package/dist/dropdown.test.focus.js +18 -2
  58. package/dist/dropdown.test.interactions.filterable.js +121 -45
  59. package/dist/dropdown.test.interactions.multiple.js +71 -30
  60. package/dist/dropdown.test.interactions.single.js +26 -4
  61. package/dist/form-controls-layout.d.ts +0 -2
  62. package/dist/icon-button.d.ts +2 -4
  63. package/dist/icon-button.js +1 -1
  64. package/dist/icon-button.test.basics.js +14 -82
  65. package/dist/icon-button.test.focus.d.ts +1 -0
  66. package/dist/icon-button.test.focus.js +13 -0
  67. package/dist/input.d.ts +4 -5
  68. package/dist/input.js +1 -1
  69. package/dist/input.styles.js +4 -4
  70. package/dist/input.test.basics.js +0 -52
  71. package/dist/input.test.events.js +27 -27
  72. package/dist/input.test.focus.js +27 -26
  73. package/dist/input.test.form.js +6 -6
  74. package/dist/input.test.validity.js +130 -130
  75. package/dist/label.d.ts +1 -3
  76. package/dist/label.js +1 -1
  77. package/dist/label.styles.js +5 -6
  78. package/dist/label.test.basics.js +4 -4
  79. package/dist/library/ow.js +1 -1
  80. package/dist/menu.button.d.ts +0 -2
  81. package/dist/menu.button.test.basics.js +3 -3
  82. package/dist/menu.d.ts +1 -4
  83. package/dist/menu.js +1 -1
  84. package/dist/menu.link.d.ts +1 -2
  85. package/dist/menu.link.js +1 -1
  86. package/dist/menu.options.d.ts +0 -2
  87. package/dist/menu.test.events.js +6 -6
  88. package/dist/menu.test.focus.js +5 -18
  89. package/dist/menu.test.interactions.js +48 -24
  90. package/dist/modal.d.ts +6 -17
  91. package/dist/modal.icon-button.d.ts +0 -2
  92. package/dist/modal.icon-button.test.basics.js +3 -3
  93. package/dist/modal.js +1 -1
  94. package/dist/modal.styles.js +13 -19
  95. package/dist/modal.tertiary-icon.d.ts +0 -3
  96. package/dist/modal.tertiary-icon.test.basics.js +3 -3
  97. package/dist/modal.test.basics.js +9 -5
  98. package/dist/modal.test.close.js +2 -2
  99. package/dist/modal.test.events.js +2 -2
  100. package/dist/radio-group.d.ts +0 -3
  101. package/dist/radio-group.js +1 -1
  102. package/dist/radio-group.test.basics.js +61 -61
  103. package/dist/radio-group.test.events.js +13 -13
  104. package/dist/radio-group.test.focus.js +1 -1
  105. package/dist/radio-group.test.form.js +2 -2
  106. package/dist/radio-group.test.validity.js +12 -12
  107. package/dist/radio.d.ts +0 -3
  108. package/dist/radio.styles.js +4 -12
  109. package/dist/split-button.d.ts +8 -11
  110. package/dist/split-button.js +1 -1
  111. package/dist/split-button.primary-button.d.ts +21 -0
  112. package/dist/split-button.primary-button.js +1 -0
  113. package/dist/split-button.primary-button.styles.js +96 -0
  114. package/dist/split-button.primary-button.test.basics.d.ts +1 -0
  115. package/dist/split-button.primary-button.test.basics.js +31 -0
  116. package/dist/split-button.primary-button.test.focus.d.ts +1 -0
  117. package/dist/split-button.primary-button.test.focus.js +14 -0
  118. package/dist/split-button.primary-link.d.ts +19 -0
  119. package/dist/split-button.primary-link.js +1 -0
  120. package/dist/split-button.primary-link.test.basics.d.ts +1 -0
  121. package/dist/split-button.primary-link.test.basics.js +30 -0
  122. package/dist/split-button.primary-link.test.focus.d.ts +1 -0
  123. package/dist/split-button.primary-link.test.focus.js +15 -0
  124. package/dist/split-button.secondary-button.d.ts +25 -0
  125. package/dist/split-button.secondary-button.js +1 -0
  126. package/dist/split-button.secondary-button.styles.js +103 -0
  127. package/dist/split-button.secondary-button.test.basics.d.ts +1 -0
  128. package/dist/split-button.secondary-button.test.basics.js +58 -0
  129. package/dist/split-button.secondary-button.test.focus.d.ts +1 -0
  130. package/dist/split-button.secondary-button.test.focus.js +14 -0
  131. package/dist/split-button.secondary-button.test.interactions.d.ts +2 -0
  132. package/dist/split-button.secondary-button.test.interactions.js +30 -0
  133. package/dist/split-button.stories.d.ts +4 -3
  134. package/dist/split-button.styles.js +1 -94
  135. package/dist/split-button.test.basics.d.ts +2 -1
  136. package/dist/split-button.test.basics.js +67 -80
  137. package/dist/split-button.test.interactions.d.ts +4 -0
  138. package/dist/split-button.test.interactions.js +51 -0
  139. package/dist/styles/opacity-and-scale-animation.js +2 -6
  140. package/dist/styles/variables.css +1 -1
  141. package/dist/tab.d.ts +2 -11
  142. package/dist/tab.group.d.ts +2 -5
  143. package/dist/tab.group.styles.js +12 -15
  144. package/dist/tab.group.test.basics.js +49 -34
  145. package/dist/tab.group.test.interactions.js +17 -14
  146. package/dist/tab.panel.d.ts +0 -3
  147. package/dist/tab.test.basics.js +6 -5
  148. package/dist/tag.d.ts +6 -4
  149. package/dist/tag.js +1 -1
  150. package/dist/tag.styles.js +36 -36
  151. package/dist/tag.test.basics.js +16 -109
  152. package/dist/tag.test.events.js +12 -8
  153. package/dist/tag.test.focus.js +2 -3
  154. package/dist/tag.test.interactions.d.ts +1 -0
  155. package/dist/tag.test.interactions.js +34 -0
  156. package/dist/textarea.d.ts +2 -3
  157. package/dist/textarea.js +2 -2
  158. package/dist/textarea.test.basics.js +8 -8
  159. package/dist/textarea.test.events.js +55 -55
  160. package/dist/textarea.test.form.js +9 -9
  161. package/dist/textarea.test.validity.js +167 -135
  162. package/dist/toasts.d.ts +1 -5
  163. package/dist/toasts.test.basics.js +2 -1
  164. package/dist/toasts.toast.d.ts +1 -4
  165. package/dist/toasts.toast.js +1 -1
  166. package/dist/toasts.toast.styles.js +12 -0
  167. package/dist/toggle.d.ts +0 -2
  168. package/dist/toggle.styles.js +1 -5
  169. package/dist/toggle.test.basics.js +2 -2
  170. package/dist/toggle.test.interactions.js +7 -7
  171. package/dist/tooltip.d.ts +2 -1
  172. package/dist/tooltip.js +1 -1
  173. package/dist/tooltip.styles.js +36 -13
  174. package/dist/tooltip.test.basics.d.ts +1 -1
  175. package/dist/tooltip.test.basics.js +19 -19
  176. package/dist/tree.d.ts +0 -2
  177. package/dist/tree.item.d.ts +5 -7
  178. package/dist/tree.item.icon-button.d.ts +1 -4
  179. package/dist/tree.item.js +1 -1
  180. package/dist/tree.item.menu.d.ts +0 -2
  181. package/dist/tree.item.menu.test.basics.js +9 -9
  182. package/dist/tree.item.styles.js +4 -3
  183. package/dist/tree.item.test.basics.js +43 -31
  184. package/dist/tree.test.basics.js +29 -29
  185. package/dist/tree.test.focus.js +77 -74
  186. package/package.json +12 -14
  187. package/dist/split-container.d.ts +0 -31
  188. package/dist/split-container.js +0 -1
  189. package/dist/split-container.styles.js +0 -132
  190. package/dist/split-container.test.basics.d.ts +0 -3
  191. package/dist/split-container.test.basics.js +0 -445
  192. package/dist/split-container.test.interactions.d.ts +0 -1
  193. package/dist/split-container.test.interactions.js +0 -20
  194. package/dist/split-link.d.ts +0 -25
  195. package/dist/split-link.js +0 -1
  196. package/dist/split-link.test.basics.d.ts +0 -1
  197. package/dist/split-link.test.basics.js +0 -93
  198. package/dist/split-link.test.interactions.d.ts +0 -1
  199. package/dist/split-link.test.interactions.js +0 -20
  200. package/dist/status-indicator.d.ts +0 -30
  201. package/dist/status-indicator.js +0 -1
  202. package/dist/status-indicator.stories.d.ts +0 -5
  203. package/dist/status-indicator.styles.js +0 -58
  204. package/dist/status-indicator.test.basics.d.ts +0 -1
  205. package/dist/status-indicator.test.basics.js +0 -102
  206. /package/dist/{split-container.styles.d.ts → split-button.primary-button.styles.d.ts} +0 -0
  207. /package/dist/{status-indicator.styles.d.ts → split-button.secondary-button.styles.d.ts} +0 -0
@@ -5,19 +5,6 @@ import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-
5
5
  import { sendKeys } from '@web/test-runner-commands';
6
6
  import GlideCoreMenu from './menu.js';
7
7
  GlideCoreMenu.shadowRootOptions.mode = 'open';
8
- it('focuses the target on `focus()`', async () => {
9
- const component = await fixture(html `<glide-core-menu>
10
- <button slot="target">Target</button>
11
-
12
- <glide-core-menu-options>
13
- <glide-core-menu-link label="Link"></glide-core-menu-link>
14
- </glide-core-menu-options>
15
- </glide-core-menu>`);
16
- component.focus();
17
- const target = component.querySelector('button');
18
- assert(target);
19
- expect(document.activeElement).to.equal(target);
20
- });
21
8
  it('closes when it loses focus', async () => {
22
9
  const component = await fixture(html `<glide-core-menu open>
23
10
  <button slot="target">Target</button>
@@ -26,7 +13,7 @@ it('closes when it loses focus', async () => {
26
13
  <glide-core-menu-link label="Link"></glide-core-menu-link>
27
14
  </glide-core-menu-options>
28
15
  </glide-core-menu>`);
29
- component.focus();
16
+ component.querySelector('button')?.focus();
30
17
  await sendKeys({ press: 'Tab' });
31
18
  const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
32
19
  const options = component.querySelector('glide-core-menu-options');
@@ -44,7 +31,7 @@ it('remains open when the options component is focused', async () => {
44
31
  </glide-core-menu>`);
45
32
  // Wait for Floating UI.
46
33
  await aTimeout(0);
47
- component.focus();
34
+ component.querySelector('button')?.focus();
48
35
  const options = component.querySelector('glide-core-menu-options');
49
36
  const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
50
37
  options?.focus();
@@ -61,7 +48,7 @@ it('remains open when an option is focused', async () => {
61
48
  </glide-core-menu>`);
62
49
  // Wait for Floating UI.
63
50
  await aTimeout(0);
64
- component.focus();
51
+ component.querySelector('button')?.focus();
65
52
  const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
66
53
  const option = component.querySelector('glide-core-menu-link');
67
54
  assert(option);
@@ -80,7 +67,7 @@ it('sets an inactive option as active when focused', async () => {
80
67
  </glide-core-menu>`);
81
68
  // Wait for Floating UI.
82
69
  await aTimeout(0);
83
- component.focus();
70
+ component.querySelector('button')?.focus();
84
71
  const button = component.querySelector('glide-core-menu-button');
85
72
  const link = component.querySelector('glide-core-menu-link');
86
73
  const options = component.querySelector('glide-core-menu-options');
@@ -103,7 +90,7 @@ it('sets an already active option as active when focused', async () => {
103
90
  </glide-core-menu>`);
104
91
  // Wait for Floating UI.
105
92
  await aTimeout(0);
106
- component.focus();
93
+ component.querySelector('button')?.focus();
107
94
  const button = component.querySelector('glide-core-menu-button');
108
95
  const link = component.querySelector('glide-core-menu-link');
109
96
  const options = component.querySelector('glide-core-menu-options');
@@ -11,6 +11,7 @@ import { LitElement } from 'lit';
11
11
  import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
12
12
  import { customElement } from 'lit/decorators.js';
13
13
  import { sendKeys } from '@web/test-runner-commands';
14
+ import { sendMouse } from '@web/test-runner-commands';
14
15
  import GlideCoreMenu from './menu.js';
15
16
  let GlideCoreNestedSlot = class GlideCoreNestedSlot extends LitElement {
16
17
  static { this.shadowRootOptions = {
@@ -30,8 +31,27 @@ let GlideCoreNestedSlot = class GlideCoreNestedSlot extends LitElement {
30
31
  GlideCoreNestedSlot = __decorate([
31
32
  customElement('glide-core-nested-slot')
32
33
  ], GlideCoreNestedSlot);
34
+ let GlideCoreMenuInAnotherComponent = class GlideCoreMenuInAnotherComponent extends LitElement {
35
+ static { this.shadowRootOptions = {
36
+ ...LitElement.shadowRootOptions,
37
+ mode: 'closed',
38
+ }; }
39
+ render() {
40
+ return html `<glide-core-menu open>
41
+ <button slot="target">Target</button>
42
+
43
+ <glide-core-menu-options>
44
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
45
+ </glide-core-menu-options>
46
+ </glide-core-menu>`;
47
+ }
48
+ };
49
+ GlideCoreMenuInAnotherComponent = __decorate([
50
+ customElement('glide-core-menu-in-another-component')
51
+ ], GlideCoreMenuInAnotherComponent);
33
52
  GlideCoreMenu.shadowRootOptions.mode = 'open';
34
53
  GlideCoreNestedSlot.shadowRootOptions.mode = 'open';
54
+ GlideCoreMenuInAnotherComponent.shadowRootOptions.mode = 'open';
35
55
  it('opens on click', async () => {
36
56
  const component = await fixture(html `<glide-core-menu>
37
57
  <button slot="target">Target</button>
@@ -377,19 +397,23 @@ it('sets `privateSize` on the options component when `size` is changed programma
377
397
  const options = component.querySelector('glide-core-menu-options');
378
398
  expect(options?.privateSize).to.equal('small');
379
399
  });
380
- it('closes when clicked', async () => {
381
- const component = await fixture(html `<glide-core-menu open>
382
- <button slot="target">Target</button>
383
-
384
- <glide-core-menu-options>
385
- <glide-core-menu-link label="Link"></glide-core-menu-link>
386
- </glide-core-menu-options>
387
- </glide-core-menu>`);
388
- component.querySelector('button')?.click();
389
- const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
390
- const options = component.querySelector('glide-core-menu-options');
391
- const target = component.querySelector('button');
392
- expect(component.open).to.be.false;
400
+ it('closes when its target clicked', async () => {
401
+ const component = await fixture(html `<glide-core-menu-in-another-component></glide-core-menu-in-another-component>`);
402
+ // Wait for it to open.
403
+ await aTimeout(0);
404
+ const target = component.shadowRoot?.querySelector('button');
405
+ assert(target);
406
+ const { x, y } = target.getBoundingClientRect();
407
+ // Calling `click()` won't do because Menu relies on a "mouseup" event to
408
+ // decide if it should close.
409
+ await sendMouse({
410
+ type: 'click',
411
+ position: [Math.ceil(x), Math.ceil(y)],
412
+ });
413
+ const menu = component.shadowRoot?.querySelector('glide-core-menu');
414
+ const defaultSlot = menu?.shadowRoot?.querySelector('slot:not([name])');
415
+ const options = menu?.querySelector('glide-core-menu-options');
416
+ expect(menu?.open).to.be.false;
393
417
  expect(defaultSlot?.checkVisibility()).to.be.false;
394
418
  expect(options?.getAttribute('aria-activedescendant')).to.equal('');
395
419
  expect(target?.ariaExpanded).to.equal('false');
@@ -422,7 +446,7 @@ it('closes on Escape', async () => {
422
446
  </glide-core-menu>`);
423
447
  // Wait for it to open
424
448
  await aTimeout(0);
425
- component.focus();
449
+ component.querySelector('button')?.focus();
426
450
  await sendKeys({ press: 'Escape' });
427
451
  const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
428
452
  const options = component.querySelector('glide-core-menu-options');
@@ -457,7 +481,7 @@ it('closes when an option is selected via Enter', async () => {
457
481
  <glide-core-menu-link label="Link"></glide-core-menu-link>
458
482
  </glide-core-menu-options>
459
483
  </glide-core-menu>`);
460
- component.focus();
484
+ component.querySelector('button')?.focus();
461
485
  component
462
486
  .querySelector('glide-core-menu-link')
463
487
  ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
@@ -478,7 +502,7 @@ it('closes when an option is selected via Space', async () => {
478
502
  <glide-core-menu-link label="Link"></glide-core-menu-link>
479
503
  </glide-core-menu-options>
480
504
  </glide-core-menu>`);
481
- component.focus();
505
+ component.querySelector('button')?.focus();
482
506
  await sendKeys({ press: ' ' });
483
507
  const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
484
508
  const options = component.querySelector('glide-core-menu-options');
@@ -617,7 +641,7 @@ it('activates the next option on ArrowDown', async () => {
617
641
  `);
618
642
  // Wait for Floating UI.
619
643
  await aTimeout(0);
620
- component.focus();
644
+ component.querySelector('button')?.focus();
621
645
  const links = component.querySelectorAll('glide-core-menu-link');
622
646
  const options = component.querySelector('glide-core-menu-options');
623
647
  links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
@@ -640,7 +664,7 @@ it('activates the previous option on ArrowUp', async () => {
640
664
  `);
641
665
  // Wait for Floating UI.
642
666
  await aTimeout(0);
643
- component.focus();
667
+ component.querySelector('button')?.focus();
644
668
  const links = component.querySelectorAll('glide-core-menu-link');
645
669
  const options = component.querySelector('glide-core-menu-options');
646
670
  links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
@@ -662,7 +686,7 @@ it('activates the first option on Home', async () => {
662
686
  `);
663
687
  // Wait for Floating UI.
664
688
  await aTimeout(0);
665
- component.focus();
689
+ component.querySelector('button')?.focus();
666
690
  const links = component.querySelectorAll('glide-core-menu-link');
667
691
  const options = component.querySelector('glide-core-menu-options');
668
692
  links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
@@ -684,7 +708,7 @@ it('activates the first option on PageUp', async () => {
684
708
  `);
685
709
  // Wait for Floating UI.
686
710
  await aTimeout(0);
687
- component.focus();
711
+ component.querySelector('button')?.focus();
688
712
  const links = component.querySelectorAll('glide-core-menu-link');
689
713
  const options = component.querySelector('glide-core-menu-options');
690
714
  links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
@@ -706,7 +730,7 @@ it('activates the first option on Meta + ArrowUp', async () => {
706
730
  `);
707
731
  // Wait for Floating UI.
708
732
  await aTimeout(0);
709
- component.focus();
733
+ component.querySelector('button')?.focus();
710
734
  const links = component.querySelectorAll('glide-core-menu-link');
711
735
  const options = component.querySelector('glide-core-menu-options');
712
736
  links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
@@ -730,7 +754,7 @@ it('activates the last option on End', async () => {
730
754
  `);
731
755
  // Wait for Floating UI.
732
756
  await aTimeout(0);
733
- component.focus();
757
+ component.querySelector('button')?.focus();
734
758
  await sendKeys({ press: 'End' });
735
759
  const links = component.querySelectorAll('glide-core-menu-link');
736
760
  const options = component.querySelector('glide-core-menu-options');
@@ -752,7 +776,7 @@ it('activates the last option on PageDown', async () => {
752
776
  component.querySelector('button')?.click();
753
777
  // Wait for Floating UI.
754
778
  await aTimeout(0);
755
- component.focus();
779
+ component.querySelector('button')?.focus();
756
780
  const links = component.querySelectorAll('glide-core-menu-link');
757
781
  const options = component.querySelector('glide-core-menu-options');
758
782
  links[0].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
@@ -774,7 +798,7 @@ it('activates the last option on Meta + ArrowDown', async () => {
774
798
  `);
775
799
  // Wait for Floating UI.
776
800
  await aTimeout(0);
777
- component.focus();
801
+ component.querySelector('button')?.focus();
778
802
  const links = component.querySelectorAll('glide-core-menu-link');
779
803
  const options = component.querySelector('glide-core-menu-options');
780
804
  links[0].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
package/dist/modal.d.ts CHANGED
@@ -6,31 +6,20 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @description A Modal dialog component which interrupts interaction with the rest of the page.
10
- *
11
- * @event close - Emitted when the Modal closes.
9
+ * @event close - `(event: "close", listener: (event: Event)) => void) => void`
12
10
  *
13
11
  * @slot - The content of the modal.
14
- *
15
- * @slot header-actions - A slot for placing additional header actions. These are co-located with the close button.
16
- * Use the `glide-core-modal-icon-button` component only.
17
- *
18
- * @slot primary - A slot for rendering a primary action button. Normally a "Continue", "Next", or "Submit" action.
19
- *
20
- * @slot secondary - A slot for rendering a secondary action button. Normally a "Cancel" action.
21
- *
22
- * @slot tertiary - A slot for rendering an icon+tooltip for additional information,
23
- * or a tertiary action button.
12
+ * @slot header-actions - One or more of `<glide-core-modal-icon-button>`.
13
+ * @slot primary - One of `<glide-core-button>`.
14
+ * @slot secondary - One of `<glide-core-button>`.
15
+ * @slot tertiary - One or more of `<glide-core-button>` or `<glide-core-modal-tertiary-icon>`.
24
16
  */
25
17
  export default class GlideCoreModal extends LitElement {
26
18
  #private;
27
19
  static shadowRootOptions: ShadowRootInit;
28
20
  static styles: import("lit").CSSResult[];
29
- /** The title text for the Modal. */
30
21
  label: string;
31
- /** Adds a back/dismiss button in the Modal header. */
32
- showBackButton: boolean;
33
- /** Fixed-size options for the Modal. */
22
+ backButton: boolean;
34
23
  size?: 'small' | 'medium' | 'large' | 'xlarge';
35
24
  close(): void;
36
25
  connectedCallback(): void;
@@ -6,8 +6,6 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @description A Modal Icon Button. Should be used only in the "header-actions" slot of a Modal.
10
- *
11
9
  * @slot - The content of the button. Should only be an icon. The icon should also leverage the
12
10
  * "label" attribute for accessibility so that it is read to screenreaders.
13
11
  *
@@ -18,19 +18,19 @@ it('renders and sets default attributes', async () => {
18
18
  expect(component).to.be.ok;
19
19
  const buttonElement = component.shadowRoot?.querySelector('glide-core-icon-button');
20
20
  expect(buttonElement).to.be.not.null;
21
- expect(buttonElement).to.have.attribute('variant', 'tertiary');
21
+ expect(buttonElement?.getAttribute('variant')).to.equal('tertiary');
22
22
  });
23
23
  it('adds an accessible label when given', async () => {
24
24
  const component = await fixture(html `<glide-core-modal-icon-button label="test-label"
25
25
  >Test</glide-core-modal-icon-button
26
26
  >`);
27
27
  const buttonElement = component.shadowRoot?.querySelector('glide-core-icon-button');
28
- expect(buttonElement).to.have.attribute('label', 'test-label');
28
+ expect(buttonElement?.getAttribute('label')).to.equal('test-label');
29
29
  });
30
30
  it('does not add an acceessible label when not given', async () => {
31
31
  const component = await fixture(html `<glide-core-modal-icon-button>Test</glide-core-modal-icon-button>`);
32
32
  const buttonElement = component.shadowRoot?.querySelector('glide-core-icon-button');
33
- expect(buttonElement).to.have.attribute('label', '');
33
+ expect(buttonElement?.getAttribute('label')).to.equal('');
34
34
  });
35
35
  it('throws if it does not have a default slot', async () => {
36
36
  const spy = sinon.spy();
package/dist/modal.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,l){var n,r=arguments.length,i=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,l);else for(var s=e.length-1;s>=0;s--)(n=e[s])&&(i=(r<3?n(i):r>3?n(t,o,i):n(t,o))||i);return r>3&&i&&Object.defineProperty(t,o,i),i};import"./modal.icon-button.js";import{LitElement,html}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{when}from"lit/directives/when.js";import GlideCoreButton from"./button.js";import GlideCoreModalIconButton from"./modal.icon-button.js";import GlideCoreModalTertiaryIcon from"./modal.tertiary-icon.js";import ow,{owSlot,owSlotType}from"./library/ow.js";import styles from"./modal.styles.js";const globalStylesheet=new CSSStyleSheet;globalStylesheet.insertRule("\n @supports (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n scrollbar-gutter: stable !important;\n overflow: hidden !important;\n }\n }\n"),globalStylesheet.insertRule("\n @supports not (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n padding-right: var(--glide-scroll-size, 0.9375rem) !important;\n overflow: hidden !important;\n }\n }\n");let GlideCoreModal=class GlideCoreModal extends LitElement{constructor(){super(...arguments),this.label="",this.showBackButton=!1,this.size="medium",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#n=createRef(),this.#r=createRef(),this.#i=new LocalizeController(this)}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}close(){this.#e.value?.open&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}connectedCallback(){super.connectedCallback();document.adoptedStyleSheets.includes(globalStylesheet)||document.adoptedStyleSheets.push(globalStylesheet)}disconnectedCallback(){super.disconnectedCallback(),document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),document.adoptedStyleSheets=document.adoptedStyleSheets.filter((e=>e!==globalStylesheet))}firstUpdated(){owSlot(this.#t.value),owSlotType(this.#r.value,[GlideCoreModalIconButton]),owSlotType(this.#o.value,[GlideCoreButton]),owSlotType(this.#l.value,[GlideCoreButton]),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}render(){return html`<dialog class="${classMap({component:!0,small:"small"===this.size,medium:"medium"===this.size,large:"large"===this.size,xlarge:"xlarge"===this.size})}" tabindex="-1" @keydown="${this.#s}" @mousedown="${this.#a}" ${ref(this.#e)}><header class="header"><h2 class="label" data-test="heading" id="heading">${when(this.showBackButton,(()=>html`<glide-core-modal-icon-button data-test="back-button" @click="${this.#c}"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("dismiss")}</title><path d="M12 18C11.4477 18 11 18.4477 11 19C11 19.5523 11.4477 20 12 20V18ZM20 14.5C20 16.433 18.433 18 16.5 18V20C19.5376 20 22 17.5376 22 14.5H20ZM16.5 11C18.433 11 20 12.567 20 14.5H22C22 11.4624 19.5376 9 16.5 9V11ZM16.5 18H12V20H16.5V18ZM16.5 9H3V11H16.5V9Z" fill="currentColor"/><path d="M7 6L3 10L7 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button>`))} ${this.label}</h2><div class="header-actions" role="toolbar"><slot name="header-actions" @slotchange="${this.#d}" ${ref(this.#r)}></slot><glide-core-modal-icon-button data-test="close-button" @click="${this.#c}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("close")}</title><path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button></div></header><article aria-labelledby="heading" class="body" role="region" tabindex="0"><slot @slotchange="${this.#m}" ${ref(this.#t)}></slot></article><footer class="footer"><menu class="menu"><li class="flex align-center"><slot name="tertiary" @slotchange="${this.#h}" ${ref(this.#n)}></slot></li><li><menu class="actions"><li><slot name="secondary" @slotchange="${this.#u}" ${ref(this.#l)}></slot></li><li><slot name="primary" @slotchange="${this.#f}" ${ref(this.#o)}></slot></li></menu></li></menu></footer></dialog>`}showModal(){if(!this.#e.value?.open){if(document.documentElement.classList.add("private-glide-core-modal-lock-scroll"),!window.CSS.supports("scrollbar-gutter","stable")){const e=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.documentElement.style.setProperty("--glide-scroll-size",`${e}px`)}this.#e.value?.showModal(),this.#e.value?.focus()}}#e;#t;#o;#l;#n;#r;#i;#c(){document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close()}#m(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlot(this.#t.value)}#f(){owSlotType(this.#o.value,[GlideCoreButton])}#u(){owSlotType(this.#l.value,[GlideCoreButton])}#h(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}#d(){owSlotType(this.#r.value,[GlideCoreModalIconButton])}#s(e){"Escape"===e.key&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}#a(e){if(e.target!==this.#e.value)return;const t=this.#e.value?.getBoundingClientRect();if(t){t.top<=e.clientY&&e.clientY<=t.top+t.height&&t.left<=e.clientX&&e.clientX<=t.left+t.width||(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}}};__decorate([property({reflect:!0})],GlideCoreModal.prototype,"label",void 0),__decorate([property({attribute:"show-back-button",type:Boolean,reflect:!0})],GlideCoreModal.prototype,"showBackButton",void 0),__decorate([property({reflect:!0})],GlideCoreModal.prototype,"size",void 0),GlideCoreModal=__decorate([customElement("glide-core-modal")],GlideCoreModal);export default GlideCoreModal;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,l){var n,r=arguments.length,i=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,l);else for(var s=e.length-1;s>=0;s--)(n=e[s])&&(i=(r<3?n(i):r>3?n(t,o,i):n(t,o))||i);return r>3&&i&&Object.defineProperty(t,o,i),i};import"./modal.icon-button.js";import{LitElement,html}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{when}from"lit/directives/when.js";import GlideCoreButton from"./button.js";import GlideCoreModalIconButton from"./modal.icon-button.js";import GlideCoreModalTertiaryIcon from"./modal.tertiary-icon.js";import ow,{owSlot,owSlotType}from"./library/ow.js";import styles from"./modal.styles.js";const globalStylesheet=new CSSStyleSheet;globalStylesheet.insertRule("\n @supports (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n scrollbar-gutter: stable !important;\n overflow: hidden !important;\n }\n }\n"),globalStylesheet.insertRule("\n @supports not (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n padding-right: var(--glide-scroll-size, 0.9375rem) !important;\n overflow: hidden !important;\n }\n }\n");let GlideCoreModal=class GlideCoreModal extends LitElement{constructor(){super(...arguments),this.label="",this.backButton=!1,this.size="medium",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#n=createRef(),this.#r=createRef(),this.#i=new LocalizeController(this)}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}close(){this.#e.value?.open&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}connectedCallback(){super.connectedCallback();document.adoptedStyleSheets.includes(globalStylesheet)||document.adoptedStyleSheets.push(globalStylesheet)}disconnectedCallback(){super.disconnectedCallback(),document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),document.adoptedStyleSheets=document.adoptedStyleSheets.filter((e=>e!==globalStylesheet))}firstUpdated(){owSlot(this.#t.value),owSlotType(this.#r.value,[GlideCoreModalIconButton]),owSlotType(this.#o.value,[GlideCoreButton]),owSlotType(this.#l.value,[GlideCoreButton]),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}render(){return html`<dialog class="${classMap({component:!0,small:"small"===this.size,medium:"medium"===this.size,large:"large"===this.size,xlarge:"xlarge"===this.size})}" tabindex="-1" @keydown="${this.#s}" @mousedown="${this.#a}" ${ref(this.#e)}><header class="header"><h2 class="label" data-test="heading" id="heading">${when(this.backButton,(()=>html`<glide-core-modal-icon-button class="icon-button" data-test="back-button" @click="${this.#c}"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("dismiss")}</title><path d="M12 18C11.4477 18 11 18.4477 11 19C11 19.5523 11.4477 20 12 20V18ZM20 14.5C20 16.433 18.433 18 16.5 18V20C19.5376 20 22 17.5376 22 14.5H20ZM16.5 11C18.433 11 20 12.567 20 14.5H22C22 11.4624 19.5376 9 16.5 9V11ZM16.5 18H12V20H16.5V18ZM16.5 9H3V11H16.5V9Z" fill="currentColor"/><path d="M7 6L3 10L7 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button>`))} ${this.label}</h2><div class="header-actions" role="toolbar"><slot name="header-actions" @slotchange="${this.#d}" ${ref(this.#r)}></slot><glide-core-modal-icon-button class="icon-button" data-test="close-button" @click="${this.#c}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("close")}</title><path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button></div></header><article aria-labelledby="heading" class="body" role="region" tabindex="0"><slot @slotchange="${this.#m}" ${ref(this.#t)}></slot></article><footer class="footer"><menu class="menu"><li class="flex align-center"><slot name="tertiary" @slotchange="${this.#u}" ${ref(this.#n)}></slot></li><li><menu class="actions"><li><slot name="secondary" @slotchange="${this.#h}" ${ref(this.#l)}></slot></li><li><slot name="primary" @slotchange="${this.#f}" ${ref(this.#o)}></slot></li></menu></li></menu></footer></dialog>`}showModal(){if(!this.#e.value?.open){if(document.documentElement.classList.add("private-glide-core-modal-lock-scroll"),!window.CSS.supports("scrollbar-gutter","stable")){const e=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.documentElement.style.setProperty("--glide-scroll-size",`${e}px`)}this.#e.value?.showModal(),this.#e.value?.focus()}}#e;#t;#o;#l;#n;#r;#i;#c(){document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close()}#m(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlot(this.#t.value)}#f(){owSlotType(this.#o.value,[GlideCoreButton])}#h(){owSlotType(this.#l.value,[GlideCoreButton])}#u(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}#d(){owSlotType(this.#r.value,[GlideCoreModalIconButton])}#s(e){"Escape"===e.key&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}#a(e){if(e.target!==this.#e.value)return;const t=this.#e.value?.getBoundingClientRect();if(t){t.top<=e.clientY&&e.clientY<=t.top+t.height&&t.left<=e.clientX&&e.clientX<=t.left+t.width||(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}}};__decorate([property({reflect:!0})],GlideCoreModal.prototype,"label",void 0),__decorate([property({attribute:"back-button",type:Boolean,reflect:!0})],GlideCoreModal.prototype,"backButton",void 0),__decorate([property({reflect:!0})],GlideCoreModal.prototype,"size",void 0),GlideCoreModal=__decorate([customElement("glide-core-modal")],GlideCoreModal);export default GlideCoreModal;
@@ -24,22 +24,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
24
24
  }
25
25
  }
26
26
 
27
- @media (prefers-reduced-motion) {
28
- /**
29
- ':host' is targeted here to increase specificity so that
30
- we don't need to use '!important' to turn off the animation.
31
- */
32
- :host .component {
33
- &[open] {
34
- animation: none;
35
- }
36
-
37
- &::backdrop {
38
- animation: none;
39
- }
40
- }
41
- }
42
-
43
27
  .component {
44
28
  backdrop-filter: blur(100px);
45
29
  background-color: var(--glide-core-surface-modal);
@@ -54,8 +38,11 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
54
38
  padding: 1.25rem;
55
39
 
56
40
  &[open] {
57
- animation: modal-open 250ms;
58
41
  opacity: 1;
42
+
43
+ @media (prefers-reduced-motion: no-preference) {
44
+ animation: modal-open 250ms;
45
+ }
59
46
  }
60
47
 
61
48
  &:focus {
@@ -63,18 +50,21 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
63
50
  }
64
51
 
65
52
  &::backdrop {
66
- animation: backdrop-fade-in 250ms;
67
-
68
53
  /* prefix required for Safari */
69
54
  /* stylelint-disable-next-line property-no-vendor-prefix */
70
55
  -webkit-backdrop-filter: blur(3px);
71
56
  backdrop-filter: blur(3px);
72
57
  background-color: rgba(0 0 0 / 40%);
58
+
59
+ @media (prefers-reduced-motion: no-preference) {
60
+ animation: backdrop-fade-in 250ms;
61
+ }
73
62
  }
74
63
 
75
64
  ::slotted([slot='tertiary']) {
76
65
  --size: 1rem;
77
66
 
67
+ display: contents;
78
68
  size: 1rem;
79
69
  }
80
70
  }
@@ -123,6 +113,10 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
123
113
  line-height: 1;
124
114
  }
125
115
 
116
+ .icon-button {
117
+ display: contents;
118
+ }
119
+
126
120
  .body {
127
121
  line-height: 1;
128
122
  overflow: auto;
@@ -6,9 +6,6 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @description A Modal tertiary icon wrapper. Provides opinionated styling and accessibility for icons in Modals.
10
- * Should be used only in the "tertiary" slot of a Modal.
11
- *
12
9
  * @slot - The icon to be rendered.
13
10
  */
14
11
  export default class GlideCoreModalTertiaryIcon extends LitElement {
@@ -27,7 +27,7 @@ it('adds an accessible label when given', async () => {
27
27
  >Test</glide-core-modal-tertiary-icon
28
28
  >`);
29
29
  const spanElement = component.shadowRoot?.querySelector('span');
30
- expect(spanElement).to.have.attribute('aria-label', 'test-label');
30
+ expect(spanElement?.getAttribute('aria-label')).to.equal('test-label');
31
31
  });
32
32
  it('does not add an acceessible label when not given', async () => {
33
33
  const component = await fixture(html `<glide-core-modal-tertiary-icon>Test</glide-core-modal-tertiary-icon>`);
@@ -39,12 +39,12 @@ it('sets the tooltip placement when attribute "tooltip-placement" is given', asy
39
39
  >Test</glide-core-modal-tertiary-icon
40
40
  >`);
41
41
  const toolTip = component.shadowRoot?.querySelector('glide-core-tooltip');
42
- expect(toolTip).to.have.attribute('placement', 'right');
42
+ expect(toolTip?.getAttribute('placement')).to.equal('right');
43
43
  });
44
44
  it('sets the tooltip placement to "bottom" when attribute "tooltip-placement" is not given', async () => {
45
45
  const component = await fixture(html `<glide-core-modal-tertiary-icon>Test</glide-core-modal-tertiary-icon>`);
46
46
  const toolTip = component.shadowRoot?.querySelector('glide-core-tooltip');
47
- expect(toolTip).to.have.attribute('placement', 'bottom');
47
+ expect(toolTip?.getAttribute('placement')).to.equal('bottom');
48
48
  });
49
49
  it('throws if it does not have a default slot', async () => {
50
50
  const spy = sinon.spy();
@@ -18,8 +18,8 @@ it('has defaults', async () => {
18
18
  expect(dialog?.hasAttribute('open')).to.be.false;
19
19
  expect(component.size).to.equal('medium');
20
20
  expect(component.getAttribute('size')).to.equal('medium');
21
- expect(component.showBackButton).to.be.false;
22
- expect(component.hasAttribute('show-back-button')).to.be.false;
21
+ expect(component.backButton).to.be.false;
22
+ expect(component.hasAttribute('back-button')).to.be.false;
23
23
  });
24
24
  it('renders the provided "label"', async () => {
25
25
  const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
@@ -33,8 +33,8 @@ it('does not render the show back button in the label by default', async () => {
33
33
  component.showModal();
34
34
  expect(component.shadowRoot?.querySelector('[data-test="back-button"]')).to.be.null;
35
35
  });
36
- it('renders the show back button in the label when provided with "show-back-button"', async () => {
37
- const component = await fixture(html `<glide-core-modal label="Label" show-back-button>
36
+ it('renders the show back button in the label when provided with "back-button"', async () => {
37
+ const component = await fixture(html `<glide-core-modal label="Label" back-button>
38
38
  Content
39
39
  </glide-core-modal>`);
40
40
  component.showModal();
@@ -51,7 +51,11 @@ it('renders the provided default slotted content', async () => {
51
51
  it('renders the provided primary slot content', async () => {
52
52
  const component = await fixture(html `<glide-core-modal label="Label">
53
53
  Content
54
- <glide-core-button slot="primary" data-primary>Primary</glide-core-button>
54
+ <glide-core-button
55
+ label="Primary"
56
+ slot="primary"
57
+ data-primary
58
+ ></glide-core-button>
55
59
  </glide-core-modal>`);
56
60
  component.showModal();
57
61
  const slotContent = component.querySelector('[data-primary]');
@@ -21,8 +21,8 @@ it('closes the modal when the escape key is pressed', async () => {
21
21
  await sendKeys({ press: 'Escape' });
22
22
  expect(dialogElement?.hasAttribute('open')).to.be.false;
23
23
  });
24
- it('closes the modal via "show-back-button"', async () => {
25
- const component = await fixture(html `<glide-core-modal label="Label" show-back-button>
24
+ it('closes the modal via "back-button"', async () => {
25
+ const component = await fixture(html `<glide-core-modal label="Label" back-button>
26
26
  Content
27
27
  </glide-core-modal>`);
28
28
  component.showModal();
@@ -43,9 +43,9 @@ it('does not dispatch a "close" event when the modal is open and non-escape keys
43
43
  await sendKeys({ press: 'Enter' });
44
44
  expect(spy.callCount).to.equal(0);
45
45
  });
46
- it('dispatches a "close" event when the modal is closed via "show-back-button"', async () => {
46
+ it('dispatches a "close" event when the modal is closed via "back-button"', async () => {
47
47
  const spy = sinon.spy();
48
- const component = await fixture(html `<glide-core-modal label="Label" show-back-button>
48
+ const component = await fixture(html `<glide-core-modal label="Label" back-button>
49
49
  Content
50
50
  </glide-core-modal>`);
51
51
  component.addEventListener('close', spy);
@@ -7,9 +7,6 @@ declare global {
7
7
  }
8
8
  }
9
9
  /**
10
- /**
11
- * @description A radio group with a label, and optional description and tooltip. Participates in forms and validation via `FormData` and various methods.
12
- *
13
10
  * @event change - `(event: Event) => void`
14
11
  * @event input - `(event: Event) => void`
15
12
  * @event invalid - `(event: Event) => void`
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,i,t,o){var s,a=arguments.length,d=a<3?i:null===o?o=Object.getOwnPropertyDescriptor(i,t):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)d=Reflect.decorate(e,i,t,o);else for(var r=e.length-1;r>=0;r--)(s=e[r])&&(d=(a<3?s(d):a>3?s(i,t,d):s(i,t))||d);return a>3&&d&&Object.defineProperty(i,t,d),d};import"./label.js";import"./tooltip.js";import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{owSlot,owSlotType}from"./library/ow.js";import GlideCoreRadio from"./radio.js";import styles from"./radio-group.styles.js";let GlideCoreRadioGroup=class GlideCoreRadioGroup extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}checkValidity(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i),this.#t=void 0}firstUpdated(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#t=this.#s.find((e=>e.checked)),this.#a()}focus(e){let i=this.#s.find((e=>e.checked));i||(i=this.#s.find((e=>0===e.tabIndex))),i?.focus(e)}get form(){return this.#e.form}get validity(){return this.#e.validity}get willValidate(){return this.#e.willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){if(this.#t&&this.contains(this.#t))for(const e of this.#s)this.#d(e===this.#t,e)}render(){return html`<div class="component" @click="${this.#r}" @keydown="${this.#l}" ${ref(this.#n)}><glide-core-private-label orientation="horizontal" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?error="${this.#h}" ?hide="${this.hideLabel}" ?required="${this.required}"><label id="label" data-test="label">${this.label}</label><div class="${classMap({"radio-container":!0,vertical:!0,invalid:this.#h})}" role="radiogroup" slot="control" aria-labelledby="label description" @blur="${this.#c}"><slot ${ref(this.#o)} @slotchange="${this.#p}"></slot></div><slot name="tooltip" slot="tooltip"></slot><slot id="description" name="description" slot="description"></slot></glide-core-private-label></div>`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#e.reportValidity();return this.requestUpdate(),e}updated(e){this.hasUpdated&&(e.has("value")||e.has("required"))&&(this.#f(),this.#u(!this.#e.validity.valid),this.requestUpdate())}willUpdate(e){if(this.hasUpdated){if(e.has("required")&&this.#R(),e.has("disabled")){for(const e of this.#s)this.#m(this.disabled,e);!this.disabled&&this.#b()}if(e.has("value"))for(const e of this.#s)e.checked=e.value===this.value}}constructor(){super(),this.description="",this.disabled=!1,this.label="",this.hideLabel=!1,this.name="",this.required=!1,this.value="",this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#n=createRef(),this.#o=createRef(),this.#t=void 0,this.#i=({formData:e})=>{this.name&&this.value.length>0&&!this.disabled&&e.append(this.name,this.value)},this.#e=this.attachInternals(),this.addEventListener("invalid",this.#v)}#n;#o;#t;#e;#C;#i;#a(){const e=this.#s.find((e=>e.checked));this.value=e?.value??this.#t?.value??"",this.#C=e??this.#t,this.required&&this.#R();for(const e of this.#s)this.disabled?this.#m(this.disabled,e):this.#m(e.disabled,e),e.addEventListener("blur",this.#y.bind(this));!this.disabled&&this.#b()}get#h(){const e=!this.disabled&&!this.validity.valid&&this.isReportValidityOrSubmit;return this.#u(e),e}#c(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1}#r(e){if(this.disabled)return;if(e.target instanceof GlideCoreRadio&&e.target.disabled&&this.#C&&!this.#C.disabled)return void this.#C?.focus();const i=e.target;if(i instanceof GlideCoreRadio&&i&&!i.disabled){this.#d(!0,i);for(const e of this.#s)e!==i&&this.#d(!1,e)}}#p(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#a()}#v(e){if(e.preventDefault(),!this.isCheckingValidity){if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}}#l(e){if(!(this.disabled||e.target instanceof GlideCoreRadio&&e.target?.disabled)&&e.target instanceof GlideCoreRadio){const i=e.target;switch(e.key){case"Enter":this.form?.requestSubmit();break;case"ArrowUp":case"ArrowLeft":{e.preventDefault();let t=i.previousElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(-1);e&&(t=e)}else t=t.previousElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#d(!1,i),this.#d(!0,t));break}case"ArrowDown":case"ArrowRight":{e.preventDefault();let t=i.nextElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(0);e&&(t=e)}else t=t.nextElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#d(!1,i),this.#d(!0,t));break}case" ":if(e.preventDefault(),!i.disabled&&!i.checked){this.#d(!0,i);for(const e of this.#s)e!==i&&this.#d(!1,e)}}}}#y(e){const i=e.relatedTarget;i&&i instanceof GlideCoreRadio&&this.#s.includes(i)||this.#c()}#f(){const e=this.#s.find((e=>e.checked));this.required&&!e?this.#e.setValidity({valueMissing:!0}," ",this.#n.value):this.#e.setValidity({})}get#s(){return this.#o.value?.assignedElements().filter((e=>e instanceof GlideCoreRadio))??[]}#d(e,i){i.checked=e,i.tabIndex=e?0:-1,e&&(this.#C=i,this.value=i.value,i.focus(),i.dispatchEvent(new Event("change",{bubbles:!0})),i.dispatchEvent(new Event("input",{bubbles:!0})))}#m(e,i){i.disabled=e,e&&(i.tabIndex=-1)}#u(e){for(const i of this.#s)i.invalid=e}#b(){if(this.disabled||this.#s.every((e=>e.disabled)))return;let e=null;const i=this.#s.find((e=>!e.disabled&&e.checked));if(i)e=i;else{const i=this.#s.find((e=>!e.disabled));i&&(e=i)}if(e)for(const i of this.#s)i.tabIndex=i===e?0:-1}#R(){for(const e of this.#s)e.required=this.required}};__decorate([property()],GlideCoreRadioGroup.prototype,"description",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"disabled",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreRadioGroup.prototype,"hideLabel",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"name",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"privateSplit",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"required",void 0),__decorate([property({reflect:!0})],GlideCoreRadioGroup.prototype,"value",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isBlurring",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isReportValidityOrSubmit",void 0),GlideCoreRadioGroup=__decorate([customElement("glide-core-radio-group")],GlideCoreRadioGroup);export default GlideCoreRadioGroup;
1
+ var __decorate=this&&this.__decorate||function(e,i,t,o){var s,a=arguments.length,d=a<3?i:null===o?o=Object.getOwnPropertyDescriptor(i,t):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)d=Reflect.decorate(e,i,t,o);else for(var r=e.length-1;r>=0;r--)(s=e[r])&&(d=(a<3?s(d):a>3?s(i,t,d):s(i,t))||d);return a>3&&d&&Object.defineProperty(i,t,d),d};import"./label.js";import"./tooltip.js";import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{owSlot,owSlotType}from"./library/ow.js";import GlideCoreRadio from"./radio.js";import styles from"./radio-group.styles.js";let GlideCoreRadioGroup=class GlideCoreRadioGroup extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}checkValidity(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i),this.#t=void 0}firstUpdated(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#t=this.#s.find((e=>e.checked)),this.#a()}focus(e){let i=this.#s.find((e=>e.checked));i||(i=this.#s.find((e=>0===e.tabIndex))),i?.focus(e)}get form(){return this.#e.form}get validity(){return this.#e.validity}get willValidate(){return this.#e.willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){if(this.#t&&this.contains(this.#t))for(const e of this.#s)this.#d(e===this.#t,e)}render(){return html`<div class="component" @click="${this.#r}" @keydown="${this.#l}" ${ref(this.#n)}><glide-core-private-label orientation="horizontal" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?error="${this.#h}" ?hide="${this.hideLabel}" ?required="${this.required}"><label id="label" data-test="label">${this.label}</label><div class="${classMap({"radio-container":!0,vertical:!0,invalid:this.#h})}" role="radiogroup" slot="control" aria-labelledby="label description" @blur="${this.#c}"><slot ${ref(this.#o)} @slotchange="${this.#p}"></slot></div><slot name="tooltip" slot="tooltip"></slot><slot id="description" name="description" slot="description"></slot></glide-core-private-label></div>`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#e.reportValidity();return this.requestUpdate(),e}updated(e){this.hasUpdated&&(e.has("value")||e.has("required"))&&(this.#f(),this.#u(!this.#e.validity.valid),this.requestUpdate())}willUpdate(e){if(this.hasUpdated){if(e.has("required")&&this.#R(),e.has("disabled")){for(const e of this.#s)this.#m(this.disabled,e);!this.disabled&&this.#b()}if(e.has("value"))for(const e of this.#s)e.checked=e.value===this.value}}constructor(){super(),this.description="",this.disabled=!1,this.label="",this.hideLabel=!1,this.name="",this.required=!1,this.value="",this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#n=createRef(),this.#o=createRef(),this.#t=void 0,this.#i=({formData:e})=>{this.name&&this.value.length>0&&!this.disabled&&e.append(this.name,this.value)},this.#e=this.attachInternals(),this.addEventListener("invalid",this.#v)}#n;#o;#t;#e;#C;#i;#a(){const e=this.#s.find((e=>e.checked));this.value=e?.value??this.#t?.value??"",this.#C=e??this.#t,this.required&&this.#R();for(const e of this.#s)this.disabled?this.#m(this.disabled,e):this.#m(e.disabled,e),e.addEventListener("blur",this.#y.bind(this));!this.disabled&&this.#b()}get#h(){const e=!this.disabled&&!this.validity.valid&&this.isReportValidityOrSubmit;return this.#u(e),e}#c(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1}#r(e){if(this.disabled)return;if(e.target instanceof GlideCoreRadio&&e.target.disabled&&this.#C&&!this.#C.disabled)return void this.#C?.focus();const i=e.target;if(i instanceof GlideCoreRadio&&i&&!i.disabled){this.#d(!0,i);for(const e of this.#s)e!==i&&this.#d(!1,e)}}#p(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#a()}#v(e){if(e.preventDefault(),!this.isCheckingValidity){if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}}#l(e){if(!(this.disabled||e.target instanceof GlideCoreRadio&&e.target?.disabled)&&e.target instanceof GlideCoreRadio){const i=e.target;switch(e.key){case"Enter":this.form?.requestSubmit();break;case"ArrowUp":case"ArrowLeft":{e.preventDefault();let t=i.previousElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(-1);e&&(t=e)}else t=t.previousElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#d(!1,i),this.#d(!0,t));break}case"ArrowDown":case"ArrowRight":{e.preventDefault();let t=i.nextElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(0);e&&(t=e)}else t=t.nextElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#d(!1,i),this.#d(!0,t));break}case" ":if(e.preventDefault(),!i.disabled&&!i.checked){this.#d(!0,i);for(const e of this.#s)e!==i&&this.#d(!1,e)}}}}#y(e){const i=e.relatedTarget;i&&i instanceof GlideCoreRadio&&this.#s.includes(i)||this.#c()}#f(){const e=this.#s.find((e=>e.checked));this.required&&!e?this.#e.setValidity({valueMissing:!0}," ",this.#n.value):this.#e.setValidity({})}get#s(){return this.#o.value?.assignedElements().filter((e=>e instanceof GlideCoreRadio))??[]}#d(e,i){i.checked=e,i.tabIndex=e?0:-1,e&&(this.#C=i,this.value=i.value,i.focus(),i.dispatchEvent(new Event("change",{bubbles:!0})),i.dispatchEvent(new Event("input",{bubbles:!0})))}#m(e,i){i.disabled=e,e&&(i.tabIndex=-1)}#u(e){for(const i of this.#s)i.invalid=e}#b(){if(this.disabled||this.#s.every((e=>e.disabled)))return;let e=null;const i=this.#s.find((e=>!e.disabled&&e.checked));if(i)e=i;else{const i=this.#s.find((e=>!e.disabled));i&&(e=i)}if(e)for(const i of this.#s)i.tabIndex=i===e?0:-1}#R(){for(const e of this.#s)e.required=this.required}};__decorate([property()],GlideCoreRadioGroup.prototype,"description",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"disabled",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreRadioGroup.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreRadioGroup.prototype,"name",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"privateSplit",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"required",void 0),__decorate([property({reflect:!0})],GlideCoreRadioGroup.prototype,"value",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isBlurring",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isReportValidityOrSubmit",void 0),GlideCoreRadioGroup=__decorate([customElement("glide-core-radio-group")],GlideCoreRadioGroup);export default GlideCoreRadioGroup;