@crowdstrike/glide-core 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/dist/accordion.d.ts +7 -3
  2. package/dist/button-group.button.d.ts +12 -16
  3. package/dist/button-group.button.js +1 -1
  4. package/dist/button-group.button.styles.js +76 -52
  5. package/dist/button-group.button.test.basics.d.ts +1 -1
  6. package/dist/button-group.button.test.basics.js +83 -147
  7. package/dist/button-group.button.test.events.js +8 -67
  8. package/dist/button-group.button.test.focus.js +13 -0
  9. package/dist/button-group.button.test.interactions.d.ts +1 -0
  10. package/dist/button-group.button.test.interactions.js +42 -0
  11. package/dist/button-group.d.ts +10 -10
  12. package/dist/button-group.js +1 -1
  13. package/dist/button-group.stories.d.ts +1 -5
  14. package/dist/button-group.styles.js +18 -6
  15. package/dist/button-group.test.basics.js +113 -234
  16. package/dist/button-group.test.events.js +210 -263
  17. package/dist/button-group.test.focus.d.ts +1 -0
  18. package/dist/button-group.test.focus.js +39 -0
  19. package/dist/button-group.test.interactions.d.ts +1 -0
  20. package/dist/button-group.test.interactions.js +91 -0
  21. package/dist/button.d.ts +3 -0
  22. package/dist/button.test.basics.js +1 -1
  23. package/dist/checkbox-group.d.ts +6 -2
  24. package/dist/checkbox-group.js +1 -1
  25. package/dist/checkbox-group.stories.d.ts +1 -1
  26. package/dist/checkbox-group.styles.js +1 -1
  27. package/dist/checkbox-group.test.basics.js +1 -1
  28. package/dist/checkbox-group.test.events.js +4 -4
  29. package/dist/checkbox-group.test.focus.js +4 -3
  30. package/dist/checkbox.d.ts +12 -5
  31. package/dist/checkbox.js +1 -1
  32. package/dist/checkbox.stories.d.ts +1 -1
  33. package/dist/checkbox.styles.js +10 -0
  34. package/dist/checkbox.test.basics.js +15 -6
  35. package/dist/checkbox.test.events.js +16 -8
  36. package/dist/checkbox.test.focus.js +3 -3
  37. package/dist/checkbox.test.form.js +1 -0
  38. package/dist/checkbox.test.interactions.js +123 -0
  39. package/dist/drawer.d.ts +5 -5
  40. package/dist/drawer.js +1 -1
  41. package/dist/drawer.stories.d.ts +0 -1
  42. package/dist/dropdown.d.ts +9 -6
  43. package/dist/dropdown.js +1 -1
  44. package/dist/dropdown.option.d.ts +6 -2
  45. package/dist/dropdown.option.js +1 -1
  46. package/dist/dropdown.option.styles.js +13 -0
  47. package/dist/dropdown.option.test.basics.js +6 -3
  48. package/dist/dropdown.option.test.events.js +1 -1
  49. package/dist/dropdown.option.test.focus.js +1 -1
  50. package/dist/dropdown.option.test.interactions.multiple.js +1 -54
  51. package/dist/dropdown.option.test.interactions.single.js +51 -9
  52. package/dist/dropdown.styles.js +20 -19
  53. package/dist/dropdown.test.basics.js +143 -2
  54. package/dist/dropdown.test.basics.multiple.js +5 -2
  55. package/dist/dropdown.test.events.filterable.js +74 -0
  56. package/dist/dropdown.test.events.js +49 -160
  57. package/dist/dropdown.test.events.multiple.js +265 -8
  58. package/dist/dropdown.test.events.single.js +199 -2
  59. package/dist/dropdown.test.focus.filterable.js +9 -5
  60. package/dist/dropdown.test.focus.js +1 -1
  61. package/dist/dropdown.test.focus.multiple.js +1 -1
  62. package/dist/dropdown.test.focus.single.js +1 -1
  63. package/dist/dropdown.test.interactions.filterable.js +68 -11
  64. package/dist/dropdown.test.interactions.js +94 -5
  65. package/dist/dropdown.test.interactions.multiple.js +202 -5
  66. package/dist/dropdown.test.interactions.single.js +68 -6
  67. package/dist/form-controls-layout.test.basics.js +1 -1
  68. package/dist/icon-button.d.ts +2 -0
  69. package/dist/icon-button.test.basics.js +1 -1
  70. package/dist/icons/checked.d.ts +1 -1
  71. package/dist/icons/checked.js +1 -1
  72. package/dist/icons/magnifying-glass.js +1 -1
  73. package/dist/input.d.ts +4 -9
  74. package/dist/input.js +1 -1
  75. package/dist/input.styles.js +7 -2
  76. package/dist/input.test.basics.js +19 -5
  77. package/dist/input.test.events.js +4 -4
  78. package/dist/input.test.focus.js +4 -4
  79. package/dist/input.test.translations.d.ts +1 -0
  80. package/dist/input.test.translations.js +38 -0
  81. package/dist/input.test.validity.js +133 -4
  82. package/dist/label.d.ts +1 -1
  83. package/dist/label.js +1 -1
  84. package/dist/label.styles.js +25 -13
  85. package/dist/label.test.basics.js +26 -24
  86. package/dist/library/expect-argument-error.js +1 -1
  87. package/dist/library/localize.d.ts +4 -1
  88. package/dist/menu.d.ts +3 -5
  89. package/dist/menu.js +1 -1
  90. package/dist/menu.options.test.basics.js +2 -2
  91. package/dist/menu.styles.js +1 -15
  92. package/dist/menu.test.basics.d.ts +1 -2
  93. package/dist/menu.test.basics.js +22 -6
  94. package/dist/menu.test.events.js +197 -7
  95. package/dist/menu.test.focus.d.ts +1 -0
  96. package/dist/menu.test.focus.js +13 -6
  97. package/dist/menu.test.interactions.js +214 -58
  98. package/dist/modal.icon-button.test.basics.js +1 -1
  99. package/dist/modal.js +1 -1
  100. package/dist/modal.stories.d.ts +1 -0
  101. package/dist/modal.styles.js +18 -13
  102. package/dist/modal.tertiary-icon.d.ts +0 -1
  103. package/dist/modal.tertiary-icon.js +1 -1
  104. package/dist/modal.tertiary-icon.test.basics.js +3 -3
  105. package/dist/modal.test.basics.js +1 -1
  106. package/dist/modal.test.events.js +10 -10
  107. package/dist/radio-group.d.ts +4 -3
  108. package/dist/radio-group.js +1 -1
  109. package/dist/radio-group.stories.d.ts +1 -1
  110. package/dist/radio-group.styles.js +1 -1
  111. package/dist/radio-group.test.focus.js +3 -3
  112. package/dist/radio.d.ts +2 -2
  113. package/dist/radio.js +1 -1
  114. package/dist/radio.styles.js +33 -0
  115. package/dist/split-container.d.ts +1 -1
  116. package/dist/split-container.test.basics.js +4 -0
  117. package/dist/split-link.test.interactions.js +1 -1
  118. package/dist/status-indicator.d.ts +1 -1
  119. package/dist/styles/variables.css +1 -1
  120. package/dist/tab.d.ts +1 -1
  121. package/dist/tab.group.js +1 -1
  122. package/dist/tab.group.test.basics.js +1 -1
  123. package/dist/tab.group.test.interactions.js +198 -2
  124. package/dist/tab.js +1 -1
  125. package/dist/tab.panel.d.ts +1 -0
  126. package/dist/tab.panel.js +1 -1
  127. package/dist/tab.panel.styles.js +11 -1
  128. package/dist/tabs.stories.d.ts +1 -0
  129. package/dist/tag.d.ts +3 -6
  130. package/dist/tag.test.basics.js +2 -2
  131. package/dist/textarea.d.ts +4 -4
  132. package/dist/textarea.js +2 -2
  133. package/dist/textarea.stories.d.ts +3 -4
  134. package/dist/textarea.styles.js +14 -3
  135. package/dist/textarea.test.basics.js +80 -44
  136. package/dist/textarea.test.events.js +56 -41
  137. package/dist/textarea.test.translations.d.ts +1 -0
  138. package/dist/textarea.test.translations.js +34 -0
  139. package/dist/textarea.test.validity.js +104 -20
  140. package/dist/toasts.js +1 -1
  141. package/dist/toasts.styles.js +8 -1
  142. package/dist/toasts.test.basics.js +20 -0
  143. package/dist/toggle.d.ts +3 -3
  144. package/dist/toggle.js +1 -1
  145. package/dist/toggle.stories.d.ts +1 -1
  146. package/dist/toggle.test.focus.js +1 -1
  147. package/dist/toggle.test.interactions.d.ts +1 -0
  148. package/dist/{toggle.test.states.js → toggle.test.interactions.js} +26 -0
  149. package/dist/tooltip.d.ts +9 -7
  150. package/dist/tooltip.js +1 -1
  151. package/dist/tooltip.styles.js +90 -25
  152. package/dist/tooltip.test.basics.js +38 -3
  153. package/dist/tooltip.test.interactions.js +136 -34
  154. package/dist/translations/en.js +1 -1
  155. package/dist/translations/fr.js +1 -1
  156. package/dist/translations/ja.js +1 -1
  157. package/dist/tree.d.ts +1 -2
  158. package/dist/tree.item.d.ts +1 -5
  159. package/dist/tree.item.icon-button.d.ts +1 -0
  160. package/dist/tree.item.icon-button.js +1 -1
  161. package/dist/tree.item.icon-button.test.basics.js +9 -0
  162. package/dist/tree.item.js +1 -1
  163. package/dist/tree.item.menu.d.ts +2 -1
  164. package/dist/tree.item.menu.js +1 -1
  165. package/dist/tree.item.menu.test.basics.js +15 -0
  166. package/dist/tree.item.styles.js +2 -0
  167. package/dist/tree.item.test.basics.d.ts +2 -1
  168. package/dist/tree.item.test.basics.js +46 -4
  169. package/dist/tree.js +1 -1
  170. package/dist/tree.test.basics.js +1 -1
  171. package/dist/tree.test.focus.js +91 -4
  172. package/package.json +3 -4
  173. package/dist/checkbox.test.states.js +0 -63
  174. package/dist/drawer.test.floating-components.d.ts +0 -1
  175. package/dist/drawer.test.floating-components.js +0 -52
  176. package/dist/library/set-containing-block.d.ts +0 -15
  177. package/dist/library/set-containing-block.js +0 -1
  178. package/dist/modal.test.floating-components.js +0 -63
  179. /package/dist/{checkbox.test.states.d.ts → button-group.button.test.focus.d.ts} +0 -0
  180. /package/dist/{modal.test.floating-components.d.ts → checkbox.test.interactions.d.ts} +0 -0
  181. /package/dist/{toggle.test.states.d.ts → dropdown.test.events.filterable.d.ts} +0 -0
@@ -1,20 +1,68 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-expressions */
2
2
  import './tooltip.js';
3
- import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
3
+ import { aTimeout, assert, expect, fixture, html } from '@open-wc/testing';
4
4
  import { sendKeys } from '@web/test-runner-commands';
5
5
  import GlideCoreTooltip from './tooltip.js';
6
- import sinon from 'sinon';
7
6
  GlideCoreTooltip.shadowRootOptions.mode = 'open';
7
+ it('is open when opened programmatically', async () => {
8
+ const component = await fixture(html `<glide-core-tooltip aria-label="Label">
9
+ Tooltip
10
+ <span slot="target" tabindex="0">Target</span>
11
+ </glide-core-tooltip>`);
12
+ component.open = true;
13
+ // Wait for Floating UI.
14
+ await aTimeout(0);
15
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
16
+ expect(tooltip?.checkVisibility()).to.be.true;
17
+ });
18
+ it('is open when `open` and enabled programmatically', async () => {
19
+ const component = await fixture(html `<glide-core-tooltip aria-label="Label" open disabled>
20
+ Tooltip
21
+ <span slot="target" tabindex="0">Target</span>
22
+ </glide-core-tooltip>`);
23
+ component.disabled = false;
24
+ // Wait for Floating UI.
25
+ await aTimeout(0);
26
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
27
+ expect(tooltip?.checkVisibility()).to.be.true;
28
+ });
29
+ it('is not open when `open` and disabled programmatically', async () => {
30
+ const component = await fixture(html `<glide-core-tooltip aria-label="Label" open>
31
+ Tooltip
32
+ <span slot="target" tabindex="0">Target</span>
33
+ </glide-core-tooltip>`);
34
+ // Wait for Floating UI.
35
+ await aTimeout(0);
36
+ component.disabled = true;
37
+ // Wait for Floating UI.
38
+ await aTimeout(0);
39
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
40
+ expect(tooltip?.checkVisibility()).to.be.false;
41
+ });
42
+ it('is not open when opened programmatically and disabled', async () => {
43
+ const component = await fixture(html `<glide-core-tooltip aria-label="Label" disabled>
44
+ Tooltip
45
+ <span slot="target" tabindex="0">Target</span>
46
+ </glide-core-tooltip>`);
47
+ component.open = true;
48
+ // Wait for Floating UI.
49
+ await aTimeout(0);
50
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
51
+ expect(tooltip?.checkVisibility()).to.be.false;
52
+ });
8
53
  it('is visible on "focusin"', async () => {
9
54
  const component = await fixture(html `<glide-core-tooltip>
10
55
  Tooltip
11
56
  <span slot="target" tabindex="0">Target</span>
12
57
  </glide-core-tooltip>`);
13
58
  component.shadowRoot
14
- ?.querySelector('[aria-labelledby="tooltip"]')
59
+ ?.querySelector('[data-test="target"]')
15
60
  ?.dispatchEvent(new FocusEvent('focusin'));
16
- await elementUpdated(component);
17
- expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.true;
61
+ // Wait for Floating UI.
62
+ await aTimeout(0);
63
+ expect(component.shadowRoot
64
+ ?.querySelector('[data-test="tooltip"]')
65
+ ?.checkVisibility()).to.be.true;
18
66
  });
19
67
  it('is hidden on "focusin" when disabled', async () => {
20
68
  const component = await fixture(html `<glide-core-tooltip disabled>
@@ -22,25 +70,27 @@ it('is hidden on "focusin" when disabled', async () => {
22
70
  <span slot="target" tabindex="0">Target</span>
23
71
  </glide-core-tooltip>`);
24
72
  component.shadowRoot
25
- ?.querySelector('[aria-labelledby="tooltip"]')
73
+ ?.querySelector('[data-test="target"]')
26
74
  ?.dispatchEvent(new FocusEvent('focusin'));
27
- await elementUpdated(component);
28
- expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.not.be.ok;
75
+ // Wait for Floating UI.
76
+ await aTimeout(0);
77
+ expect(component.shadowRoot
78
+ ?.querySelector('[data-test="tooltip"]')
79
+ ?.checkVisibility()).to.be.false;
29
80
  });
30
81
  it('is hidden on "blur"', async () => {
31
82
  const component = await fixture(html `<glide-core-tooltip>
32
83
  Tooltip
33
84
  <span slot="target" tabindex="0">Target</span>
34
85
  </glide-core-tooltip>`);
35
- component.shadowRoot
36
- ?.querySelector('[aria-labelledby="tooltip"]')
37
- ?.dispatchEvent(new FocusEvent('focusin'));
38
- await elementUpdated(component);
39
- component.shadowRoot
40
- ?.querySelector('[aria-labelledby="tooltip"]')
41
- ?.dispatchEvent(new FocusEvent('focusout'));
42
- await elementUpdated(component);
43
- expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.false;
86
+ const target = component.shadowRoot?.querySelector('[data-test="target"]');
87
+ target?.dispatchEvent(new FocusEvent('focusin'));
88
+ // Wait for Floating UI.
89
+ await aTimeout(0);
90
+ target?.dispatchEvent(new FocusEvent('focusout'));
91
+ expect(component.shadowRoot
92
+ ?.querySelector('[data-test="tooltip"]')
93
+ ?.checkVisibility()).to.be.false;
44
94
  });
45
95
  it('is hidden on Escape', async () => {
46
96
  const component = await fixture(html `<glide-core-tooltip>
@@ -48,54 +98,106 @@ it('is hidden on Escape', async () => {
48
98
  <span slot="target" tabindex="0">Target</span>
49
99
  </glide-core-tooltip>`);
50
100
  component.shadowRoot
51
- ?.querySelector('[aria-labelledby="tooltip"]')
101
+ ?.querySelector('[data-test="target"]')
52
102
  ?.dispatchEvent(new FocusEvent('focusin'));
53
- await elementUpdated(component);
54
- // So the key is sent to the component instead of `<body>`. It's not
55
- // clear why `component.focus()` doesn't focus the span when using
56
- // Playwright.
103
+ // Wait for Floating UI.
104
+ await aTimeout(0);
57
105
  component.querySelector('span')?.focus();
58
106
  await sendKeys({ press: 'Escape' });
59
- await elementUpdated(component);
60
- expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.false;
107
+ expect(component.shadowRoot
108
+ ?.querySelector('[data-test="tooltip"]')
109
+ ?.checkVisibility()).to.be.false;
61
110
  });
62
111
  it('is visible on "mouseover"', async () => {
63
112
  const component = await fixture(html `<glide-core-tooltip>
64
113
  Tooltip
65
114
  <span slot="target" tabindex="0">Target</span>
66
115
  </glide-core-tooltip>`);
116
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
117
+ assert(tooltip);
118
+ tooltip.dataset.openDelay = '0';
67
119
  component.shadowRoot
68
120
  ?.querySelector('.component')
69
121
  ?.dispatchEvent(new MouseEvent('mouseover'));
70
- await elementUpdated(component);
71
- expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.true;
122
+ // Wait for Floating UI and the open delay.
123
+ await aTimeout(0);
124
+ expect(tooltip.checkVisibility()).to.be.true;
72
125
  });
73
126
  it('is hidden on "mouseover" when disabled', async () => {
74
127
  const component = await fixture(html `<glide-core-tooltip disabled>
75
128
  Tooltip
76
129
  <span slot="target" tabindex="0">Target</span>
77
130
  </glide-core-tooltip>`);
131
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
132
+ assert(tooltip);
133
+ tooltip.dataset.openDelay = '0';
78
134
  component.shadowRoot
79
135
  ?.querySelector('.component')
80
136
  ?.dispatchEvent(new MouseEvent('mouseover'));
81
- await elementUpdated(component);
82
- expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.not.be.ok;
137
+ // Wait for Floating UI.
138
+ await aTimeout(0);
139
+ expect(tooltip.checkVisibility()).to.be.false;
83
140
  });
84
141
  it('is hidden on "mouseout"', async () => {
85
- const clock = sinon.useFakeTimers();
86
142
  const component = await fixture(html `<glide-core-tooltip>
87
143
  Tooltip
88
144
  <span slot="target" tabindex="0">Target</span>
89
145
  </glide-core-tooltip>`);
146
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
147
+ assert(tooltip);
148
+ tooltip.dataset.openDelay = '0';
149
+ component.shadowRoot
150
+ ?.querySelector('.component')
151
+ ?.dispatchEvent(new MouseEvent('mouseover'));
152
+ // Wait for Floating UI and the open delay.
153
+ await aTimeout(0);
154
+ tooltip.dataset.closeDelay = '0';
155
+ component.shadowRoot
156
+ ?.querySelector('.component')
157
+ ?.dispatchEvent(new MouseEvent('mouseout'));
158
+ // Wait for the close delay.
159
+ await aTimeout(0);
160
+ expect(tooltip.checkVisibility()).to.be.false;
161
+ });
162
+ it('remains hidden if "mouseout" fires before the "mouseover" delay', async () => {
163
+ const component = await fixture(html `<glide-core-tooltip>
164
+ Tooltip
165
+ <span slot="target" tabindex="0">Target</span>
166
+ </glide-core-tooltip>`);
167
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
168
+ assert(tooltip);
169
+ tooltip.dataset.openDelay = '1';
170
+ tooltip.dataset.closeDelay = '0';
90
171
  component.shadowRoot
91
172
  ?.querySelector('.component')
92
173
  ?.dispatchEvent(new MouseEvent('mouseover'));
93
- await elementUpdated(component);
174
+ expect(tooltip?.checkVisibility()).to.be.false;
94
175
  component.shadowRoot
95
176
  ?.querySelector('.component')
96
177
  ?.dispatchEvent(new MouseEvent('mouseout'));
97
- clock.tick(300);
98
- await elementUpdated(component);
99
- expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.false;
100
- clock.restore();
178
+ await aTimeout(1);
179
+ expect(tooltip.checkVisibility()).to.be.false;
180
+ });
181
+ // This would be better served by a visual regression test. It exists only
182
+ // to meet our coverage threshold, so the `middlewareData.arrow.y` branch
183
+ // is hit.
184
+ it('positions the tooltip when `placement="right"`', async () => {
185
+ const component = await fixture(html `<glide-core-tooltip
186
+ placement="right"
187
+ style="align-items: center; display: flex; height: 100vh; justify-content:center; width: 100vw;"
188
+ >
189
+ Tooltip
190
+ <span slot="target" tabindex="0">Target</span>
191
+ </glide-core-tooltip>`);
192
+ component.shadowRoot
193
+ ?.querySelector('[data-test="target"]')
194
+ ?.dispatchEvent(new FocusEvent('focusin'));
195
+ // Wait for Floating UI.
196
+ await aTimeout(0);
197
+ const tooltipContainer = component.shadowRoot?.querySelector('[data-test="tooltip"]');
198
+ const arrow = component.shadowRoot?.querySelector('[data-test="arrow"]');
199
+ expect(tooltipContainer?.style.left).to.not.be.empty.string;
200
+ expect(tooltipContainer?.style.top).to.not.be.empty.string;
201
+ expect(arrow?.style.left).to.be.empty.string;
202
+ expect(arrow?.style.top).to.not.be.empty.string;
101
203
  });
@@ -1 +1 @@
1
- const translation={$code:"en",$name:"English",$dir:"ltr",close:"Close",dismiss:"Dismiss",open:"Open",selectAll:"Select all",clearEntry:"Clear entry",moreInformation:"More information",nextTab:"Next tab",notifications:"Notifications",previousTab:"Previous tab",removeTag:e=>`Remove tag: ${e}`};export default translation;
1
+ const translation={$code:"en",$name:"English",$dir:"ltr",close:"Close",dismiss:"Dismiss",open:"Open",selectAll:"Select all",moreInformation:"More information",nextTab:"Next tab",notifications:"Notifications",previousTab:"Previous tab",announcedCharacterCount:(e,o)=>`Character count ${e} of ${o}`,displayedCharacterCount:(e,o)=>`${e}/${o}`,clearEntry:e=>`Clear ${e} entry`,removeTag:e=>`Remove tag: ${e}`,actionsFor:e=>`Actions for ${e}`};export default translation;
@@ -1 +1 @@
1
- const translation={$code:"fr",$name:"French",$dir:"ltr",close:"Fermer",dismiss:"Congédier",open:"Ouvrir",selectAll:"Tout sélectionner",clearEntry:"Effacer l’entrée",moreInformation:"Plus d’informations",notifications:"Notifications",nextTab:"",previousTab:"",removeTag:e=>`Supprimer la balise : ${e}`};export default translation;
1
+ const translation={$code:"fr",$name:"French",$dir:"ltr",close:"Fermer",dismiss:"Congédier",open:"Ouvrir",selectAll:"Tout sélectionner",moreInformation:"Plus d’informations",notifications:"Notifications",nextTab:"Next tab",previousTab:"Previous tab",announcedCharacterCount:(r,e)=>`Character count ${r} of ${e}`,displayedCharacterCount:(r,e)=>`${r}/${e}`,clearEntry:r=>`Clear ${r} entry`,removeTag:r=>`Supprimer la balise : ${r}`,actionsFor:r=>`Actions for ${r}`};export default translation;
@@ -1 +1 @@
1
- const translation={$code:"ja",$name:"Japanese",$dir:"ltr",close:"閉じる",dismiss:"無視",open:"オープン",selectAll:"すべて選択",clearEntry:"入力のクリア",moreInformation:"詳細情報",notifications:"通知",nextTab:"",previousTab:"",removeTag:e=>`タグを削除: ${e}`};export default translation;
1
+ const translation={$code:"ja",$name:"Japanese",$dir:"ltr",close:"閉じる",dismiss:"無視",open:"オープン",selectAll:"すべて選択",moreInformation:"詳細情報",notifications:"通知",nextTab:"Next tab",previousTab:"Previous tab",announcedCharacterCount:(a,t)=>`Character count ${a} of ${t}`,displayedCharacterCount:(a,t)=>`${a}/${t}`,clearEntry:a=>`Clear ${a} entry`,removeTag:a=>`タグを削除: ${a}`,actionsFor:a=>`Actions for ${a}`};export default translation;
package/dist/tree.d.ts CHANGED
@@ -6,7 +6,7 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @description A tree element, containing a hierarchy of tree items
9
+ * @description A tree containing a hierarchy of Tree Items.
10
10
  *
11
11
  * @slot - One or more of <glide-core-tree-item>
12
12
  */
@@ -22,6 +22,5 @@ export default class GlideCoreTree extends LitElement {
22
22
  firstUpdated(): void;
23
23
  render(): import("lit").TemplateResult<1>;
24
24
  selectItem(item: GlideCoreTreeItem): void;
25
- setContainingBlock(containingBlock: Element): void;
26
25
  constructor();
27
26
  }
@@ -1,6 +1,5 @@
1
1
  import './tree.item.menu.js';
2
2
  import { LitElement } from 'lit';
3
- import type GlideCoreMenu from './menu.js';
4
3
  declare global {
5
4
  interface HTMLElementTagNameMap {
6
5
  'glide-core-tree-item': GlideCoreTreeItem;
@@ -24,12 +23,10 @@ export default class GlideCoreTreeItem extends LitElement {
24
23
  selected: boolean;
25
24
  removeIndentation: boolean;
26
25
  nonCollapsible: boolean;
27
- menuSlotAssignedElements: GlideCoreMenu[];
28
- prefixSlotAssignedElements: HTMLElement[];
29
26
  slotElements: GlideCoreTreeItem[];
30
27
  suffixSlotAssignedElements: HTMLElement[];
31
28
  firstUpdated(): void;
32
- focus(): void;
29
+ focus(options?: FocusOptions): void;
33
30
  get hasChildTreeItems(): boolean;
34
31
  get hasExpandIcon(): boolean;
35
32
  render(): import("lit").TemplateResult<1>;
@@ -39,7 +36,6 @@ export default class GlideCoreTreeItem extends LitElement {
39
36
  * Returns the selected item
40
37
  */
41
38
  selectItem(item: GlideCoreTreeItem): GlideCoreTreeItem | undefined;
42
- setContainingBlock(containingBlock: Element): void;
43
39
  toggleExpand(): void;
44
40
  private childTreeItems;
45
41
  }
@@ -15,6 +15,7 @@ export default class GlideCoreTreeItemIconButton extends LitElement {
15
15
  #private;
16
16
  static shadowRootOptions: ShadowRootInit;
17
17
  static styles: import("lit").CSSResult[];
18
+ label: string;
18
19
  firstUpdated(): void;
19
20
  render(): import("lit").TemplateResult<1>;
20
21
  }
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,r){var l,n=arguments.length,i=n<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,r);else for(var s=e.length-1;s>=0;s--)(l=e[s])&&(i=(n<3?l(i):n>3?l(t,o,i):l(t,o))||i);return n>3&&i&&Object.defineProperty(t,o,i),i};import"./icon-button.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement}from"lit/decorators.js";import{owSlot}from"./library/ow.js";import styles from"./tree.item.icon-button.styles.js";let GlideCoreTreeItemIconButton=class GlideCoreTreeItemIconButton extends LitElement{static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#e.value)}render(){return html`<glide-core-icon-button class="component" variant="tertiary"><slot @slotchange="${this.#t}" ${ref(this.#e)}></slot></glide-core-icon-button>`}#e=createRef();#t(){owSlot(this.#e.value)}};GlideCoreTreeItemIconButton=__decorate([customElement("glide-core-tree-item-icon-button")],GlideCoreTreeItemIconButton);export default GlideCoreTreeItemIconButton;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,r){var l,n=arguments.length,i=n<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,r);else for(var s=e.length-1;s>=0;s--)(l=e[s])&&(i=(n<3?l(i):n>3?l(t,o,i):l(t,o))||i);return n>3&&i&&Object.defineProperty(t,o,i),i};import"./icon-button.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{owSlot}from"./library/ow.js";import styles from"./tree.item.icon-button.styles.js";let GlideCoreTreeItemIconButton=class GlideCoreTreeItemIconButton extends LitElement{constructor(){super(...arguments),this.label="",this.#e=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#e.value)}render(){return html`<glide-core-icon-button class="component" variant="tertiary" tabindex="-1" label="${this.label}"><slot @slotchange="${this.#t}" ${ref(this.#e)}></slot></glide-core-icon-button>`}#e;#t(){owSlot(this.#e.value)}};__decorate([property()],GlideCoreTreeItemIconButton.prototype,"label",void 0),GlideCoreTreeItemIconButton=__decorate([customElement("glide-core-tree-item-icon-button")],GlideCoreTreeItemIconButton);export default GlideCoreTreeItemIconButton;
@@ -1,6 +1,7 @@
1
1
  import { expect, fixture, html } from '@open-wc/testing';
2
2
  import GlideCoreTreeItemIconButton from './tree.item.icon-button.js';
3
3
  import expectArgumentError from './library/expect-argument-error.js';
4
+ GlideCoreTreeItemIconButton.shadowRootOptions.mode = 'open';
4
5
  it('registers', async () => {
5
6
  expect(window.customElements.get('glide-core-tree-item-icon-button')).to.equal(GlideCoreTreeItemIconButton);
6
7
  });
@@ -11,3 +12,11 @@ it('throws if it does not have a default slot', async () => {
11
12
  `);
12
13
  });
13
14
  });
15
+ it('passes its label to the icon button', async () => {
16
+ const component = await fixture(html `
17
+ <glide-core-tree-item-icon-button label="My label"
18
+ >Hello</glide-core-tree-item-icon-button
19
+ >
20
+ `);
21
+ expect(component.shadowRoot?.querySelector('glide-core-icon-button')?.label).to.equal('My label');
22
+ });
package/dist/tree.item.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,i,o){var s,r=arguments.length,l=r<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,i,o);else for(var n=e.length-1;n>=0;n--)(s=e[n])&&(l=(r<3?s(l):r>3?s(t,i,l):s(t,i))||l);return r>3&&l&&Object.defineProperty(t,i,l),l};import"./tree.item.menu.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,queryAssignedElements,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{when}from"lit/directives/when.js";import styles from"./tree.item.styles.js";let GlideCoreTreeItem=class GlideCoreTreeItem extends LitElement{constructor(){super(...arguments),this.expanded=!1,this.label="",this.level=1,this.selected=!1,this.removeIndentation=!1,this.nonCollapsible=!1,this.childTreeItems=[],this.#e=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}firstUpdated(){this.#t()}focus(){this.#e.value?.focus()}get hasChildTreeItems(){return this.childTreeItems.length>0}get hasExpandIcon(){return this.hasChildTreeItems&&!this.nonCollapsible}render(){return html`<div class="${classMap({component:!0,expanded:this.expanded,selected:this.selected})}" role="treeitem" aria-label="${this.label}" aria-selected="${ifDefined(this.#i)}" aria-expanded="${ifDefined(this.#o)}"><div class="${classMap({"label-container":!0})}" tabindex="-1" ${ref(this.#e)}><div style="flex-shrink: 0; width:${this.#s};"></div>${when(!this.removeIndentation||this.hasExpandIcon,(()=>html`<div class="expand-icon-container">${when(this.hasExpandIcon,(()=>html`<div><svg aria-hidden="true" class="${classMap({"expand-icon":!0,"expand-icon-expanded":this.expanded})}" width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></div>`))}</div>`))}<slot name="prefix"></slot><div class="label">${this.label}</div><div class="icon-container"><slot name="menu"></slot><slot name="suffix"></slot></div></div><div class="child-items" role="group"><slot></slot></div></div>`}selectItem(e){let t;for(const i of this.slotElements)if(e===i)i.setAttribute("selected","true"),t=i;else{i.removeAttribute("selected");const o=i.selectItem(e);o&&(t=o)}return t}setContainingBlock(e){for(const t of this.menuSlotAssignedElements)t.setContainingBlock(e)}toggleExpand(){this.expanded=!this.expanded}#e;get#o(){return this.hasChildTreeItems?this.expanded?"true":"false":void 0}get#i(){return this.hasChildTreeItems?void 0:this.selected?"true":"false"}get#s(){return 20*(this.level-1)+"px"}#t(){const e=[];for(const t of this.slotElements)t.level=this.level+1,e.push(t);this.childTreeItems=e}};__decorate([property({type:Boolean})],GlideCoreTreeItem.prototype,"expanded",void 0),__decorate([property({reflect:!0})],GlideCoreTreeItem.prototype,"label",void 0),__decorate([property({type:Number})],GlideCoreTreeItem.prototype,"level",void 0),__decorate([property({type:Boolean})],GlideCoreTreeItem.prototype,"selected",void 0),__decorate([property({type:Boolean,attribute:"remove-indentation"})],GlideCoreTreeItem.prototype,"removeIndentation",void 0),__decorate([property({type:Boolean,attribute:"non-collapsible"})],GlideCoreTreeItem.prototype,"nonCollapsible",void 0),__decorate([queryAssignedElements({slot:"menu"})],GlideCoreTreeItem.prototype,"menuSlotAssignedElements",void 0),__decorate([queryAssignedElements({slot:"prefix"})],GlideCoreTreeItem.prototype,"prefixSlotAssignedElements",void 0),__decorate([queryAssignedElements()],GlideCoreTreeItem.prototype,"slotElements",void 0),__decorate([queryAssignedElements({slot:"suffix"})],GlideCoreTreeItem.prototype,"suffixSlotAssignedElements",void 0),__decorate([state()],GlideCoreTreeItem.prototype,"childTreeItems",void 0),GlideCoreTreeItem=__decorate([customElement("glide-core-tree-item")],GlideCoreTreeItem);export default GlideCoreTreeItem;
1
+ var _a,GlideCoreTreeItem_1,__decorate=this&&this.__decorate||function(e,t,o,i){var r,s=arguments.length,l=s<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,o,i);else for(var n=e.length-1;n>=0;n--)(r=e[n])&&(l=(s<3?r(l):s>3?r(t,o,l):r(t,o))||l);return s>3&&l&&Object.defineProperty(t,o,l),l};import"./tree.item.menu.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,queryAssignedElements,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{when}from"lit/directives/when.js";import GlideCoreIconButton from"./icon-button.js";import GlideCoreTreeItemMenu from"./tree.item.menu.js";import ow,{owSlotType}from"./library/ow.js";import styles from"./tree.item.styles.js";let GlideCoreTreeItem=class GlideCoreTreeItem extends LitElement{constructor(){super(...arguments),this.expanded=!1,this.label="",this.level=1,this.selected=!1,this.removeIndentation=!1,this.nonCollapsible=!1,this.childTreeItems=[],this.#e=createRef(),this.#t=new LocalizeController(this),this.#o=createRef()}static{GlideCoreTreeItem_1=this}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}firstUpdated(){this.#i()}focus(e){this.#e.value?.focus(e),this.#r(0)}get hasChildTreeItems(){return this.childTreeItems.length>0}get hasExpandIcon(){return this.hasChildTreeItems&&!this.nonCollapsible}render(){return html`<div class="${classMap({component:!0,expanded:this.expanded,selected:this.selected})}" role="treeitem" aria-label="${this.label}" aria-selected="${ifDefined(this.#s)}" aria-expanded="${ifDefined(this.#l)}"><div class="${classMap({"label-container":!0})}" tabindex="-1" @focusout="${this.#n}" @focusin="${this.#a}" ${ref(this.#e)}><div style="flex-shrink: 0; width:${this.#d};"></div>${when(!this.removeIndentation||this.hasExpandIcon,(()=>html`<div class="expand-icon-container">${when(this.hasExpandIcon,(()=>html`<div><svg aria-hidden="true" class="${classMap({"expand-icon":!0,"expand-icon-expanded":this.expanded})}" width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></div>`))}</div>`))}<slot name="prefix"></slot><div class="label">${this.label}</div><div class="icon-container"><slot name="menu" ${ref(this.#o)} @slotchange="${this.#c}"></slot><slot name="suffix"></slot></div></div><div class="child-items" role="group"><slot></slot></div></div>`}selectItem(e){let t;for(const o of this.slotElements)if(e===o)o.setAttribute("selected","true"),t=o;else{o.removeAttribute("selected");const i=o.selectItem(e);i&&(t=i)}return t}toggleExpand(){this.expanded=!this.expanded}#e;#t;#o;get#l(){return this.hasChildTreeItems?this.expanded?"true":"false":void 0}get#s(){return this.hasChildTreeItems?void 0:this.selected?"true":"false"}#a(e){this.#m(e.target)&&e.stopPropagation()}#n(e){this.#m(e.relatedTarget)?e.stopPropagation():this.#r(-1)}get#d(){return 20*(this.level-1)+"px"}#m(e){return e&&e instanceof HTMLElement&&!(e instanceof GlideCoreTreeItem_1)&&this.contains(e)}#c(){owSlotType(this.#o.value,[GlideCoreTreeItemMenu]);for(const e of this.#o.value.assignedElements())e instanceof GlideCoreTreeItemMenu&&(e.label=this.#t.term("actionsFor",this.label))}#r(e){ow(this.#e.value,ow.object.instanceOf(HTMLElement)),this.#e.value.tabIndex=e;for(const t of this.querySelectorAll("& > glide-core-tree-item-icon-button"))t.tabIndex=e}#i(){const e=[];for(const t of this.slotElements)t.level=this.level+1,e.push(t);this.childTreeItems=e}};__decorate([property({type:Boolean})],GlideCoreTreeItem.prototype,"expanded",void 0),__decorate([property({reflect:!0})],GlideCoreTreeItem.prototype,"label",void 0),__decorate([property({type:Number})],GlideCoreTreeItem.prototype,"level",void 0),__decorate([property({type:Boolean})],GlideCoreTreeItem.prototype,"selected",void 0),__decorate([property({type:Boolean,attribute:"remove-indentation"})],GlideCoreTreeItem.prototype,"removeIndentation",void 0),__decorate([property({type:Boolean,attribute:"non-collapsible"})],GlideCoreTreeItem.prototype,"nonCollapsible",void 0),__decorate([queryAssignedElements()],GlideCoreTreeItem.prototype,"slotElements",void 0),__decorate([queryAssignedElements({slot:"suffix"})],GlideCoreTreeItem.prototype,"suffixSlotAssignedElements",void 0),__decorate([state()],GlideCoreTreeItem.prototype,"childTreeItems",void 0),GlideCoreTreeItem=GlideCoreTreeItem_1=__decorate([customElement("glide-core-tree-item")],GlideCoreTreeItem);export default GlideCoreTreeItem;
@@ -19,7 +19,8 @@ export default class GlideCoreTreeItemMenu extends LitElement {
19
19
  static shadowRootOptions: ShadowRootInit;
20
20
  static styles: import("lit").CSSResult[];
21
21
  placement: Placement;
22
+ label: string;
23
+ click(): void;
22
24
  firstUpdated(): void;
23
25
  render(): import("lit").TemplateResult<1>;
24
- setContainingBlock(containingBlock: Element): void;
25
26
  }
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,l){var r,n=arguments.length,i=n<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 m=e.length-1;m>=0;m--)(r=e[m])&&(i=(n<3?r(i):n>3?r(t,o,i):r(t,o))||i);return n>3&&i&&Object.defineProperty(t,o,i),i};import"./icon-button.js";import"./menu.js";import"./menu.options.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{owSlot,owSlotType}from"./library/ow.js";import GlideCoreMenuButton from"./menu.button.js";import GlideCoreMenuLink from"./menu.link.js";import ow from"./library/ow.js";import styles from"./tree.item.menu.styles.js";let GlideCoreTreeItemMenu=class GlideCoreTreeItemMenu extends LitElement{constructor(){super(...arguments),this.placement="bottom-start",this.#e=createRef(),this.#t=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#e.value),owSlotType(this.#e.value,[GlideCoreMenuButton,GlideCoreMenuLink])}render(){return html`<glide-core-menu class="component" placement="${this.placement}" ${ref(this.#t)}><glide-core-menu-options><slot @slotchange="${this.#o}" ${ref(this.#e)}></slot></glide-core-menu-options><glide-core-icon-button slot="target" variant="tertiary"><svg width="4" height="14" viewBox="0 0 4 18" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 15C2.55228 15 3 15.4477 3 16C3 16.5523 2.55228 17 2 17C1.44772 17 1 16.5523 1 16C1 15.4477 1.44772 15 2 15Z"/><path d="M2 8C2.55228 8 3 8.44772 3 9C3 9.55228 2.55228 10 2 10C1.44772 10 1 9.55228 1 9C1 8.44772 1.44772 8 2 8Z"/><path d="M2 1C2.55228 1 3 1.44772 3 2C3 2.55228 2.55228 3 2 3C1.44772 3 1 2.55228 1 2C1 1.44772 1.44772 1 2 1Z"/></svg></glide-core-icon-button></glide-core-menu>`}setContainingBlock(e){ow(this.#t.value,ow.object.instanceOf(Element)),this.#t.value.setContainingBlock(e)}#e;#t;#o(){owSlot(this.#e.value),owSlotType(this.#e.value,[GlideCoreMenuButton,GlideCoreMenuLink])}};__decorate([property({reflect:!0})],GlideCoreTreeItemMenu.prototype,"placement",void 0),GlideCoreTreeItemMenu=__decorate([customElement("glide-core-tree-item-menu")],GlideCoreTreeItemMenu);export default GlideCoreTreeItemMenu;
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"./icon-button.js";import"./menu.js";import"./menu.options.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import GlideCoreIconButton from"./icon-button.js";import GlideCoreMenuButton from"./menu.button.js";import GlideCoreMenuLink from"./menu.link.js";import ow,{owSlot,owSlotType}from"./library/ow.js";import styles from"./tree.item.menu.styles.js";let GlideCoreTreeItemMenu=class GlideCoreTreeItemMenu extends LitElement{constructor(){super(...arguments),this.placement="bottom-start",this.label="",this.#e=createRef(),this.#t=createRef(),this.#o=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}click(){ow(this.#t.value,ow.object.instanceOf(GlideCoreIconButton)),this.#t.value.click()}firstUpdated(){owSlot(this.#e.value),owSlotType(this.#e.value,[GlideCoreMenuButton,GlideCoreMenuLink])}render(){return html`<glide-core-menu class="component" placement="${this.placement}" ${ref(this.#o)}><glide-core-menu-options><slot @slotchange="${this.#l}" ${ref(this.#e)}></slot></glide-core-menu-options><glide-core-icon-button slot="target" variant="tertiary" label="${this.label}" ${ref(this.#t)}><svg aria-hidden="true" width="4" height="14" viewBox="0 0 4 18" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 15C2.55228 15 3 15.4477 3 16C3 16.5523 2.55228 17 2 17C1.44772 17 1 16.5523 1 16C1 15.4477 1.44772 15 2 15Z"/><path d="M2 8C2.55228 8 3 8.44772 3 9C3 9.55228 2.55228 10 2 10C1.44772 10 1 9.55228 1 9C1 8.44772 1.44772 8 2 8Z"/><path d="M2 1C2.55228 1 3 1.44772 3 2C3 2.55228 2.55228 3 2 3C1.44772 3 1 2.55228 1 2C1 1.44772 1.44772 1 2 1Z"/></svg></glide-core-icon-button></glide-core-menu>`}#e;#t;#o;#l(){owSlot(this.#e.value),owSlotType(this.#e.value,[GlideCoreMenuButton,GlideCoreMenuLink])}};__decorate([property({reflect:!0})],GlideCoreTreeItemMenu.prototype,"placement",void 0),__decorate([property()],GlideCoreTreeItemMenu.prototype,"label",void 0),GlideCoreTreeItemMenu=__decorate([customElement("glide-core-tree-item-menu")],GlideCoreTreeItemMenu);export default GlideCoreTreeItemMenu;
@@ -48,3 +48,18 @@ it('can set placement of the menu', async () => {
48
48
  `);
49
49
  expect(treeItemMenu.shadowRoot?.querySelector('glide-core-menu')?.placement).to.equal('bottom-end');
50
50
  });
51
+ it('can be opened programmatically', async () => {
52
+ const treeItemMenu = await fixture(html `
53
+ <glide-core-tree-item-menu>
54
+ <glide-core-menu-link label="One" url="/one"> </glide-core-menu-link>
55
+ </glide-core-tree-item-menu>
56
+ `);
57
+ expect(treeItemMenu.shadowRoot
58
+ ?.querySelector('glide-core-menu')
59
+ ?.getAttribute('open')).to.equal(null);
60
+ treeItemMenu.click();
61
+ await treeItemMenu.updateComplete;
62
+ expect(treeItemMenu.shadowRoot
63
+ ?.querySelector('glide-core-menu')
64
+ ?.getAttribute('open')).to.equal('');
65
+ });
@@ -129,11 +129,13 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
129
129
  display: flex;
130
130
  flex-direction: column;
131
131
  overflow: hidden;
132
+ visibility: hidden;
132
133
  }
133
134
 
134
135
  .expanded {
135
136
  .child-items {
136
137
  block-size: auto;
138
+ visibility: visible;
137
139
  }
138
140
  }
139
141
 
@@ -1 +1,2 @@
1
- export {};
1
+ import './menu.link.js';
2
+ import './tree.item.menu.js';
@@ -1,7 +1,13 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ import './menu.link.js';
3
+ import './tree.item.menu.js';
2
4
  import { expect, fixture, html } from '@open-wc/testing';
5
+ import Menu from './menu.js';
3
6
  import TreeItem from './tree.item.js';
7
+ import TreeItemMenu from './tree.item.menu.js';
4
8
  TreeItem.shadowRootOptions.mode = 'open';
9
+ TreeItemMenu.shadowRootOptions.mode = 'open';
10
+ Menu.shadowRootOptions.mode = 'open';
5
11
  it('registers', () => {
6
12
  expect(window.customElements.get('glide-core-tree-item')).to.equal(TreeItem);
7
13
  });
@@ -32,13 +38,49 @@ it('renders with a prefix slot', async () => {
32
38
  `);
33
39
  expect(document.querySelector('[data-prefix]')).to.be.ok;
34
40
  });
35
- it('renders with a menu slot', async () => {
36
- await fixture(html `
41
+ it('adds label to menu target', async () => {
42
+ const treeItem = await fixture(html `
43
+ <glide-core-tree-item label="Item">
44
+ <glide-core-tree-item-menu slot="menu" data-menu>
45
+ <glide-core-menu-link label="Move" url="/move"> </glide-core-menu-link>
46
+ </glide-core-tree-item-menu>
47
+ </glide-core-tree-item>
48
+ `);
49
+ const menuTarget = treeItem
50
+ .querySelector('glide-core-tree-item-menu')
51
+ ?.shadowRoot?.querySelector('glide-core-menu')
52
+ ?.querySelector('glide-core-icon-button');
53
+ expect(menuTarget?.label).to.equal('Actions for Item');
54
+ });
55
+ it('adds Japanese label to menu', async () => {
56
+ document.documentElement.setAttribute('lang', 'ja');
57
+ const treeItem = await fixture(html `
58
+ <glide-core-tree-item label="Item">
59
+ <glide-core-tree-item-menu slot="menu" data-menu>
60
+ <glide-core-menu-link label="Move" url="/move"> </glide-core-menu-link>
61
+ </glide-core-tree-item-menu>
62
+ </glide-core-tree-item>
63
+ `);
64
+ const menuTarget = treeItem
65
+ .querySelector('glide-core-tree-item-menu')
66
+ ?.shadowRoot?.querySelector('glide-core-menu')
67
+ ?.querySelector('glide-core-icon-button');
68
+ expect(menuTarget?.label).to.equal('Actions for Item');
69
+ });
70
+ it('adds French label to menu', async () => {
71
+ document.documentElement.setAttribute('lang', 'fr');
72
+ const treeItem = await fixture(html `
37
73
  <glide-core-tree-item label="Item">
38
- <span slot="menu" data-menu>menu</span>
74
+ <glide-core-tree-item-menu slot="menu" data-menu>
75
+ <glide-core-menu-link label="Move" url="/move"> </glide-core-menu-link>
76
+ </glide-core-tree-item-menu>
39
77
  </glide-core-tree-item>
40
78
  `);
41
- expect(document.querySelector('[data-menu]')).to.be.ok;
79
+ const menuTarget = treeItem
80
+ .querySelector('glide-core-tree-item-menu')
81
+ ?.shadowRoot?.querySelector('glide-core-menu')
82
+ ?.querySelector('glide-core-icon-button');
83
+ expect(menuTarget?.label).to.equal('Actions for Item');
42
84
  });
43
85
  it('renders with a suffix slot', async () => {
44
86
  await fixture(html `
package/dist/tree.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,s){var l,r=arguments.length,i=r<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,o):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,s);else for(var n=e.length-1;n>=0;n--)(l=e[n])&&(i=(r<3?l(i):r>3?l(t,o,i):l(t,o))||i);return r>3&&i&&Object.defineProperty(t,o,i),i};import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,queryAssignedElements,state}from"lit/decorators.js";import{owSlot,owSlotType}from"./library/ow.js";import GlideCoreTreeItem from"./tree.item.js";import styles from"./tree.styles.js";let GlideCoreTree=class GlideCoreTree extends LitElement{static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("focusin",this.#e),this.removeEventListener("focusout",this.#t)}firstUpdated(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreTreeItem])}render(){return html`<div class="component" role="tree" tabindex="${this.privateTabIndex}" @click="${this.#s}" @keydown="${this.#l}"><slot @slotchange="${this.#r}" ${ref(this.#o)}></slot></div>`}selectItem(e){for(const t of this.slotElements){e===t?(t.setAttribute("selected","true"),this.selectedItem=t):t.removeAttribute("selected");const o=t.selectItem(e);o&&(this.selectedItem=o)}this.dispatchEvent(new CustomEvent("item-selected",{bubbles:!0,detail:e}))}setContainingBlock(e){for(const t of this.#i())t.setContainingBlock(e)}constructor(){super(),this.privateTabIndex=0,this.#o=createRef(),this.addEventListener("focusin",this.#e),this.addEventListener("focusout",this.#t)}#o;#n(e){e?.focus(),this.focusedItem=e}#i(){return[...this.querySelectorAll("glide-core-tree-item")]}#d(){const e=this.#i(),t=new Set;return e.filter((e=>{const o=e.parentElement?.closest("glide-core-tree-item");return!o||o.expanded&&!t.has(o)||t.add(e),!t.has(e)}))}#s(e){const t=e.target;if(t.closest("glide-core-tree-item-icon-button")??t.closest("glide-core-tree-item-menu"))return;const o=t.closest("glide-core-tree-item");o&&(o.hasChildTreeItems&&!o.nonCollapsible?o.toggleExpand():this.selectItem(o))}#e(e){let t;e.target===this?t=this.selectedItem??this.slotElements[0]:e.target instanceof GlideCoreTreeItem&&(t=e.target,this.privateTabIndex=-1),this.#n(t)}#t(e){const t=e.relatedTarget;t&&this.contains(t)||(this.privateTabIndex=0,this.focusedItem=void 0)}#l(e){if(!["ArrowRight","ArrowLeft","ArrowDown","ArrowUp","Home","End","Enter"].includes(e.key))return;const t=this.#d(),{focusedItem:o}=this,s=t.findIndex((e=>e.matches(":focus")));if("ArrowRight"===e.key&&o?.hasChildTreeItems&&(o.expanded?this.#n(o.slotElements[0]):o.toggleExpand()),"ArrowLeft"===e.key)if(o?.expanded&&!o.nonCollapsible)o.toggleExpand();else{const e=o?.parentElement?.closest("glide-core-tree-item");this.#n(e)}"ArrowDown"===e.key&&-1!==s&&s<t.length-1&&this.#n(t[s+1]),"ArrowUp"===e.key&&s>0&&this.#n(t[s-1]),"Home"===e.key&&this.#n(t[0]),"End"===e.key&&this.#n(t.at(-1)),"Enter"===e.key&&o&&(o.hasChildTreeItems&&!o.nonCollapsible?o.toggleExpand():this.selectItem(o))}#r(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreTreeItem])}};__decorate([state()],GlideCoreTree.prototype,"selectedItem",void 0),__decorate([state()],GlideCoreTree.prototype,"focusedItem",void 0),__decorate([state()],GlideCoreTree.prototype,"privateTabIndex",void 0),__decorate([queryAssignedElements()],GlideCoreTree.prototype,"slotElements",void 0),GlideCoreTree=__decorate([customElement("glide-core-tree")],GlideCoreTree);export default GlideCoreTree;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,s){var r,l=arguments.length,i=l<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,o):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,s);else for(var n=e.length-1;n>=0;n--)(r=e[n])&&(i=(l<3?r(i):l>3?r(t,o,i):r(t,o))||i);return l>3&&i&&Object.defineProperty(t,o,i),i};import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,queryAssignedElements,state}from"lit/decorators.js";import{owSlot,owSlotType}from"./library/ow.js";import GlideCoreTreeItem from"./tree.item.js";import styles from"./tree.styles.js";let GlideCoreTree=class GlideCoreTree extends LitElement{static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("focusin",this.#e),this.removeEventListener("focusout",this.#t)}firstUpdated(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreTreeItem])}render(){return html`<div class="component" role="tree" tabindex="${this.privateTabIndex}" @click="${this.#s}" @keydown="${this.#r}"><slot @slotchange="${this.#l}" ${ref(this.#o)}></slot></div>`}selectItem(e){for(const t of this.slotElements){e===t?(t.setAttribute("selected","true"),this.selectedItem=t):t.removeAttribute("selected");const o=t.selectItem(e);o&&(this.selectedItem=o)}this.dispatchEvent(new CustomEvent("item-selected",{bubbles:!0,detail:e}))}constructor(){super(),this.privateTabIndex=0,this.#o=createRef(),this.addEventListener("focusin",this.#e),this.addEventListener("focusout",this.#t)}#o;#i(e){e?.focus(),this.focusedItem=e}#n(){return[...this.querySelectorAll("glide-core-tree-item")]}#d(){const e=this.#n(),t=new Set;return e.filter((e=>{const o=e.parentElement?.closest("glide-core-tree-item");return!o||o.expanded&&!t.has(o)||t.add(e),!t.has(e)}))}#s(e){const t=e.target;if(t.closest("glide-core-tree-item-icon-button")??t.closest("glide-core-tree-item-menu"))return;const o=t.closest("glide-core-tree-item");o&&(o.hasChildTreeItems&&!o.nonCollapsible?o.toggleExpand():this.selectItem(o))}#e(e){let t;e.target===this?t=this.selectedItem?.checkVisibility({visibilityProperty:!0})?this.selectedItem:this.slotElements[0]:e.target instanceof GlideCoreTreeItem&&(t=e.target,this.privateTabIndex=-1),this.#i(t)}#t(e){e.relatedTarget&&e.relatedTarget instanceof HTMLElement&&this.contains(e.relatedTarget)||(this.privateTabIndex=0,this.focusedItem=void 0)}#r(e){if(!["ArrowRight","ArrowLeft","ArrowDown","ArrowUp","Home","End","Enter"].includes(e.key))return;if(e.target&&e.target instanceof HTMLElement&&(e.target.closest("glide-core-tree-item-icon-button")??e.target.closest("glide-core-tree-item-menu")))return;const t=this.#d(),{focusedItem:o}=this,s=t.findIndex((e=>e.matches(":focus")));if("ArrowRight"===e.key&&o?.hasChildTreeItems&&(o.expanded?this.#i(o.slotElements[0]):o.toggleExpand()),"ArrowLeft"===e.key)if(o?.expanded&&!o.nonCollapsible)o.toggleExpand();else{const e=o?.parentElement?.closest("glide-core-tree-item");this.#i(e)}"ArrowDown"===e.key&&-1!==s&&s<t.length-1&&this.#i(t[s+1]),"ArrowUp"===e.key&&s>0&&this.#i(t[s-1]),"Home"===e.key&&this.#i(t[0]),"End"===e.key&&this.#i(t.at(-1)),"Enter"===e.key&&o&&(o.hasChildTreeItems&&!o.nonCollapsible?o.toggleExpand():this.selectItem(o))}#l(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreTreeItem])}};__decorate([state()],GlideCoreTree.prototype,"selectedItem",void 0),__decorate([state()],GlideCoreTree.prototype,"focusedItem",void 0),__decorate([state()],GlideCoreTree.prototype,"privateTabIndex",void 0),__decorate([queryAssignedElements()],GlideCoreTree.prototype,"slotElements",void 0),GlideCoreTree=__decorate([customElement("glide-core-tree")],GlideCoreTree);export default GlideCoreTree;
@@ -117,7 +117,7 @@ it('throws if it does not have a default slot', async () => {
117
117
  spy();
118
118
  }
119
119
  }
120
- expect(spy.called).to.be.true;
120
+ expect(spy.callCount).to.equal(1);
121
121
  });
122
122
  it('throws if the default slot is the incorrect type', async () => {
123
123
  await expectArgumentError(() => {