@crowdstrike/glide-core 0.5.1 → 0.6.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 (242) hide show
  1. package/README.md +11 -1
  2. package/dist/accordion.js +1 -1
  3. package/dist/accordion.styles.js +5 -4
  4. package/dist/accordion.test.basics.js +109 -0
  5. package/dist/accordion.test.events.js +39 -0
  6. package/dist/button-group.button.js +1 -1
  7. package/dist/button-group.button.styles.js +6 -5
  8. package/dist/button-group.button.test.basics.js +169 -0
  9. package/dist/button-group.button.test.events.js +73 -0
  10. package/dist/button-group.js +1 -1
  11. package/dist/button-group.styles.js +3 -3
  12. package/dist/button-group.test.basics.js +268 -0
  13. package/dist/button-group.test.events.js +291 -0
  14. package/dist/button.d.ts +3 -2
  15. package/dist/button.js +1 -1
  16. package/dist/button.styles.js +5 -5
  17. package/dist/button.test.basics.js +202 -0
  18. package/dist/button.test.events.js +25 -0
  19. package/dist/button.test.form.js +49 -0
  20. package/dist/checkbox-group.js +1 -1
  21. package/dist/checkbox-group.styles.js +2 -2
  22. package/dist/checkbox-group.test.basics.js +119 -0
  23. package/dist/checkbox-group.test.events.js +110 -0
  24. package/dist/checkbox-group.test.focus.js +45 -0
  25. package/dist/checkbox-group.test.form.js +130 -0
  26. package/dist/checkbox-group.test.validity.js +75 -0
  27. package/dist/checkbox.js +1 -1
  28. package/dist/checkbox.styles.js +7 -4
  29. package/dist/checkbox.test.basics.js +89 -0
  30. package/dist/checkbox.test.events.js +87 -0
  31. package/dist/checkbox.test.focus.js +38 -0
  32. package/dist/checkbox.test.form.js +115 -0
  33. package/dist/checkbox.test.states.js +62 -0
  34. package/dist/checkbox.test.validity.js +51 -0
  35. package/dist/drawer.d.ts +2 -2
  36. package/dist/drawer.js +1 -15
  37. package/dist/drawer.styles.js +14 -4
  38. package/dist/drawer.test.accessibility.js +22 -0
  39. package/dist/drawer.test.basics.js +43 -0
  40. package/dist/drawer.test.closing.js +37 -0
  41. package/dist/drawer.test.events.js +52 -0
  42. package/dist/drawer.test.floating-components.d.ts +1 -0
  43. package/dist/drawer.test.floating-components.js +51 -0
  44. package/dist/drawer.test.methods.js +34 -0
  45. package/dist/dropdown.d.ts +4 -2
  46. package/dist/dropdown.js +1 -1
  47. package/dist/dropdown.option.d.ts +0 -2
  48. package/dist/dropdown.option.js +1 -1
  49. package/dist/dropdown.option.styles.js +2 -2
  50. package/dist/dropdown.option.test.basics.js +59 -0
  51. package/dist/dropdown.option.test.basics.multiple.js +26 -0
  52. package/dist/dropdown.option.test.basics.single.js +20 -0
  53. package/dist/dropdown.option.test.events.js +27 -0
  54. package/dist/dropdown.option.test.focus.js +11 -0
  55. package/dist/dropdown.option.test.interactions.multiple.js +82 -0
  56. package/dist/dropdown.option.test.interactions.single.js +22 -0
  57. package/dist/dropdown.styles.js +26 -6
  58. package/dist/dropdown.test.basics.filterable.js +84 -0
  59. package/dist/dropdown.test.basics.js +233 -0
  60. package/dist/dropdown.test.basics.multiple.js +270 -0
  61. package/dist/dropdown.test.basics.single.js +79 -0
  62. package/dist/dropdown.test.events.js +268 -0
  63. package/dist/dropdown.test.events.multiple.js +130 -0
  64. package/dist/dropdown.test.focus.d.ts +1 -0
  65. package/dist/dropdown.test.focus.filterable.js +154 -0
  66. package/dist/dropdown.test.focus.js +28 -0
  67. package/dist/dropdown.test.focus.multiple.js +181 -0
  68. package/dist/dropdown.test.focus.single.js +53 -0
  69. package/dist/dropdown.test.form.js +140 -0
  70. package/dist/dropdown.test.form.multiple.js +149 -0
  71. package/dist/dropdown.test.form.single.js +128 -0
  72. package/dist/dropdown.test.interactions.filterable.js +449 -0
  73. package/dist/dropdown.test.interactions.js +446 -0
  74. package/dist/dropdown.test.interactions.multiple.js +908 -0
  75. package/dist/dropdown.test.interactions.single.js +466 -0
  76. package/dist/dropdown.test.validity.js +46 -0
  77. package/dist/icon-button.d.ts +3 -2
  78. package/dist/icon-button.js +1 -1
  79. package/dist/icon-button.styles.js +12 -12
  80. package/dist/icon-button.test.basics.js +110 -0
  81. package/dist/icons/checked.js +1 -1
  82. package/dist/icons/magnifying-glass.js +1 -1
  83. package/dist/input.js +1 -1
  84. package/dist/input.styles.js +4 -3
  85. package/dist/input.test.basics.js +169 -0
  86. package/dist/input.test.events.js +97 -0
  87. package/dist/input.test.focus.js +54 -0
  88. package/dist/input.test.form.js +56 -0
  89. package/dist/input.test.validity.js +50 -0
  90. package/dist/label.js +1 -1
  91. package/dist/label.styles.js +13 -15
  92. package/dist/label.test.basics.js +129 -0
  93. package/dist/library/expect-argument-error.js +1 -1
  94. package/dist/library/localize.d.ts +17 -0
  95. package/dist/library/localize.js +1 -0
  96. package/dist/library/ow.js +1 -1
  97. package/dist/library/ow.test.js +55 -0
  98. package/dist/library/set-containing-block.d.ts +15 -0
  99. package/dist/library/set-containing-block.js +1 -0
  100. package/dist/menu.button.d.ts +1 -2
  101. package/dist/menu.button.js +1 -1
  102. package/dist/menu.button.styles.js +3 -3
  103. package/dist/menu.button.test.basics.js +42 -0
  104. package/dist/menu.d.ts +7 -2
  105. package/dist/menu.js +1 -1
  106. package/dist/menu.link.d.ts +1 -2
  107. package/dist/menu.link.js +1 -1
  108. package/dist/menu.link.styles.js +3 -3
  109. package/dist/menu.link.test.basics.js +46 -0
  110. package/dist/menu.options.d.ts +22 -0
  111. package/dist/menu.options.js +1 -0
  112. package/dist/menu.options.styles.d.ts +2 -0
  113. package/dist/menu.options.styles.js +33 -0
  114. package/dist/menu.options.test.basics.d.ts +2 -0
  115. package/dist/menu.options.test.basics.js +43 -0
  116. package/dist/menu.stories.d.ts +1 -0
  117. package/dist/menu.styles.js +7 -31
  118. package/dist/menu.test.basics.d.ts +1 -0
  119. package/dist/menu.test.basics.js +183 -0
  120. package/dist/menu.test.focus.d.ts +0 -1
  121. package/dist/menu.test.focus.js +84 -0
  122. package/dist/menu.test.interactions.d.ts +1 -1
  123. package/dist/menu.test.interactions.js +664 -0
  124. package/dist/modal.icon-button.js +1 -1
  125. package/dist/modal.icon-button.styles.js +2 -2
  126. package/dist/modal.icon-button.test.basics.js +45 -0
  127. package/dist/modal.js +1 -15
  128. package/dist/modal.styles.js +4 -7
  129. package/dist/modal.tertiary-icon.d.ts +1 -0
  130. package/dist/modal.tertiary-icon.js +1 -1
  131. package/dist/modal.tertiary-icon.test.basics.js +59 -0
  132. package/dist/modal.test.accessibility.js +48 -0
  133. package/dist/modal.test.basics.js +203 -0
  134. package/dist/modal.test.close.js +38 -0
  135. package/dist/modal.test.events.js +110 -0
  136. package/dist/modal.test.floating-components.d.ts +1 -0
  137. package/dist/modal.test.floating-components.js +62 -0
  138. package/dist/modal.test.lock-scroll.js +76 -0
  139. package/dist/modal.test.methods.js +23 -0
  140. package/dist/modal.test.scrollbars.js +19 -0
  141. package/dist/radio-group.js +1 -1
  142. package/dist/radio-group.styles.js +20 -24
  143. package/dist/radio-group.test.basics.js +323 -0
  144. package/dist/radio-group.test.events.js +277 -0
  145. package/dist/radio-group.test.focus.js +75 -0
  146. package/dist/radio-group.test.form.js +104 -0
  147. package/dist/radio-group.test.validity.js +228 -0
  148. package/dist/radio.js +1 -1
  149. package/dist/radio.styles.js +14 -31
  150. package/dist/split-button.d.ts +27 -0
  151. package/dist/split-button.js +1 -0
  152. package/dist/split-button.stories.d.ts +17 -0
  153. package/dist/split-button.styles.d.ts +2 -0
  154. package/dist/split-button.styles.js +102 -0
  155. package/dist/split-button.test.basics.d.ts +1 -0
  156. package/dist/split-button.test.basics.js +99 -0
  157. package/dist/split-container.d.ts +31 -0
  158. package/dist/split-container.js +1 -0
  159. package/dist/split-container.styles.d.ts +2 -0
  160. package/dist/split-container.styles.js +134 -0
  161. package/dist/split-container.test.basics.d.ts +3 -0
  162. package/dist/split-container.test.basics.js +440 -0
  163. package/dist/split-container.test.interactions.d.ts +1 -0
  164. package/dist/split-container.test.interactions.js +20 -0
  165. package/dist/split-link.d.ts +25 -0
  166. package/dist/split-link.js +1 -0
  167. package/dist/split-link.test.basics.d.ts +1 -0
  168. package/dist/split-link.test.basics.js +92 -0
  169. package/dist/split-link.test.interactions.d.ts +1 -0
  170. package/dist/split-link.test.interactions.js +19 -0
  171. package/dist/status-indicator.js +1 -1
  172. package/dist/status-indicator.styles.js +2 -2
  173. package/dist/status-indicator.test.basics.js +102 -0
  174. package/dist/styles/focus-outline.js +1 -4
  175. package/dist/styles/variables.css +1 -1
  176. package/dist/styles/visually-hidden.js +1 -11
  177. package/dist/tab.group.js +1 -1
  178. package/dist/tab.group.styles.js +2 -2
  179. package/dist/tab.group.test.basics.js +185 -0
  180. package/dist/tab.js +1 -1
  181. package/dist/tab.panel.js +1 -1
  182. package/dist/tab.panel.styles.js +3 -3
  183. package/dist/tab.styles.js +80 -55
  184. package/dist/tab.test.basics.js +71 -0
  185. package/dist/tag.js +1 -1
  186. package/dist/tag.styles.js +4 -3
  187. package/dist/tag.test.basics.js +118 -0
  188. package/dist/tag.test.events.js +16 -0
  189. package/dist/tag.test.focus.js +11 -0
  190. package/dist/tag.test.translations.d.ts +1 -0
  191. package/dist/tag.test.translations.js +25 -0
  192. package/dist/textarea.js +2 -2
  193. package/dist/textarea.styles.js +5 -4
  194. package/dist/textarea.test.basics.js +140 -0
  195. package/dist/textarea.test.events.js +204 -0
  196. package/dist/textarea.test.form.js +70 -0
  197. package/dist/textarea.test.validity.js +83 -0
  198. package/dist/toasts.js +1 -1
  199. package/dist/toasts.styles.js +2 -2
  200. package/dist/toasts.test.basics.js +94 -0
  201. package/dist/toasts.toast.js +1 -1
  202. package/dist/toasts.toast.styles.js +5 -2
  203. package/dist/toasts.toast.test.basics.js +139 -0
  204. package/dist/toggle.js +1 -1
  205. package/dist/toggle.styles.js +3 -3
  206. package/dist/toggle.test.basics.js +68 -0
  207. package/dist/toggle.test.events.js +29 -0
  208. package/dist/toggle.test.focus.js +9 -0
  209. package/dist/toggle.test.states.js +43 -0
  210. package/dist/tooltip.d.ts +2 -0
  211. package/dist/tooltip.js +1 -1
  212. package/dist/tooltip.styles.js +5 -3
  213. package/dist/tooltip.test.basics.js +64 -0
  214. package/dist/tooltip.test.interactions.js +78 -0
  215. package/dist/translations/en.d.ts +3 -0
  216. package/dist/translations/en.js +1 -0
  217. package/dist/translations/fr.d.ts +3 -0
  218. package/dist/translations/fr.js +1 -0
  219. package/dist/translations/ja.d.ts +3 -0
  220. package/dist/translations/ja.js +1 -0
  221. package/dist/tree.d.ts +1 -0
  222. package/dist/tree.item.d.ts +3 -1
  223. package/dist/tree.item.icon-button.js +1 -1
  224. package/dist/tree.item.icon-button.styles.js +2 -2
  225. package/dist/tree.item.icon-button.test.basics.js +13 -0
  226. package/dist/tree.item.js +1 -1
  227. package/dist/tree.item.menu.d.ts +2 -0
  228. package/dist/tree.item.menu.js +1 -1
  229. package/dist/tree.item.menu.styles.js +2 -2
  230. package/dist/tree.item.menu.test.basics.js +33 -0
  231. package/dist/tree.item.styles.js +23 -8
  232. package/dist/tree.item.test.basics.js +102 -0
  233. package/dist/tree.js +1 -1
  234. package/dist/tree.stories.d.ts +1 -0
  235. package/dist/tree.styles.js +2 -2
  236. package/dist/tree.test.aria.js +86 -0
  237. package/dist/tree.test.basics.js +123 -0
  238. package/dist/tree.test.events.js +19 -0
  239. package/dist/tree.test.focus.js +261 -0
  240. package/package.json +25 -18
  241. /package/dist/{dropdown.option.test.focus.multiple.d.ts → dropdown.option.test.focus.d.ts} +0 -0
  242. /package/dist/{dropdown.option.test.focus.single.d.ts → dropdown.test.events.multiple.d.ts} +0 -0
@@ -0,0 +1,134 @@
1
+ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
2
+ .component {
3
+ display: inline-flex;
4
+ gap: 0;
5
+
6
+ & .divider {
7
+ inline-size: 1px;
8
+
9
+ &.primary {
10
+ background-color: var(--glide-core-border-base-light);
11
+ }
12
+
13
+ &.secondary {
14
+ background-color: var(--glide-core-border-primary);
15
+ }
16
+ }
17
+
18
+ &:not(.disabled):hover {
19
+ & .divider {
20
+ background-color: transparent;
21
+ }
22
+ }
23
+
24
+ &.disabled,
25
+ &.disabled:hover {
26
+ cursor: not-allowed;
27
+
28
+ & .divider {
29
+ background-color: var(--glide-core-border-base-light);
30
+ }
31
+ }
32
+
33
+ & .menu-button {
34
+ align-items: center;
35
+ border-color: transparent;
36
+ border-radius: 0 0.75rem 0.75rem 0;
37
+ border-style: solid;
38
+ border-width: 1px 1px 1px 0;
39
+ cursor: pointer;
40
+ display: inline-flex;
41
+ font-family: var(--glide-core-heading-xxs-font-family);
42
+ font-style: var(--glide-core-heading-xxs-font-style);
43
+ font-weight: var(--glide-core-heading-xxs-font-weight);
44
+ gap: 0.625rem;
45
+ justify-content: center;
46
+ padding-block: var(--glide-core-spacing-xs);
47
+ padding-inline: var(--glide-core-spacing-xs);
48
+ text-decoration: none;
49
+ transition-duration: 150ms;
50
+ transition-property: color, background-color, border-color, fill, stroke;
51
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
52
+ user-select: none;
53
+
54
+ &:focus {
55
+ outline: none;
56
+ }
57
+
58
+ &:focus-visible {
59
+ ${focusOutline};
60
+ }
61
+
62
+ &:disabled {
63
+ cursor: default;
64
+ opacity: 1;
65
+ pointer-events: none;
66
+ }
67
+
68
+ &.primary {
69
+ background-color: var(--glide-core-surface-primary);
70
+ border-color: transparent;
71
+ color: var(--glide-core-text-selected);
72
+
73
+ &:disabled {
74
+ background-color: var(--glide-core-surface-disabled);
75
+ border-color: transparent;
76
+ color: var(--glide-core-text-tertiary-disabled);
77
+ }
78
+
79
+ &:not(:disabled):active {
80
+ background-color: var(--glide-core-surface-selected-hover);
81
+ border-color: transparent;
82
+ color: var(--glide-core-text-selected);
83
+ }
84
+
85
+ &:not(:active):hover:not(:disabled) {
86
+ background-color: var(--glide-core-surface-hover);
87
+ border-color: transparent;
88
+ box-shadow: var(--glide-core-glow-sm);
89
+ color: var(--glide-core-text-primary);
90
+ }
91
+ }
92
+
93
+ &.secondary {
94
+ background-color: transparent;
95
+ border-color: var(--glide-core-border-primary);
96
+ color: var(--glide-core-text-primary);
97
+
98
+ &:disabled {
99
+ background-color: var(--glide-core-surface-disabled);
100
+ border-color: transparent;
101
+ color: var(--glide-core-text-tertiary-disabled);
102
+ }
103
+
104
+ &:not(:disabled):active {
105
+ background-color: var(--glide-core-surface-selected-hover);
106
+ border-color: transparent;
107
+ color: var(--glide-core-text-selected);
108
+ }
109
+
110
+ &:not(:active):hover:not(:disabled) {
111
+ background-color: var(--glide-core-surface-hover);
112
+ border-color: transparent;
113
+ box-shadow: var(--glide-core-glow-sm);
114
+ color: var(--glide-core-text-primary);
115
+ }
116
+ }
117
+
118
+ &.small {
119
+ block-size: 1.75rem;
120
+ box-sizing: border-box;
121
+ font-size: var(--glide-core-body-xs-font-size);
122
+ line-height: 1rem;
123
+ min-inline-size: fit-content;
124
+ }
125
+
126
+ &.large {
127
+ block-size: 2.125rem;
128
+ box-sizing: border-box;
129
+ font-size: var(--glide-core-body-xxs-font-size);
130
+ line-height: 1.5rem;
131
+ }
132
+ }
133
+ }
134
+ `];
@@ -0,0 +1,3 @@
1
+ import './split-button.js';
2
+ import './split-container.js';
3
+ import './split-link.js';
@@ -0,0 +1,440 @@
1
+ import './split-button.js';
2
+ import './split-container.js';
3
+ import './split-link.js';
4
+ import { elementUpdated, expect, fixture, html, waitUntil, } from '@open-wc/testing';
5
+ import GlideCoreSplitButton from './split-button.js';
6
+ import GlideCoreSplitContainer from './split-container.js';
7
+ import GlideCoreSplitLink from './split-link.js';
8
+ import expectArgumentError from './library/expect-argument-error.js';
9
+ import sinon from 'sinon';
10
+ GlideCoreSplitContainer.shadowRootOptions.mode = 'open';
11
+ it('registers', async () => {
12
+ expect(window.customElements.get('glide-core-split-container')).to.equal(GlideCoreSplitContainer);
13
+ });
14
+ it('is accessible', async () => {
15
+ const component = await fixture(html `
16
+ <glide-core-split-container menu-label="label">
17
+ <glide-core-split-button slot="primary-action"
18
+ >Button</glide-core-split-button
19
+ >
20
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
21
+ <glide-core-menu-link label="Two" url="/two"></glide-core-menu-link>
22
+ <glide-core-menu-button label="Three"></glide-core-menu-button>
23
+ </glide-core-split-container>
24
+ `);
25
+ await expect(component).to.be.accessible();
26
+ });
27
+ it('should render a split button, a divider, and a menu button', async () => {
28
+ const component = await fixture(html `
29
+ <glide-core-split-container menu-label="label">
30
+ <glide-core-split-button slot="primary-action"
31
+ >Button</glide-core-split-button
32
+ >
33
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
34
+ </glide-core-split-container>
35
+ `);
36
+ expect(component.shadowRoot?.querySelector('[data-test="split-menu-button"]'))
37
+ .to.be.not.null;
38
+ expect(component.shadowRoot?.querySelector('[data-test="split-divider"]')).to
39
+ .be.not.null;
40
+ const slot = component?.shadowRoot?.querySelector('slot[data-test="primary-action"]');
41
+ expect(slot).to.be.not.null;
42
+ const defaultSlotValue = slot.assignedNodes()?.at(0);
43
+ expect(defaultSlotValue instanceof GlideCoreSplitButton).to.be.true;
44
+ expect(defaultSlotValue?.textContent).to.equal('Button');
45
+ });
46
+ it('should render a split link, a divider, and a menu button', async () => {
47
+ const component = await fixture(html `
48
+ <glide-core-split-container menu-label="label">
49
+ <glide-core-split-link slot="primary-action">Link</glide-core-split-link>
50
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
51
+ </glide-core-split-container>
52
+ `);
53
+ expect(component.shadowRoot?.querySelector('[data-test="split-menu-button"]'))
54
+ .to.be.not.null;
55
+ expect(component.shadowRoot?.querySelector('[data-test="split-divider"]')).to
56
+ .be.not.null;
57
+ const slot = component?.shadowRoot?.querySelector('slot[data-test="primary-action"]');
58
+ expect(slot).to.be.not.null;
59
+ const defaultSlotValue = slot.assignedNodes()?.at(0);
60
+ expect(defaultSlotValue instanceof GlideCoreSplitLink).to.be.true;
61
+ expect(defaultSlotValue?.textContent).to.equal('Link');
62
+ });
63
+ it('does not set the menu to "open" by default', async () => {
64
+ const component = await fixture(html `
65
+ <glide-core-split-container menu-label="label">
66
+ <glide-core-split-button slot="primary-action"
67
+ >Button</glide-core-split-button
68
+ >
69
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
70
+ </glide-core-split-container>
71
+ `);
72
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.not.have.attribute('open');
73
+ });
74
+ it('sets the menu component to "open" when the "open" attribute is set', async () => {
75
+ const component = await fixture(html `
76
+ <glide-core-split-container menu-label="label" open>
77
+ <glide-core-split-button slot="primary-action"
78
+ >Button</glide-core-split-button
79
+ >
80
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
81
+ </glide-core-split-container>
82
+ `);
83
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('open');
84
+ });
85
+ it('applies appropriate classes and attributes when "size" is set to "small"', async () => {
86
+ const component = await fixture(html `
87
+ <glide-core-split-container menu-label="label" size="small">
88
+ <glide-core-split-button slot="primary-action"
89
+ >Button</glide-core-split-button
90
+ >
91
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
92
+ </glide-core-split-container>
93
+ `);
94
+ expect(component.shadowRoot
95
+ ?.querySelector('[data-test="primary-action"]')
96
+ ?.assignedNodes()
97
+ ?.at(0)).to.have.attribute('size', 'small');
98
+ expect(component.shadowRoot
99
+ ?.querySelector('[data-test="split-menu-button"]')
100
+ ?.classList.contains('small')).to.be.true;
101
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('size', 'small');
102
+ });
103
+ it('applies appropriate classes and attributes when "size" is set to "large"', async () => {
104
+ const component = await fixture(html `
105
+ <glide-core-split-container menu-label="label" size="large">
106
+ <glide-core-split-button slot="primary-action"
107
+ >Button</glide-core-split-button
108
+ >
109
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
110
+ </glide-core-split-container>
111
+ `);
112
+ expect(component.shadowRoot
113
+ ?.querySelector('[data-test="primary-action"]')
114
+ ?.assignedNodes()
115
+ ?.at(0)).to.have.attribute('size', 'large');
116
+ expect(component.shadowRoot
117
+ ?.querySelector('[data-test="split-menu-button"]')
118
+ ?.classList.contains('large')).to.be.true;
119
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('size', 'large');
120
+ });
121
+ it('applies appropriate classes and attributes by default as "large" when "size" is not set', async () => {
122
+ const component = await fixture(html `
123
+ <glide-core-split-container menu-label="label">
124
+ <glide-core-split-button slot="primary-action"
125
+ >Button</glide-core-split-button
126
+ >
127
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
128
+ </glide-core-split-container>
129
+ `);
130
+ expect(component.shadowRoot
131
+ ?.querySelector('[data-test="primary-action"]')
132
+ ?.assignedNodes()
133
+ ?.at(0)).to.have.attribute('size', 'large');
134
+ expect(component.shadowRoot
135
+ ?.querySelector('[data-test="split-menu-button"]')
136
+ ?.classList.contains('large')).to.be.true;
137
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('size', 'large');
138
+ });
139
+ it('applies appropriate classes and attributes when "size" is dynamically changed using the split button', async () => {
140
+ const component = await fixture(html `
141
+ <glide-core-split-container menu-label="label" size="large">
142
+ <glide-core-split-button slot="primary-action"
143
+ >Button</glide-core-split-button
144
+ >
145
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
146
+ </glide-core-split-container>
147
+ `);
148
+ expect(component.shadowRoot
149
+ ?.querySelector('[data-test="primary-action"]')
150
+ ?.assignedNodes()
151
+ ?.at(0)).to.have.attribute('size', 'large');
152
+ expect(component.shadowRoot
153
+ ?.querySelector('[data-test="split-menu-button"]')
154
+ ?.classList.contains('large')).to.be.true;
155
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('size', 'large');
156
+ component.size = 'small';
157
+ await elementUpdated(component);
158
+ expect(component.shadowRoot
159
+ ?.querySelector('[data-test="primary-action"]')
160
+ ?.assignedNodes()
161
+ ?.at(0)).to.have.attribute('size', 'small');
162
+ expect(component.shadowRoot
163
+ ?.querySelector('[data-test="split-menu-button"]')
164
+ ?.classList.contains('small')).to.be.true;
165
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('size', 'small');
166
+ });
167
+ it('applies appropriate classes and attributes when "size" is dynamically changed using the link button', async () => {
168
+ const component = await fixture(html `
169
+ <glide-core-split-container menu-label="label" size="large">
170
+ <glide-core-split-link slot="primary-action" url="/"
171
+ >Button</glide-core-split-link
172
+ >
173
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
174
+ </glide-core-split-container>
175
+ `);
176
+ expect(component.shadowRoot
177
+ ?.querySelector('[data-test="primary-action"]')
178
+ ?.assignedNodes()
179
+ ?.at(0)).to.have.attribute('size', 'large');
180
+ expect(component.shadowRoot
181
+ ?.querySelector('[data-test="split-menu-button"]')
182
+ ?.classList.contains('large')).to.be.true;
183
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('size', 'large');
184
+ component.size = 'small';
185
+ await elementUpdated(component);
186
+ expect(component.shadowRoot
187
+ ?.querySelector('[data-test="primary-action"]')
188
+ ?.assignedNodes()
189
+ ?.at(0)).to.have.attribute('size', 'small');
190
+ expect(component.shadowRoot
191
+ ?.querySelector('[data-test="split-menu-button"]')
192
+ ?.classList.contains('small')).to.be.true;
193
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('size', 'small');
194
+ });
195
+ it('applies appropriate classes and sets the "variant" to "primary" by default', async () => {
196
+ const component = await fixture(html `
197
+ <glide-core-split-container menu-label="label">
198
+ <glide-core-split-button slot="primary-action"
199
+ >Button</glide-core-split-button
200
+ >
201
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
202
+ </glide-core-split-container>
203
+ `);
204
+ expect(component.shadowRoot
205
+ ?.querySelector('[data-test="primary-action"]')
206
+ ?.assignedNodes()
207
+ ?.at(0)).to.have.attribute('variant', 'primary');
208
+ expect(component.shadowRoot
209
+ ?.querySelector('[data-test="split-menu-button"]')
210
+ ?.classList.contains('primary')).to.be.true;
211
+ expect(component.shadowRoot
212
+ ?.querySelector('[data-test="split-divider"]')
213
+ ?.classList.contains('primary')).to.be.true;
214
+ });
215
+ it('applies appropriate classes when "variant" is set to "primary"', async () => {
216
+ const component = await fixture(html `
217
+ <glide-core-split-container menu-label="label" variant="primary">
218
+ <glide-core-split-button slot="primary-action"
219
+ >Button</glide-core-split-button
220
+ >
221
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
222
+ </glide-core-split-container>
223
+ `);
224
+ expect(component.shadowRoot
225
+ ?.querySelector('[data-test="primary-action"]')
226
+ ?.assignedNodes()
227
+ ?.at(0)).to.have.attribute('variant', 'primary');
228
+ expect(component.shadowRoot
229
+ ?.querySelector('[data-test="split-menu-button"]')
230
+ ?.classList.contains('primary')).to.be.true;
231
+ expect(component.shadowRoot
232
+ ?.querySelector('[data-test="split-divider"]')
233
+ ?.classList.contains('primary')).to.be.true;
234
+ });
235
+ it('applies appropriate classes when "variant" is set to "secondary"', async () => {
236
+ const component = await fixture(html `
237
+ <glide-core-split-container menu-label="label" variant="secondary">
238
+ <glide-core-split-button slot="primary-action"
239
+ >Button</glide-core-split-button
240
+ >
241
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
242
+ </glide-core-split-container>
243
+ `);
244
+ expect(component.shadowRoot
245
+ ?.querySelector('[data-test="primary-action"]')
246
+ ?.assignedNodes()
247
+ ?.at(0)).to.have.attribute('variant', 'secondary');
248
+ expect(component.shadowRoot
249
+ ?.querySelector('[data-test="split-menu-button"]')
250
+ ?.classList.contains('secondary')).to.be.true;
251
+ expect(component.shadowRoot
252
+ ?.querySelector('[data-test="split-divider"]')
253
+ ?.classList.contains('secondary')).to.be.true;
254
+ });
255
+ it('applies appropriate classes and attributes when "variant" is dynamically changed using the split button', async () => {
256
+ const component = await fixture(html `
257
+ <glide-core-split-container menu-label="label" variant="primary">
258
+ <glide-core-split-button slot="primary-action"
259
+ >Button</glide-core-split-button
260
+ >
261
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
262
+ </glide-core-split-container>
263
+ `);
264
+ expect(component.shadowRoot
265
+ ?.querySelector('[data-test="primary-action"]')
266
+ ?.assignedNodes()
267
+ ?.at(0)).to.have.attribute('variant', 'primary');
268
+ expect(component.shadowRoot
269
+ ?.querySelector('[data-test="split-menu-button"]')
270
+ ?.classList.contains('primary')).to.be.true;
271
+ expect(component.shadowRoot
272
+ ?.querySelector('[data-test="split-divider"]')
273
+ ?.classList.contains('primary')).to.be.true;
274
+ component.variant = 'secondary';
275
+ await elementUpdated(component);
276
+ expect(component.shadowRoot
277
+ ?.querySelector('[data-test="primary-action"]')
278
+ ?.assignedNodes()
279
+ ?.at(0)).to.have.attribute('variant', 'secondary');
280
+ expect(component.shadowRoot
281
+ ?.querySelector('[data-test="split-menu-button"]')
282
+ ?.classList.contains('secondary')).to.be.true;
283
+ expect(component.shadowRoot
284
+ ?.querySelector('[data-test="split-divider"]')
285
+ ?.classList.contains('secondary')).to.be.true;
286
+ });
287
+ it('applies appropriate classes and attributes when "variant" is dynamically changed using the link button', async () => {
288
+ const component = await fixture(html `
289
+ <glide-core-split-container menu-label="label" variant="primary">
290
+ <glide-core-split-link slot="primary-action" url="/"
291
+ >Button</glide-core-split-link
292
+ >
293
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
294
+ </glide-core-split-container>
295
+ `);
296
+ expect(component.shadowRoot
297
+ ?.querySelector('[data-test="primary-action"]')
298
+ ?.assignedNodes()
299
+ ?.at(0)).to.have.attribute('variant', 'primary');
300
+ expect(component.shadowRoot
301
+ ?.querySelector('[data-test="split-menu-button"]')
302
+ ?.classList.contains('primary')).to.be.true;
303
+ expect(component.shadowRoot
304
+ ?.querySelector('[data-test="split-divider"]')
305
+ ?.classList.contains('primary')).to.be.true;
306
+ component.variant = 'secondary';
307
+ await elementUpdated(component);
308
+ expect(component.shadowRoot
309
+ ?.querySelector('[data-test="primary-action"]')
310
+ ?.assignedNodes()
311
+ ?.at(0)).to.have.attribute('variant', 'secondary');
312
+ expect(component.shadowRoot
313
+ ?.querySelector('[data-test="split-menu-button"]')
314
+ ?.classList.contains('secondary')).to.be.true;
315
+ expect(component.shadowRoot
316
+ ?.querySelector('[data-test="split-divider"]')
317
+ ?.classList.contains('secondary')).to.be.true;
318
+ });
319
+ it('sets the appropriate classes and attributes when the "disabled" attribute is set', async () => {
320
+ const component = await fixture(html `
321
+ <glide-core-split-container menu-label="label" disabled>
322
+ <glide-core-split-button slot="primary-action"
323
+ >Button</glide-core-split-button
324
+ >
325
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
326
+ </glide-core-split-container>
327
+ `);
328
+ expect(component.shadowRoot
329
+ ?.querySelector('[data-test="primary-action"]')
330
+ ?.assignedNodes()
331
+ ?.at(0)).to.have.attribute('disabled');
332
+ expect(component.shadowRoot?.querySelector('[data-test="split-menu-button"]')).to.have.attribute('disabled');
333
+ expect(component.shadowRoot?.querySelector('[data-test="split-menu-button"]')).to.have.attribute('disabled');
334
+ });
335
+ it('applies appropriate classes and attributes when "disabled" is dynamically changed using the split button', async () => {
336
+ const component = await fixture(html `
337
+ <glide-core-split-container menu-label="label">
338
+ <glide-core-split-button slot="primary-action"
339
+ >Button</glide-core-split-button
340
+ >
341
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
342
+ </glide-core-split-container>
343
+ `);
344
+ expect(component.shadowRoot
345
+ ?.querySelector('[data-test="primary-action"]')
346
+ ?.assignedNodes()
347
+ ?.at(0)).to.not.have.attribute('disabled');
348
+ expect(component.shadowRoot?.querySelector('[data-test="split-menu-button"]')).to.not.have.attribute('disabled');
349
+ component.disabled = true;
350
+ await elementUpdated(component);
351
+ expect(component.shadowRoot
352
+ ?.querySelector('[data-test="primary-action"]')
353
+ ?.assignedNodes()
354
+ ?.at(0)).to.have.attribute('disabled');
355
+ expect(component.shadowRoot?.querySelector('[data-test="split-menu-button"]')).to.have.attribute('disabled');
356
+ });
357
+ it('applies appropriate classes and attributes when "disabled" is dynamically changed using the link button', async () => {
358
+ const component = await fixture(html `
359
+ <glide-core-split-container menu-label="label">
360
+ <glide-core-split-link slot="primary-action" url="/"
361
+ >Button</glide-core-split-link
362
+ >
363
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
364
+ </glide-core-split-container>
365
+ `);
366
+ expect(component.shadowRoot
367
+ ?.querySelector('[data-test="primary-action"]')
368
+ ?.assignedNodes()
369
+ ?.at(0)).to.not.have.attribute('disabled');
370
+ expect(component.shadowRoot?.querySelector('[data-test="split-menu-button"]')).to.not.have.attribute('disabled');
371
+ component.disabled = true;
372
+ await elementUpdated(component);
373
+ expect(component.shadowRoot
374
+ ?.querySelector('[data-test="primary-action"]')
375
+ ?.assignedNodes()
376
+ ?.at(0)).to.have.attribute('disabled');
377
+ expect(component.shadowRoot?.querySelector('[data-test="split-menu-button"]')).to.have.attribute('disabled');
378
+ });
379
+ it('sets the default "menu-placement" as "bottom-end"', async () => {
380
+ const component = await fixture(html `
381
+ <glide-core-split-container menu-label="label">
382
+ <glide-core-split-button slot="primary-action"
383
+ >Button</glide-core-split-button
384
+ >
385
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
386
+ </glide-core-split-container>
387
+ `);
388
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('placement', 'bottom-end');
389
+ });
390
+ it('sets the "menu-placement" attribute as specified', async () => {
391
+ const component = await fixture(html `
392
+ <glide-core-split-container menu-label="label" menu-placement="bottom">
393
+ <glide-core-split-button slot="primary-action"
394
+ >Button</glide-core-split-button
395
+ >
396
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
397
+ </glide-core-split-container>
398
+ `);
399
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('placement', 'bottom');
400
+ });
401
+ it('focuses the "primary-action" slotted element when the container component is focused', async () => {
402
+ const component = await fixture(html `
403
+ <glide-core-split-container menu-label="label" menu-placement="bottom">
404
+ <glide-core-split-button slot="primary-action"
405
+ >Button</glide-core-split-button
406
+ >
407
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
408
+ </glide-core-split-container>
409
+ `);
410
+ component.focus();
411
+ expect(component.shadowRoot
412
+ ?.querySelector('[data-test="primary-action"]')
413
+ ?.assignedNodes()
414
+ ?.at(0)).to.have.focus;
415
+ });
416
+ it('throws an error when the default slot is empty', async () => {
417
+ await expectArgumentError(() => fixture(html `<glide-core-split-container menu-label="label">
418
+ <glide-core-split-button slot="primary-action"
419
+ >Button</glide-core-split-button
420
+ >
421
+ </glide-core-split-container>`));
422
+ });
423
+ it('throws an error when the default slot is an unsupported type', async () => {
424
+ await expectArgumentError(() => fixture(html `<glide-core-split-container menu-label="label">
425
+ <glide-core-split-button slot="primary-action">
426
+ Button
427
+ </glide-core-split-button>
428
+ <div>Option</div>
429
+ </glide-core-split-container>`));
430
+ // Menu is rendered asynchronously outside of Split Container's lifecycle
431
+ // and asserts against its default slot. That assertion, which is expected
432
+ // to fail in this case, results in an unhandled rejection that gets logged.
433
+ // `console.error` is stubbed so the logs aren't muddied.
434
+ const stub = sinon.stub(console, 'error');
435
+ // Menu asserts against its default slot once on `firstUpdated` and
436
+ // again on "slotchange". So we wait until the stub has been called
437
+ // twice before restoring it.
438
+ await waitUntil(() => stub.calledTwice);
439
+ stub.restore();
440
+ });
@@ -0,0 +1 @@
1
+ import './split-container.js';
@@ -0,0 +1,20 @@
1
+ import './split-container.js';
2
+ import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
3
+ import GlideCoreSplitContainer from './split-container.js';
4
+ GlideCoreSplitContainer.shadowRootOptions.mode = 'open';
5
+ it('the menu opens when the menu button is clicked', async () => {
6
+ const component = await fixture(html `
7
+ <glide-core-split-container menu-label="label">
8
+ <glide-core-split-button slot="primary-action"
9
+ >Button</glide-core-split-button
10
+ >
11
+ <glide-core-menu-link label="One" url="/one"></glide-core-menu-link>
12
+ </glide-core-split-container>
13
+ `);
14
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.not.have.attribute('open');
15
+ component.shadowRoot
16
+ ?.querySelector('[data-test="split-menu-button"]')
17
+ ?.click();
18
+ await elementUpdated(component);
19
+ expect(component.shadowRoot?.querySelector('glide-core-menu')).to.have.attribute('open');
20
+ });
@@ -0,0 +1,25 @@
1
+ import './menu.js';
2
+ import { LitElement } from 'lit';
3
+ declare global {
4
+ interface HTMLElementTagNameMap {
5
+ 'glide-core-split-link': GlideCoreSplitLink;
6
+ }
7
+ }
8
+ /**
9
+ * @description - A link to be used in the `primary-action` slot of `glide-core-split-container`.
10
+ *
11
+ * @slot prefix - An optional icon slot to display before the label.
12
+ * @slot - A label for the contents of the link.
13
+ */
14
+ export default class GlideCoreSplitLink extends LitElement {
15
+ #private;
16
+ static shadowRootOptions: ShadowRootInit;
17
+ static styles: import("lit").CSSResult[];
18
+ url?: string;
19
+ disabled: boolean;
20
+ variant: 'primary' | 'secondary';
21
+ size: 'large' | 'small';
22
+ firstUpdated(): void;
23
+ render(): import("lit").TemplateResult<1>;
24
+ private hasPrefixSlot;
25
+ }
@@ -0,0 +1 @@
1
+ var __decorate=this&&this.__decorate||function(e,t,o,l){var i,s=arguments.length,r=s<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,o,l);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(r=(s<3?i(r):s>3?i(t,o,r):i(t,o))||r);return s>3&&r&&Object.defineProperty(t,o,r),r};import"./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,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{owSlot,owSlotType}from"./library/ow.js";import styles from"./split-button.styles.js";let GlideCoreSplitLink=class GlideCoreSplitLink extends LitElement{constructor(){super(...arguments),this.disabled=!1,this.variant="primary",this.size="large",this.hasPrefixSlot=!1,this.#e=createRef(),this.#t=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#e.value),owSlotType(this.#e.value,[Text])}render(){return this.disabled?html`<span class="${classMap({component:!0,disabled:!0,[this.variant]:!0,[this.size]:!0,"has-prefix":this.hasPrefixSlot})}" aria-disabled="true" role="link" @keydown="${this.#o}" data-test="split-link"><slot name="prefix" @slotchange="${this.#l}" ${ref(this.#t)} data-test="prefix-slot"></slot><slot @slotchange="${this.#i}" ${ref(this.#e)} data-test="default-slot"></slot></span>`:html`<a href="${ifDefined(this.url)}" class="${classMap({component:!0,[this.variant]:!0,[this.size]:!0,"has-prefix":this.hasPrefixSlot})}" @keydown="${this.#o}" data-test="split-link"><slot name="prefix" @slotchange="${this.#l}" ${ref(this.#t)} data-test="prefix-slot"></slot><slot @slotchange="${this.#i}" ${ref(this.#e)} data-test="default-slot"></slot></a>`}#e;#t;#i(){owSlot(this.#e.value),owSlotType(this.#e.value,[Text])}#o(e){" "===e.key&&this.url?.length&&window.open(this.url)}#l(){const e=this.#t.value?.assignedNodes();this.hasPrefixSlot=!!(e&&e.length>0)}};__decorate([property({reflect:!0})],GlideCoreSplitLink.prototype,"url",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreSplitLink.prototype,"disabled",void 0),__decorate([property({reflect:!0})],GlideCoreSplitLink.prototype,"variant",void 0),__decorate([property({reflect:!0})],GlideCoreSplitLink.prototype,"size",void 0),__decorate([state()],GlideCoreSplitLink.prototype,"hasPrefixSlot",void 0),GlideCoreSplitLink=__decorate([customElement("glide-core-split-link")],GlideCoreSplitLink);export default GlideCoreSplitLink;
@@ -0,0 +1 @@
1
+ import './split-link.js';