@crowdstrike/glide-core 0.9.6 → 0.11.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 (216) 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.events.js +9 -0
  38. package/dist/checkbox.test.focus.js +4 -2
  39. package/dist/checkbox.test.interactions.js +11 -11
  40. package/dist/drawer.d.ts +2 -5
  41. package/dist/drawer.js +1 -1
  42. package/dist/drawer.test.accessibility.js +8 -8
  43. package/dist/drawer.test.basics.js +16 -16
  44. package/dist/drawer.test.closing.js +18 -16
  45. package/dist/drawer.test.events.js +13 -24
  46. package/dist/drawer.test.methods.js +22 -22
  47. package/dist/dropdown.d.ts +7 -5
  48. package/dist/dropdown.js +1 -1
  49. package/dist/dropdown.option.d.ts +2 -3
  50. package/dist/dropdown.option.js +1 -1
  51. package/dist/dropdown.option.styles.js +31 -19
  52. package/dist/dropdown.option.test.basics.js +4 -4
  53. package/dist/dropdown.option.test.events.js +9 -1
  54. package/dist/dropdown.option.test.interactions.single.js +2 -2
  55. package/dist/dropdown.styles.js +39 -3
  56. package/dist/dropdown.test.basics.d.ts +1 -1
  57. package/dist/dropdown.test.basics.js +27 -14
  58. package/dist/dropdown.test.basics.multiple.js +65 -32
  59. package/dist/dropdown.test.basics.single.js +49 -0
  60. package/dist/dropdown.test.events.filterable.js +13 -2
  61. package/dist/dropdown.test.focus.filterable.js +12 -3
  62. package/dist/dropdown.test.focus.js +18 -2
  63. package/dist/dropdown.test.form.multiple.js +3 -2
  64. package/dist/dropdown.test.interactions.filterable.js +141 -45
  65. package/dist/dropdown.test.interactions.js +24 -0
  66. package/dist/dropdown.test.interactions.multiple.js +87 -30
  67. package/dist/dropdown.test.interactions.single.js +40 -4
  68. package/dist/form-controls-layout.d.ts +0 -2
  69. package/dist/icon-button.d.ts +2 -4
  70. package/dist/icon-button.js +1 -1
  71. package/dist/icon-button.test.basics.js +14 -82
  72. package/dist/icon-button.test.focus.d.ts +1 -0
  73. package/dist/icon-button.test.focus.js +13 -0
  74. package/dist/input.d.ts +4 -5
  75. package/dist/input.js +1 -1
  76. package/dist/input.styles.js +4 -4
  77. package/dist/input.test.basics.js +0 -52
  78. package/dist/input.test.events.js +27 -27
  79. package/dist/input.test.focus.js +27 -26
  80. package/dist/input.test.form.js +6 -6
  81. package/dist/input.test.validity.js +130 -130
  82. package/dist/label.d.ts +1 -3
  83. package/dist/label.js +1 -1
  84. package/dist/label.styles.js +5 -6
  85. package/dist/label.test.basics.js +4 -4
  86. package/dist/library/ow.js +1 -1
  87. package/dist/menu.button.d.ts +0 -2
  88. package/dist/menu.button.test.basics.js +3 -3
  89. package/dist/menu.d.ts +1 -4
  90. package/dist/menu.js +1 -1
  91. package/dist/menu.link.d.ts +1 -2
  92. package/dist/menu.link.js +1 -1
  93. package/dist/menu.options.d.ts +0 -2
  94. package/dist/menu.test.events.js +6 -6
  95. package/dist/menu.test.focus.js +5 -18
  96. package/dist/menu.test.interactions.js +48 -24
  97. package/dist/modal.d.ts +6 -17
  98. package/dist/modal.icon-button.d.ts +0 -2
  99. package/dist/modal.icon-button.test.basics.js +3 -3
  100. package/dist/modal.js +1 -1
  101. package/dist/modal.styles.js +13 -19
  102. package/dist/modal.tertiary-icon.d.ts +0 -3
  103. package/dist/modal.tertiary-icon.test.basics.js +3 -3
  104. package/dist/modal.test.basics.js +9 -5
  105. package/dist/modal.test.close.js +2 -2
  106. package/dist/modal.test.events.js +2 -2
  107. package/dist/radio-group.d.ts +0 -3
  108. package/dist/radio-group.js +1 -1
  109. package/dist/radio-group.test.basics.js +61 -61
  110. package/dist/radio-group.test.events.js +13 -13
  111. package/dist/radio-group.test.focus.js +1 -1
  112. package/dist/radio-group.test.form.js +2 -2
  113. package/dist/radio-group.test.validity.js +12 -12
  114. package/dist/radio.d.ts +0 -3
  115. package/dist/radio.styles.js +4 -12
  116. package/dist/split-button.d.ts +8 -11
  117. package/dist/split-button.js +1 -1
  118. package/dist/split-button.primary-button.d.ts +21 -0
  119. package/dist/split-button.primary-button.js +1 -0
  120. package/dist/split-button.primary-button.styles.js +96 -0
  121. package/dist/split-button.primary-button.test.basics.d.ts +1 -0
  122. package/dist/split-button.primary-button.test.basics.js +31 -0
  123. package/dist/split-button.primary-button.test.focus.d.ts +1 -0
  124. package/dist/split-button.primary-button.test.focus.js +14 -0
  125. package/dist/split-button.primary-link.d.ts +19 -0
  126. package/dist/split-button.primary-link.js +1 -0
  127. package/dist/split-button.primary-link.test.basics.d.ts +1 -0
  128. package/dist/split-button.primary-link.test.basics.js +30 -0
  129. package/dist/split-button.primary-link.test.focus.d.ts +1 -0
  130. package/dist/split-button.primary-link.test.focus.js +15 -0
  131. package/dist/split-button.secondary-button.d.ts +25 -0
  132. package/dist/split-button.secondary-button.js +1 -0
  133. package/dist/split-button.secondary-button.styles.js +103 -0
  134. package/dist/split-button.secondary-button.test.basics.d.ts +1 -0
  135. package/dist/split-button.secondary-button.test.basics.js +58 -0
  136. package/dist/split-button.secondary-button.test.focus.d.ts +1 -0
  137. package/dist/split-button.secondary-button.test.focus.js +14 -0
  138. package/dist/split-button.secondary-button.test.interactions.d.ts +2 -0
  139. package/dist/split-button.secondary-button.test.interactions.js +30 -0
  140. package/dist/split-button.stories.d.ts +4 -3
  141. package/dist/split-button.styles.js +1 -94
  142. package/dist/split-button.test.basics.d.ts +2 -1
  143. package/dist/split-button.test.basics.js +67 -80
  144. package/dist/split-button.test.interactions.d.ts +4 -0
  145. package/dist/split-button.test.interactions.js +51 -0
  146. package/dist/styles/opacity-and-scale-animation.js +2 -6
  147. package/dist/styles/variables.css +1 -1
  148. package/dist/tab.d.ts +2 -11
  149. package/dist/tab.group.d.ts +3 -5
  150. package/dist/tab.group.js +1 -1
  151. package/dist/tab.group.styles.js +18 -15
  152. package/dist/tab.group.test.basics.js +49 -34
  153. package/dist/tab.group.test.interactions.js +17 -14
  154. package/dist/tab.panel.d.ts +0 -3
  155. package/dist/tab.test.basics.js +6 -5
  156. package/dist/tag.d.ts +5 -4
  157. package/dist/tag.js +1 -1
  158. package/dist/tag.styles.js +47 -38
  159. package/dist/tag.test.basics.js +18 -110
  160. package/dist/tag.test.events.js +12 -8
  161. package/dist/tag.test.focus.js +2 -3
  162. package/dist/tag.test.interactions.d.ts +1 -0
  163. package/dist/tag.test.interactions.js +36 -0
  164. package/dist/textarea.d.ts +2 -3
  165. package/dist/textarea.js +2 -2
  166. package/dist/textarea.test.basics.js +8 -8
  167. package/dist/textarea.test.events.js +55 -55
  168. package/dist/textarea.test.form.js +9 -9
  169. package/dist/textarea.test.validity.js +167 -135
  170. package/dist/toasts.d.ts +1 -5
  171. package/dist/toasts.test.basics.js +2 -1
  172. package/dist/toasts.toast.d.ts +1 -4
  173. package/dist/toasts.toast.js +1 -1
  174. package/dist/toasts.toast.styles.js +12 -0
  175. package/dist/toggle.d.ts +0 -2
  176. package/dist/toggle.styles.js +1 -5
  177. package/dist/toggle.test.basics.js +2 -2
  178. package/dist/toggle.test.interactions.js +7 -7
  179. package/dist/tooltip.d.ts +2 -1
  180. package/dist/tooltip.js +1 -1
  181. package/dist/tooltip.styles.js +37 -13
  182. package/dist/tooltip.test.basics.d.ts +1 -1
  183. package/dist/tooltip.test.basics.js +19 -19
  184. package/dist/tree.d.ts +0 -2
  185. package/dist/tree.item.d.ts +5 -7
  186. package/dist/tree.item.icon-button.d.ts +1 -4
  187. package/dist/tree.item.js +1 -1
  188. package/dist/tree.item.menu.d.ts +1 -2
  189. package/dist/tree.item.menu.js +1 -1
  190. package/dist/tree.item.menu.test.basics.js +31 -10
  191. package/dist/tree.item.styles.js +7 -9
  192. package/dist/tree.item.test.basics.js +43 -31
  193. package/dist/tree.test.basics.js +29 -29
  194. package/dist/tree.test.focus.js +77 -74
  195. package/package.json +12 -14
  196. package/dist/split-container.d.ts +0 -31
  197. package/dist/split-container.js +0 -1
  198. package/dist/split-container.styles.js +0 -132
  199. package/dist/split-container.test.basics.d.ts +0 -3
  200. package/dist/split-container.test.basics.js +0 -445
  201. package/dist/split-container.test.interactions.d.ts +0 -1
  202. package/dist/split-container.test.interactions.js +0 -20
  203. package/dist/split-link.d.ts +0 -25
  204. package/dist/split-link.js +0 -1
  205. package/dist/split-link.test.basics.d.ts +0 -1
  206. package/dist/split-link.test.basics.js +0 -93
  207. package/dist/split-link.test.interactions.d.ts +0 -1
  208. package/dist/split-link.test.interactions.js +0 -20
  209. package/dist/status-indicator.d.ts +0 -30
  210. package/dist/status-indicator.js +0 -1
  211. package/dist/status-indicator.stories.d.ts +0 -5
  212. package/dist/status-indicator.styles.js +0 -58
  213. package/dist/status-indicator.test.basics.d.ts +0 -1
  214. package/dist/status-indicator.test.basics.js +0 -102
  215. /package/dist/{split-container.styles.d.ts → split-button.primary-button.styles.d.ts} +0 -0
  216. /package/dist/{status-indicator.styles.d.ts → split-button.secondary-button.styles.d.ts} +0 -0
@@ -46,14 +46,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
46
46
  padding: 0;
47
47
  position: absolute;
48
48
 
49
- ::slotted(kbd) {
50
- color: var(--glide-core-text-header-2);
51
- display: inline-block;
52
- font-family: inherit;
53
- font-size: inherit;
54
- white-space: nowrap;
55
- }
56
-
57
49
  &:popover-open {
58
50
  display: flex;
59
51
 
@@ -88,6 +80,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
88
80
  --arrow-height: 0.375rem;
89
81
  --arrow-width: 0.625rem;
90
82
 
83
+ color: var(--glide-core-surface-base-dark);
91
84
  display: flex;
92
85
  position: relative;
93
86
 
@@ -105,22 +98,53 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
105
98
  }
106
99
  }
107
100
 
108
- .default-slot {
101
+ .content {
109
102
  align-items: center;
110
103
  background-color: var(--glide-core-surface-base-dark);
111
104
  border-radius: var(--glide-core-spacing-xs);
112
- color: var(--glide-core-text-selected);
113
- column-gap: var(--glide-core-spacing-xs);
114
105
  display: flex;
115
106
  font-family: var(--glide-core-body-md-font-family);
116
107
  font-size: var(--glide-core-body-sm-font-size);
117
108
  font-style: var(--glide-core-body-sm-font-style);
118
109
  font-weight: var(--glide-core-body-sm-font-weight);
119
- hyphens: auto;
120
110
  inline-size: max-content;
121
111
  inset-block-start: 50%;
112
+ line-height: var(--glide-core-body-sm-line-height);
113
+ padding: var(--glide-core-spacing-xs) var(--glide-core-spacing-sm);
114
+
115
+ &.reversed {
116
+ flex-direction: row-reverse;
117
+ }
118
+ }
119
+
120
+ .default-slot {
121
+ color: var(--glide-core-text-selected-2);
122
+ display: block;
123
+ hyphens: auto;
122
124
  max-inline-size: 11.25rem;
125
+ min-inline-size: 1.875rem;
123
126
  overflow-wrap: anywhere;
124
- padding: var(--glide-core-spacing-xs) var(--glide-core-spacing-sm);
127
+ }
128
+
129
+ .shortcut {
130
+ color: var(--glide-core-text-body-lighter);
131
+ display: none;
132
+ white-space: nowrap;
133
+
134
+ &.visible {
135
+ display: inline-block;
136
+ }
137
+
138
+ &.reversed {
139
+ margin-inline-end: var(--glide-core-spacing-xs);
140
+ }
141
+
142
+ &:not(.reversed) {
143
+ margin-inline-start: var(--glide-core-spacing-xs);
144
+ }
145
+ }
146
+
147
+ kbd {
148
+ font-family: var(--glide-core-body-md-font-family);
125
149
  }
126
150
  `];
@@ -1 +1 @@
1
- import './tooltip.js';
1
+ export {};
@@ -1,5 +1,4 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-expressions */
2
- import './tooltip.js';
3
2
  import { ArgumentError } from 'ow';
4
3
  import { aTimeout, expect, fixture, html } from '@open-wc/testing';
5
4
  import GlideCoreTooltip from './tooltip.js';
@@ -30,11 +29,11 @@ it('has defaults', async () => {
30
29
  expect(component.open).to.be.false;
31
30
  expect(component.placement).to.be.be.undefined;
32
31
  expect(component.disabled).to.be.false;
33
- expect(component.hasAttribute('disabled')).to.be.false;
32
+ expect(component.shortcut).to.be.deep.equal([]);
34
33
  expect(tooltip?.checkVisibility()).to.be.false;
35
34
  });
36
35
  it('can be open', async () => {
37
- const component = await fixture(html `<glide-core-tooltip aria-label="Label" open>
36
+ const component = await fixture(html `<glide-core-tooltip open>
38
37
  Tooltip
39
38
  <span slot="target" tabindex="0">Target</span>
40
39
  </glide-core-tooltip>`);
@@ -43,29 +42,24 @@ it('can be open', async () => {
43
42
  await aTimeout(0);
44
43
  expect(tooltip?.checkVisibility()).to.be.true;
45
44
  });
46
- it('can have a tooltip', async () => {
47
- const component = await fixture(html `<glide-core-tooltip aria-label="Label">
45
+ it('can have a single-key shortcut', async () => {
46
+ const component = await fixture(html `<glide-core-tooltip .shortcut=${['Enter']}>
48
47
  Tooltip
49
48
  <span slot="target" tabindex="0">Target</span>
50
49
  </glide-core-tooltip>`);
51
- const tooltip = component?.shadowRoot
52
- ?.querySelector('slot:not([name])')
53
- ?.assignedNodes()
54
- .at(0);
55
- expect(tooltip?.textContent?.trim()).to.equal('Tooltip');
50
+ const shortcut = component.shadowRoot?.querySelector('[data-test="shortcut"]');
51
+ expect(shortcut?.textContent?.trim()).to.equal('Enter');
56
52
  });
57
- it('can have a target', async () => {
58
- const component = await fixture(html `<glide-core-tooltip>
53
+ it('can have a multi-key shortcut', async () => {
54
+ const component = await fixture(html `<glide-core-tooltip .shortcut=${['CMD', 'K']}>
59
55
  Tooltip
60
56
  <span slot="target" tabindex="0">Target</span>
61
57
  </glide-core-tooltip>`);
62
- const assignedElements = component.shadowRoot
63
- ?.querySelector('slot[name="target"]')
64
- ?.assignedElements();
65
- expect(assignedElements?.at(0)?.textContent).to.equal('Target');
58
+ const shortcut = component.shadowRoot?.querySelector('[data-test="shortcut"]');
59
+ expect(shortcut?.textContent?.replaceAll(/\s/g, '')).to.equal('CMD+K');
66
60
  });
67
- it('does not open when disabled', async () => {
68
- const component = await fixture(html `<glide-core-tooltip aria-label="Label" open disabled>
61
+ it('is not open when disabled', async () => {
62
+ const component = await fixture(html `<glide-core-tooltip open disabled>
69
63
  Tooltip
70
64
  <span slot="target" tabindex="0">Target</span>
71
65
  </glide-core-tooltip>`);
@@ -89,7 +83,7 @@ it('throws if it does not have a default slot', async () => {
89
83
  it('throws if it does not have a "target" slot', async () => {
90
84
  const spy = sinon.spy();
91
85
  try {
92
- await fixture(html `<glide-core-tooltip> Tooltip </glide-core-tooltip>`);
86
+ await fixture(html `<glide-core-tooltip>Tooltip</glide-core-tooltip>`);
93
87
  }
94
88
  catch (error) {
95
89
  if (error instanceof ArgumentError) {
@@ -98,3 +92,9 @@ it('throws if it does not have a "target" slot', async () => {
98
92
  }
99
93
  expect(spy.callCount).to.equal(1);
100
94
  });
95
+ it('has `placement` coverage', async () => {
96
+ await fixture(html `<glide-core-tooltip open placement="top">
97
+ Tooltip
98
+ <span slot="target" tabindex="0">Target</span>
99
+ </glide-core-tooltip>`);
100
+ });
package/dist/tree.d.ts CHANGED
@@ -6,8 +6,6 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @description A tree containing a hierarchy of Tree Items.
10
- *
11
9
  * @slot - One or more of <glide-core-tree-item>
12
10
  */
13
11
  export default class GlideCoreTree extends LitElement {
@@ -6,12 +6,10 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @description A single node of a Tree.
10
- *
11
- * @slot - One or more of <glide-core-tree-item>, if this tree item contains nested tree items.
12
- * @slot prefix - An optional icon to display before the label.
13
- * @slot suffix - An optional icon to add after the label.
14
- * @slot menu - Place a <glide-core-menu> here, which will be visible on hover or focus
9
+ * @slot - Zero or more of `<glide-core-tree-item>`.
10
+ * @slot prefix - An optional icon before the label.
11
+ * @slot suffix - An optional icon after the label.
12
+ * @slot menu - A `<glide-core-menu>` made visible on hover or focus.
15
13
  */
16
14
  export default class GlideCoreTreeItem extends LitElement {
17
15
  #private;
@@ -25,7 +23,6 @@ export default class GlideCoreTreeItem extends LitElement {
25
23
  nonCollapsible: boolean;
26
24
  slotElements: GlideCoreTreeItem[];
27
25
  suffixSlotAssignedElements: HTMLElement[];
28
- firstUpdated(): void;
29
26
  focus(options?: FocusOptions): void;
30
27
  get hasChildTreeItems(): boolean;
31
28
  get hasExpandIcon(): boolean;
@@ -38,4 +35,5 @@ export default class GlideCoreTreeItem extends LitElement {
38
35
  selectItem(item: GlideCoreTreeItem): GlideCoreTreeItem | undefined;
39
36
  toggleExpand(): void;
40
37
  private childTreeItems;
38
+ private hasPrefixIcon;
41
39
  }
@@ -6,10 +6,7 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @description An icon button that can be used inside of a tree item.
10
- * Provides correct color styling based on tree item state
11
- *
12
- * @slot - Reserved for the icon to display inside of the button.
9
+ * @slot - An icon.
13
10
  */
14
11
  export default class GlideCoreTreeItemIconButton extends LitElement {
15
12
  #private;
package/dist/tree.item.js CHANGED
@@ -1 +1 @@
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;
1
+ var _a,GlideCoreTreeItem_1,__decorate=this&&this.__decorate||function(e,t,o,i){var l,r=arguments.length,s=r<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,i);else for(var n=e.length-1;n>=0;n--)(l=e[n])&&(s=(r<3?l(s):r>3?l(t,o,s):l(t,o))||s);return r>3&&s&&Object.defineProperty(t,o,s),s};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.hasPrefixIcon=!1,this.#e=createRef(),this.#t=createRef(),this.#o=new LocalizeController(this),this.#i=createRef(),this.#l=createRef()}static{GlideCoreTreeItem_1=this}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}focus(e){this.#t.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.#n)}"><div class="${classMap({"label-container":!0,"prefix-icon":this.hasPrefixIcon})}" tabindex="-1" @focusout="${this.#a}" @focusin="${this.#d}" ${ref(this.#t)}><div style="flex-shrink: 0; width:${this.#c};"></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" ${ref(this.#l)} @slotchange="${this.#h}"></slot><div class="label">${this.label}</div><div class="icon-container"><slot name="menu" ${ref(this.#i)} @slotchange="${this.#m}"></slot><slot name="suffix"></slot></div></div><div class="child-items" role="group"><slot @slotchange="${this.#f}" ${ref(this.#e)}></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;#i;#l;get#n(){return this.hasChildTreeItems?this.expanded?"true":"false":void 0}get#s(){return this.hasChildTreeItems?void 0:this.selected?"true":"false"}#d(e){this.#p(e.target)&&e.stopPropagation()}#a(e){this.#p(e.relatedTarget)?e.stopPropagation():this.#r(-1)}get#c(){return 20*(this.level-1)+"px"}#p(e){return e&&e instanceof HTMLElement&&!(e instanceof GlideCoreTreeItem_1)&&this.contains(e)}#f(){this.#u()}#m(){owSlotType(this.#i.value,[GlideCoreTreeItemMenu]);for(const e of this.#i.value.assignedElements())e instanceof GlideCoreTreeItemMenu&&(e.label=this.#o.term("actionsFor",this.label))}#h(){const e=this.#l.value?.assignedNodes();this.hasPrefixIcon=Boolean(e&&e.length>0)}#r(e){ow(this.#t.value,ow.object.instanceOf(HTMLElement)),this.#t.value.tabIndex=e;for(const t of this.querySelectorAll("& > glide-core-tree-item-icon-button"))t.tabIndex=e}#u(){const e=[];for(const t of this.slotElements)t.level=this.level+1,e.push(t);this.childTreeItems=e}};__decorate([property({reflect:!0,type:Boolean})],GlideCoreTreeItem.prototype,"expanded",void 0),__decorate([property({reflect:!0})],GlideCoreTreeItem.prototype,"label",void 0),__decorate([property({reflect:!0,type:Number})],GlideCoreTreeItem.prototype,"level",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTreeItem.prototype,"selected",void 0),__decorate([property({reflect:!0,type:Boolean,attribute:"remove-indentation"})],GlideCoreTreeItem.prototype,"removeIndentation",void 0),__decorate([property({reflect:!0,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),__decorate([state()],GlideCoreTreeItem.prototype,"hasPrefixIcon",void 0),GlideCoreTreeItem=GlideCoreTreeItem_1=__decorate([customElement("glide-core-tree-item")],GlideCoreTreeItem);export default GlideCoreTreeItem;
@@ -9,8 +9,6 @@ declare global {
9
9
  }
10
10
  }
11
11
  /**
12
- * @description A menu built into a tree item. Uses <glide-core-menu>
13
- *
14
12
  * @slot - One or more of <glide-core-menu-link> or <glide-core-menu-button>.
15
13
  * @slot target - A focusable element against which Menu will be positioned. Opens and closes Menu when interacted with.
16
14
  */
@@ -23,4 +21,5 @@ export default class GlideCoreTreeItemMenu extends LitElement {
23
21
  click(): void;
24
22
  firstUpdated(): void;
25
23
  render(): import("lit").TemplateResult<1>;
24
+ private hasCustomIcon;
26
25
  }
@@ -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"./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;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,n){var l,i=arguments.length,r=i<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,o):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,o,n);else for(var s=e.length-1;s>=0;s--)(l=e[s])&&(r=(i<3?l(r):i>3?l(t,o,r):l(t,o))||r);return i>3&&r&&Object.defineProperty(t,o,r),r};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,state}from"lit/decorators.js";import{when}from"lit/directives/when.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.hasCustomIcon=!1,this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#n=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.#n)}><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)}><slot name="icon" @slotchange="${this.#i}" ${ref(this.#o)}></slot>${when(!this.hasCustomIcon,(()=>html`<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;#n;#l(){owSlot(this.#e.value),owSlotType(this.#e.value,[GlideCoreMenuButton,GlideCoreMenuLink])}#i(){const e=this.#o.value?.assignedNodes();this.hasCustomIcon=Boolean(e&&e.length>0)}};__decorate([property({reflect:!0})],GlideCoreTreeItemMenu.prototype,"placement",void 0),__decorate([property()],GlideCoreTreeItemMenu.prototype,"label",void 0),__decorate([state()],GlideCoreTreeItemMenu.prototype,"hasCustomIcon",void 0),GlideCoreTreeItemMenu=__decorate([customElement("glide-core-tree-item-menu")],GlideCoreTreeItemMenu);export default GlideCoreTreeItemMenu;
@@ -1,8 +1,10 @@
1
- import { expect, fixture, html, waitUntil } from '@open-wc/testing';
1
+ import { assert, expect, fixture, html, waitUntil } from '@open-wc/testing';
2
+ import GlideCoreMenu from './menu.js';
2
3
  import GlideCoreTreeItemMenu from './tree.item.menu.js';
3
4
  import expectArgumentError from './library/expect-argument-error.js';
4
5
  import sinon from 'sinon';
5
6
  GlideCoreTreeItemMenu.shadowRootOptions.mode = 'open';
7
+ GlideCoreMenu.shadowRootOptions.mode = 'open';
6
8
  it('registers', async () => {
7
9
  expect(window.customElements.get('glide-core-tree-item-menu')).to.equal(GlideCoreTreeItemMenu);
8
10
  });
@@ -33,33 +35,52 @@ it('throws if the default slot is the incorrect type', async () => {
33
35
  stub.restore();
34
36
  });
35
37
  it('defaults the placement of the menu to bottom start', async () => {
36
- const treeItemMenu = await fixture(html `
38
+ const component = await fixture(html `
37
39
  <glide-core-tree-item-menu>
38
40
  <glide-core-menu-link label="One" url="/one"> </glide-core-menu-link>
39
41
  </glide-core-tree-item-menu>
40
42
  `);
41
- expect(treeItemMenu.shadowRoot?.querySelector('glide-core-menu')?.placement).to.equal('bottom-start');
43
+ expect(component.shadowRoot?.querySelector('glide-core-menu')?.placement).to.equal('bottom-start');
42
44
  });
43
45
  it('can set placement of the menu', async () => {
44
- const treeItemMenu = await fixture(html `
46
+ const component = await fixture(html `
45
47
  <glide-core-tree-item-menu placement="bottom-end">
46
48
  <glide-core-menu-link label="One" url="/one"> </glide-core-menu-link>
47
49
  </glide-core-tree-item-menu>
48
50
  `);
49
- expect(treeItemMenu.shadowRoot?.querySelector('glide-core-menu')?.placement).to.equal('bottom-end');
51
+ expect(component.shadowRoot?.querySelector('glide-core-menu')?.placement).to.equal('bottom-end');
50
52
  });
51
53
  it('can be opened programmatically', async () => {
52
- const treeItemMenu = await fixture(html `
54
+ const component = await fixture(html `
53
55
  <glide-core-tree-item-menu>
54
56
  <glide-core-menu-link label="One" url="/one"> </glide-core-menu-link>
55
57
  </glide-core-tree-item-menu>
56
58
  `);
57
- expect(treeItemMenu.shadowRoot
59
+ expect(component.shadowRoot
58
60
  ?.querySelector('glide-core-menu')
59
61
  ?.getAttribute('open')).to.equal(null);
60
- treeItemMenu.click();
61
- await treeItemMenu.updateComplete;
62
- expect(treeItemMenu.shadowRoot
62
+ component.click();
63
+ await component.updateComplete;
64
+ expect(component.shadowRoot
63
65
  ?.querySelector('glide-core-menu')
64
66
  ?.getAttribute('open')).to.equal('');
65
67
  });
68
+ it('can set a custom icon', async () => {
69
+ const component = await fixture(html `
70
+ <glide-core-tree-item-menu placement="bottom-end">
71
+ <svg data-test-custom-icon="true" slot="icon"></svg>
72
+ <glide-core-menu-link label="One" url="/one"> </glide-core-menu-link>
73
+ </glide-core-tree-item-menu>
74
+ `);
75
+ const menu = component.shadowRoot?.querySelector('glide-core-menu');
76
+ assert(menu);
77
+ const menuTarget = menu.shadowRoot
78
+ ?.querySelector('slot[name="target"]')
79
+ ?.assignedElements()[0];
80
+ assert(menuTarget);
81
+ const icon = menuTarget
82
+ ?.querySelector('slot[name="icon"]')
83
+ ?.assignedElements()[0];
84
+ assert(icon instanceof SVGElement);
85
+ expect(icon.dataset.testCustomIcon).to.equal('true');
86
+ });
@@ -13,6 +13,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
13
13
  font-style: var(--glide-core-body-sm-font-style);
14
14
  font-weight: var(--glide-core-body-sm-font-weight);
15
15
  grid-template-columns: repeat(auto-fill, 2.5rem);
16
+ line-height: 1.25rem;
16
17
 
17
18
  --color: var(--glide-core-text-body-1);
18
19
 
@@ -90,10 +91,10 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
90
91
  background-color: var(--glide-core-color-dark-blue);
91
92
  }
92
93
  }
93
- }
94
94
 
95
- ::slotted([slot='prefix']) {
96
- margin-inline-end: var(--glide-core-spacing-xs);
95
+ &.prefix-icon .label {
96
+ padding-inline-start: var(--glide-core-spacing-xs);
97
+ }
97
98
  }
98
99
 
99
100
  ::slotted([slot='menu']) {
@@ -112,10 +113,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
112
113
  --hovered-icon-button-color: var(--glide-core-icon-hover);
113
114
  }
114
115
 
115
- ::slotted([slot='suffix']) {
116
- padding-inline: var(--glide-core-spacing-xxs);
117
- }
118
-
119
116
  .label-container:hover,
120
117
  .label-container:focus,
121
118
  .label-container:focus-within,
@@ -126,6 +123,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
126
123
  }
127
124
 
128
125
  .label {
126
+ margin-inline-end: auto;
129
127
  min-inline-size: 0;
130
128
  overflow: hidden;
131
129
  text-overflow: ellipsis;
@@ -149,7 +147,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
149
147
 
150
148
  .icon-container {
151
149
  display: flex;
152
- flex: 1;
153
- justify-content: flex-end;
150
+ gap: var(--glide-core-spacing-xxs);
151
+ padding-inline: var(--glide-core-spacing-xxs);
154
152
  }
155
153
  `];
@@ -12,22 +12,23 @@ it('registers', () => {
12
12
  expect(window.customElements.get('glide-core-tree-item')).to.equal(TreeItem);
13
13
  });
14
14
  it('renders and sets default attributes', async () => {
15
- const treeItem = await fixture(html `
15
+ const component = await fixture(html `
16
16
  <glide-core-tree-item label="Item"></glide-core-tree-item>
17
17
  `);
18
- expect(treeItem.expanded).to.equal(false);
19
- expect(treeItem.label).to.equal('Item');
20
- expect(treeItem.level).to.equal(1);
21
- expect(treeItem.shadowRoot?.querySelector('.expand-icon-container')).to.be.ok;
18
+ expect(component.expanded).to.be.false;
19
+ expect(component.label).to.equal('Item');
20
+ expect(component.level).to.equal(1);
21
+ expect(component.shadowRoot?.querySelector('.expand-icon-container')).to.be
22
+ .ok;
22
23
  });
23
24
  it('does not render expand-icon-container if remove-indentation is set', async () => {
24
- const treeItem = await fixture(html `
25
+ const component = await fixture(html `
25
26
  <glide-core-tree-item
26
27
  label="Item"
27
28
  remove-indentation
28
29
  ></glide-core-tree-item>
29
30
  `);
30
- expect(treeItem.shadowRoot?.querySelector('.expand-icon-container')).to.be
31
+ expect(component.shadowRoot?.querySelector('.expand-icon-container')).to.be
31
32
  .null;
32
33
  });
33
34
  it('renders with a prefix slot', async () => {
@@ -39,14 +40,14 @@ it('renders with a prefix slot', async () => {
39
40
  expect(document.querySelector('[data-prefix]')).to.be.ok;
40
41
  });
41
42
  it('adds label to menu target', async () => {
42
- const treeItem = await fixture(html `
43
+ const component = await fixture(html `
43
44
  <glide-core-tree-item label="Item">
44
45
  <glide-core-tree-item-menu slot="menu" data-menu>
45
46
  <glide-core-menu-link label="Move" url="/move"> </glide-core-menu-link>
46
47
  </glide-core-tree-item-menu>
47
48
  </glide-core-tree-item>
48
49
  `);
49
- const menuTarget = treeItem
50
+ const menuTarget = component
50
51
  .querySelector('glide-core-tree-item-menu')
51
52
  ?.shadowRoot?.querySelector('glide-core-menu')
52
53
  ?.querySelector('glide-core-icon-button');
@@ -61,34 +62,34 @@ it('renders with a suffix slot', async () => {
61
62
  expect(document.querySelector('[data-suffix]')).to.be.ok;
62
63
  });
63
64
  it('does not have an expand icon if there are no child tree items', async () => {
64
- const treeItem = await fixture(html `
65
+ const component = await fixture(html `
65
66
  <glide-core-tree-item label="Item"></glide-core-tree-item>
66
67
  `);
67
- expect(treeItem.shadowRoot?.querySelector('.expand-icon')).to.equal(null);
68
+ expect(component.shadowRoot?.querySelector('.expand-icon')).to.equal(null);
68
69
  });
69
70
  it('can expand', async () => {
70
- const treeItem = await fixture(html `
71
+ const component = await fixture(html `
71
72
  <glide-core-tree-item label="Item">
72
73
  <glide-core-tree-item label="Child Item 1"></glide-core-tree-item>
73
74
  </glide-core-tree-item>
74
75
  `);
75
76
  expect([
76
- ...treeItem.shadowRoot.querySelector('.component').classList,
77
+ ...component.shadowRoot.querySelector('.component').classList,
77
78
  ]).to.deep.equal(['component']);
78
79
  expect([
79
- ...treeItem.shadowRoot.querySelector('.expand-icon').classList,
80
+ ...component.shadowRoot.querySelector('.expand-icon').classList,
80
81
  ]).to.deep.equal(['expand-icon']);
81
- treeItem.toggleExpand();
82
- await treeItem.updateComplete;
82
+ component.toggleExpand();
83
+ await component.updateComplete;
83
84
  expect([
84
- ...treeItem.shadowRoot.querySelector('.component').classList,
85
+ ...component.shadowRoot.querySelector('.component').classList,
85
86
  ]).to.deep.equal(['component', 'expanded']);
86
87
  expect([
87
- ...treeItem.shadowRoot.querySelector('.expand-icon').classList,
88
+ ...component.shadowRoot.querySelector('.expand-icon').classList,
88
89
  ]).to.deep.equal(['expand-icon', 'expand-icon-expanded']);
89
90
  });
90
91
  it('renders child and grandchild tree items', async () => {
91
- const treeItem = await fixture(html `
92
+ const component = await fixture(html `
92
93
  <glide-core-tree-item expanded label="Item">
93
94
  <glide-core-tree-item label="Child Item 1"></glide-core-tree-item>
94
95
  <glide-core-tree-item label="Child Item 2">
@@ -96,16 +97,27 @@ it('renders child and grandchild tree items', async () => {
96
97
  </glide-core-tree-item>
97
98
  </glide-core-tree-item>
98
99
  `);
99
- expect(treeItem.shadowRoot?.querySelector('.expand-icon')).to.be.ok;
100
- const childItems = treeItem.slotElements;
100
+ expect(component.shadowRoot?.querySelector('.expand-icon')).to.be.ok;
101
+ const childItems = component.slotElements;
101
102
  expect(childItems?.length).to.equal(2);
102
103
  expect(childItems?.[0].level).to.equal(2, 'Children are level 2');
103
104
  const grandchildItems = childItems?.[1].slotElements;
104
105
  expect(grandchildItems?.length).to.equal(1);
105
106
  expect(grandchildItems?.[0].level).to.equal(3, 'Grandchildren are level 3');
106
107
  });
108
+ it('sets the level for tree items programmatically added later', async () => {
109
+ const component = await fixture(html `
110
+ <glide-core-tree-item expanded label="Item"></glide-core-tree-item>
111
+ `);
112
+ const newItem = Object.assign(document.createElement('glide-core-tree-item'), {
113
+ label: 'Child',
114
+ });
115
+ component.append(newItem);
116
+ await component.updateComplete;
117
+ expect(newItem.level).to.equal(2);
118
+ });
107
119
  it('can select child and grandchild items', async () => {
108
- const treeItem = await fixture(html `
120
+ const component = await fixture(html `
109
121
  <glide-core-tree-item expanded label="Item">
110
122
  <glide-core-tree-item label="Child Item 1"></glide-core-tree-item>
111
123
  <glide-core-tree-item label="Child Item 2">
@@ -113,14 +125,14 @@ it('can select child and grandchild items', async () => {
113
125
  </glide-core-tree-item>
114
126
  </glide-core-tree-item>
115
127
  `);
116
- const childItems = treeItem.slotElements;
128
+ const childItems = component.slotElements;
117
129
  const grandchildItems = childItems?.[1].slotElements;
118
- treeItem.selectItem(childItems[0]);
119
- expect(childItems[0].selected).to.equal(true);
120
- expect(childItems[1].selected).to.equal(false);
121
- expect(grandchildItems[0].selected).to.equal(false);
122
- treeItem.selectItem(grandchildItems[0]);
123
- expect(childItems[0].selected).to.equal(false);
124
- expect(childItems[1].selected).to.equal(false);
125
- expect(grandchildItems[0].selected).to.equal(true);
130
+ component.selectItem(childItems[0]);
131
+ expect(childItems[0].selected).to.be.true;
132
+ expect(childItems[1].selected).to.be.false;
133
+ expect(grandchildItems[0].selected).to.be.false;
134
+ component.selectItem(grandchildItems[0]);
135
+ expect(childItems[0].selected).to.be.false;
136
+ expect(childItems[1].selected).to.be.false;
137
+ expect(grandchildItems[0].selected).to.be.true;
126
138
  });