@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.
- package/README.md +11 -1
- package/dist/accordion.js +1 -1
- package/dist/accordion.styles.js +5 -4
- package/dist/accordion.test.basics.js +109 -0
- package/dist/accordion.test.events.js +39 -0
- package/dist/button-group.button.js +1 -1
- package/dist/button-group.button.styles.js +6 -5
- package/dist/button-group.button.test.basics.js +169 -0
- package/dist/button-group.button.test.events.js +73 -0
- package/dist/button-group.js +1 -1
- package/dist/button-group.styles.js +3 -3
- package/dist/button-group.test.basics.js +268 -0
- package/dist/button-group.test.events.js +291 -0
- package/dist/button.d.ts +3 -2
- package/dist/button.js +1 -1
- package/dist/button.styles.js +5 -5
- package/dist/button.test.basics.js +202 -0
- package/dist/button.test.events.js +25 -0
- package/dist/button.test.form.js +49 -0
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.styles.js +2 -2
- package/dist/checkbox-group.test.basics.js +119 -0
- package/dist/checkbox-group.test.events.js +110 -0
- package/dist/checkbox-group.test.focus.js +45 -0
- package/dist/checkbox-group.test.form.js +130 -0
- package/dist/checkbox-group.test.validity.js +75 -0
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.styles.js +7 -4
- package/dist/checkbox.test.basics.js +89 -0
- package/dist/checkbox.test.events.js +87 -0
- package/dist/checkbox.test.focus.js +38 -0
- package/dist/checkbox.test.form.js +115 -0
- package/dist/checkbox.test.states.js +62 -0
- package/dist/checkbox.test.validity.js +51 -0
- package/dist/drawer.d.ts +2 -2
- package/dist/drawer.js +1 -15
- package/dist/drawer.styles.js +14 -4
- package/dist/drawer.test.accessibility.js +22 -0
- package/dist/drawer.test.basics.js +43 -0
- package/dist/drawer.test.closing.js +37 -0
- package/dist/drawer.test.events.js +52 -0
- package/dist/drawer.test.floating-components.d.ts +1 -0
- package/dist/drawer.test.floating-components.js +51 -0
- package/dist/drawer.test.methods.js +34 -0
- package/dist/dropdown.d.ts +4 -2
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.d.ts +0 -2
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.styles.js +2 -2
- package/dist/dropdown.option.test.basics.js +59 -0
- package/dist/dropdown.option.test.basics.multiple.js +26 -0
- package/dist/dropdown.option.test.basics.single.js +20 -0
- package/dist/dropdown.option.test.events.js +27 -0
- package/dist/dropdown.option.test.focus.js +11 -0
- package/dist/dropdown.option.test.interactions.multiple.js +82 -0
- package/dist/dropdown.option.test.interactions.single.js +22 -0
- package/dist/dropdown.styles.js +26 -6
- package/dist/dropdown.test.basics.filterable.js +84 -0
- package/dist/dropdown.test.basics.js +233 -0
- package/dist/dropdown.test.basics.multiple.js +270 -0
- package/dist/dropdown.test.basics.single.js +79 -0
- package/dist/dropdown.test.events.js +268 -0
- package/dist/dropdown.test.events.multiple.js +130 -0
- package/dist/dropdown.test.focus.d.ts +1 -0
- package/dist/dropdown.test.focus.filterable.js +154 -0
- package/dist/dropdown.test.focus.js +28 -0
- package/dist/dropdown.test.focus.multiple.js +181 -0
- package/dist/dropdown.test.focus.single.js +53 -0
- package/dist/dropdown.test.form.js +140 -0
- package/dist/dropdown.test.form.multiple.js +149 -0
- package/dist/dropdown.test.form.single.js +128 -0
- package/dist/dropdown.test.interactions.filterable.js +449 -0
- package/dist/dropdown.test.interactions.js +446 -0
- package/dist/dropdown.test.interactions.multiple.js +908 -0
- package/dist/dropdown.test.interactions.single.js +466 -0
- package/dist/dropdown.test.validity.js +46 -0
- package/dist/icon-button.d.ts +3 -2
- package/dist/icon-button.js +1 -1
- package/dist/icon-button.styles.js +12 -12
- package/dist/icon-button.test.basics.js +110 -0
- package/dist/icons/checked.js +1 -1
- package/dist/icons/magnifying-glass.js +1 -1
- package/dist/input.js +1 -1
- package/dist/input.styles.js +4 -3
- package/dist/input.test.basics.js +169 -0
- package/dist/input.test.events.js +97 -0
- package/dist/input.test.focus.js +54 -0
- package/dist/input.test.form.js +56 -0
- package/dist/input.test.validity.js +50 -0
- package/dist/label.js +1 -1
- package/dist/label.styles.js +13 -15
- package/dist/label.test.basics.js +129 -0
- package/dist/library/expect-argument-error.js +1 -1
- package/dist/library/localize.d.ts +17 -0
- package/dist/library/localize.js +1 -0
- package/dist/library/ow.js +1 -1
- package/dist/library/ow.test.js +55 -0
- package/dist/library/set-containing-block.d.ts +15 -0
- package/dist/library/set-containing-block.js +1 -0
- package/dist/menu.button.d.ts +1 -2
- package/dist/menu.button.js +1 -1
- package/dist/menu.button.styles.js +3 -3
- package/dist/menu.button.test.basics.js +42 -0
- package/dist/menu.d.ts +7 -2
- package/dist/menu.js +1 -1
- package/dist/menu.link.d.ts +1 -2
- package/dist/menu.link.js +1 -1
- package/dist/menu.link.styles.js +3 -3
- package/dist/menu.link.test.basics.js +46 -0
- package/dist/menu.options.d.ts +22 -0
- package/dist/menu.options.js +1 -0
- package/dist/menu.options.styles.d.ts +2 -0
- package/dist/menu.options.styles.js +33 -0
- package/dist/menu.options.test.basics.d.ts +2 -0
- package/dist/menu.options.test.basics.js +43 -0
- package/dist/menu.stories.d.ts +1 -0
- package/dist/menu.styles.js +7 -31
- package/dist/menu.test.basics.d.ts +1 -0
- package/dist/menu.test.basics.js +183 -0
- package/dist/menu.test.focus.d.ts +0 -1
- package/dist/menu.test.focus.js +84 -0
- package/dist/menu.test.interactions.d.ts +1 -1
- package/dist/menu.test.interactions.js +664 -0
- package/dist/modal.icon-button.js +1 -1
- package/dist/modal.icon-button.styles.js +2 -2
- package/dist/modal.icon-button.test.basics.js +45 -0
- package/dist/modal.js +1 -15
- package/dist/modal.styles.js +4 -7
- package/dist/modal.tertiary-icon.d.ts +1 -0
- package/dist/modal.tertiary-icon.js +1 -1
- package/dist/modal.tertiary-icon.test.basics.js +59 -0
- package/dist/modal.test.accessibility.js +48 -0
- package/dist/modal.test.basics.js +203 -0
- package/dist/modal.test.close.js +38 -0
- package/dist/modal.test.events.js +110 -0
- package/dist/modal.test.floating-components.d.ts +1 -0
- package/dist/modal.test.floating-components.js +62 -0
- package/dist/modal.test.lock-scroll.js +76 -0
- package/dist/modal.test.methods.js +23 -0
- package/dist/modal.test.scrollbars.js +19 -0
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.styles.js +20 -24
- package/dist/radio-group.test.basics.js +323 -0
- package/dist/radio-group.test.events.js +277 -0
- package/dist/radio-group.test.focus.js +75 -0
- package/dist/radio-group.test.form.js +104 -0
- package/dist/radio-group.test.validity.js +228 -0
- package/dist/radio.js +1 -1
- package/dist/radio.styles.js +14 -31
- package/dist/split-button.d.ts +27 -0
- package/dist/split-button.js +1 -0
- package/dist/split-button.stories.d.ts +17 -0
- package/dist/split-button.styles.d.ts +2 -0
- package/dist/split-button.styles.js +102 -0
- package/dist/split-button.test.basics.d.ts +1 -0
- package/dist/split-button.test.basics.js +99 -0
- package/dist/split-container.d.ts +31 -0
- package/dist/split-container.js +1 -0
- package/dist/split-container.styles.d.ts +2 -0
- package/dist/split-container.styles.js +134 -0
- package/dist/split-container.test.basics.d.ts +3 -0
- package/dist/split-container.test.basics.js +440 -0
- package/dist/split-container.test.interactions.d.ts +1 -0
- package/dist/split-container.test.interactions.js +20 -0
- package/dist/split-link.d.ts +25 -0
- package/dist/split-link.js +1 -0
- package/dist/split-link.test.basics.d.ts +1 -0
- package/dist/split-link.test.basics.js +92 -0
- package/dist/split-link.test.interactions.d.ts +1 -0
- package/dist/split-link.test.interactions.js +19 -0
- package/dist/status-indicator.js +1 -1
- package/dist/status-indicator.styles.js +2 -2
- package/dist/status-indicator.test.basics.js +102 -0
- package/dist/styles/focus-outline.js +1 -4
- package/dist/styles/variables.css +1 -1
- package/dist/styles/visually-hidden.js +1 -11
- package/dist/tab.group.js +1 -1
- package/dist/tab.group.styles.js +2 -2
- package/dist/tab.group.test.basics.js +185 -0
- package/dist/tab.js +1 -1
- package/dist/tab.panel.js +1 -1
- package/dist/tab.panel.styles.js +3 -3
- package/dist/tab.styles.js +80 -55
- package/dist/tab.test.basics.js +71 -0
- package/dist/tag.js +1 -1
- package/dist/tag.styles.js +4 -3
- package/dist/tag.test.basics.js +118 -0
- package/dist/tag.test.events.js +16 -0
- package/dist/tag.test.focus.js +11 -0
- package/dist/tag.test.translations.d.ts +1 -0
- package/dist/tag.test.translations.js +25 -0
- package/dist/textarea.js +2 -2
- package/dist/textarea.styles.js +5 -4
- package/dist/textarea.test.basics.js +140 -0
- package/dist/textarea.test.events.js +204 -0
- package/dist/textarea.test.form.js +70 -0
- package/dist/textarea.test.validity.js +83 -0
- package/dist/toasts.js +1 -1
- package/dist/toasts.styles.js +2 -2
- package/dist/toasts.test.basics.js +94 -0
- package/dist/toasts.toast.js +1 -1
- package/dist/toasts.toast.styles.js +5 -2
- package/dist/toasts.toast.test.basics.js +139 -0
- package/dist/toggle.js +1 -1
- package/dist/toggle.styles.js +3 -3
- package/dist/toggle.test.basics.js +68 -0
- package/dist/toggle.test.events.js +29 -0
- package/dist/toggle.test.focus.js +9 -0
- package/dist/toggle.test.states.js +43 -0
- package/dist/tooltip.d.ts +2 -0
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +5 -3
- package/dist/tooltip.test.basics.js +64 -0
- package/dist/tooltip.test.interactions.js +78 -0
- package/dist/translations/en.d.ts +3 -0
- package/dist/translations/en.js +1 -0
- package/dist/translations/fr.d.ts +3 -0
- package/dist/translations/fr.js +1 -0
- package/dist/translations/ja.d.ts +3 -0
- package/dist/translations/ja.js +1 -0
- package/dist/tree.d.ts +1 -0
- package/dist/tree.item.d.ts +3 -1
- package/dist/tree.item.icon-button.js +1 -1
- package/dist/tree.item.icon-button.styles.js +2 -2
- package/dist/tree.item.icon-button.test.basics.js +13 -0
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +2 -0
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.menu.styles.js +2 -2
- package/dist/tree.item.menu.test.basics.js +33 -0
- package/dist/tree.item.styles.js +23 -8
- package/dist/tree.item.test.basics.js +102 -0
- package/dist/tree.js +1 -1
- package/dist/tree.stories.d.ts +1 -0
- package/dist/tree.styles.js +2 -2
- package/dist/tree.test.aria.js +86 -0
- package/dist/tree.test.basics.js +123 -0
- package/dist/tree.test.events.js +19 -0
- package/dist/tree.test.focus.js +261 -0
- package/package.json +25 -18
- /package/dist/{dropdown.option.test.focus.multiple.d.ts → dropdown.option.test.focus.d.ts} +0 -0
- /package/dist/{dropdown.option.test.focus.single.d.ts → dropdown.test.events.multiple.d.ts} +0 -0
@@ -0,0 +1,466 @@
|
|
1
|
+
import { ArgumentError } from 'ow';
|
2
|
+
import { assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
|
3
|
+
import { sendKeys } from '@web/test-runner-commands';
|
4
|
+
import GlideCoreDropdown from './dropdown.js';
|
5
|
+
import GlideCoreDropdownOption from './dropdown.option.js';
|
6
|
+
import sinon from 'sinon';
|
7
|
+
GlideCoreDropdown.shadowRootOptions.mode = 'open';
|
8
|
+
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
9
|
+
it('opens on click', async () => {
|
10
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
11
|
+
<glide-core-dropdown-option
|
12
|
+
label="Label"
|
13
|
+
value="value"
|
14
|
+
></glide-core-dropdown-option>
|
15
|
+
</glide-core-dropdown>`);
|
16
|
+
// Calling `click()` would be sweet. The problem is it sets `event.detail` to `0`,
|
17
|
+
// which puts us in a guard in the event handler. `Event` has no `detail` property
|
18
|
+
// and would work. `CustomEvent` is used for completeness and to get us as close as
|
19
|
+
// possible to a real click. See the comment in the handler for more information.
|
20
|
+
component.shadowRoot
|
21
|
+
?.querySelector('[data-test="button"]')
|
22
|
+
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
23
|
+
expect(component.open).to.be.true;
|
24
|
+
});
|
25
|
+
it('toggles open and closed when the button is clicked', async () => {
|
26
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
27
|
+
<glide-core-dropdown-option
|
28
|
+
label="Label"
|
29
|
+
value="value"
|
30
|
+
></glide-core-dropdown-option>
|
31
|
+
</glide-core-dropdown>`);
|
32
|
+
// Calling `click()` would be sweet. The problem is it sets `event.detail` to `0`,
|
33
|
+
// which puts us in a guard in the event handler. `Event` has no `detail` property
|
34
|
+
// and would work. `CustomEvent` is used for completeness and to get us as close as
|
35
|
+
// possible to a real click. See the comment in the handler for more information.
|
36
|
+
component.shadowRoot
|
37
|
+
?.querySelector('[data-test="button"]')
|
38
|
+
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
39
|
+
expect(component.open).to.be.false;
|
40
|
+
});
|
41
|
+
it('does not toggle open and closed when the button overflow text is clicked', async () => {
|
42
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
43
|
+
<glide-core-dropdown-option
|
44
|
+
label="Label"
|
45
|
+
value="value"
|
46
|
+
></glide-core-dropdown-option>
|
47
|
+
</glide-core-dropdown>`);
|
48
|
+
// Calling `click()` would be sweet. The problem is it sets `event.detail` to `0`,
|
49
|
+
// which puts us in a guard in the event handler. `Event` has no `detail` property
|
50
|
+
// and would work. `CustomEvent` is used for completeness and to get us as close as
|
51
|
+
// possible to a real click. See the comment in the handler for more information.
|
52
|
+
component.shadowRoot
|
53
|
+
?.querySelector('[data-test="tag-overflow-text"]')
|
54
|
+
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
55
|
+
expect(component.open).to.be.true;
|
56
|
+
});
|
57
|
+
it('selects an option on click', async () => {
|
58
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
59
|
+
<glide-core-dropdown-option
|
60
|
+
label="One"
|
61
|
+
value="one"
|
62
|
+
></glide-core-dropdown-option>
|
63
|
+
</glide-core-dropdown>`);
|
64
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
65
|
+
option?.click();
|
66
|
+
await elementUpdated(component);
|
67
|
+
const labels = component.shadowRoot?.querySelectorAll('[data-test="selected-option-label"]');
|
68
|
+
expect(option?.selected).to.be.true;
|
69
|
+
expect(labels?.length).to.equal(1);
|
70
|
+
expect(labels?.[0]?.textContent?.trim()).to.equal('One,');
|
71
|
+
});
|
72
|
+
it('selects an option on Space', async () => {
|
73
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
74
|
+
<glide-core-dropdown-option
|
75
|
+
label="One"
|
76
|
+
value="one"
|
77
|
+
></glide-core-dropdown-option>
|
78
|
+
</glide-core-dropdown>`);
|
79
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
80
|
+
option?.focus();
|
81
|
+
await sendKeys({ press: ' ' });
|
82
|
+
expect(option?.selected).to.be.true;
|
83
|
+
});
|
84
|
+
it('selects an option on Enter', async () => {
|
85
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
86
|
+
<glide-core-dropdown-option
|
87
|
+
label="One"
|
88
|
+
value="one"
|
89
|
+
></glide-core-dropdown-option>
|
90
|
+
</glide-core-dropdown>`);
|
91
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
92
|
+
option?.focus();
|
93
|
+
await sendKeys({ press: 'Enter' });
|
94
|
+
expect(option?.selected).to.be.true;
|
95
|
+
});
|
96
|
+
it('deactivates all other options on "mouseover"', async () => {
|
97
|
+
const component = await fixture(html `<glide-core-dropdown open>
|
98
|
+
<glide-core-dropdown-option
|
99
|
+
label="One"
|
100
|
+
value="one"
|
101
|
+
></glide-core-dropdown-option>
|
102
|
+
|
103
|
+
<glide-core-dropdown-option
|
104
|
+
label="Two"
|
105
|
+
value="two"
|
106
|
+
></glide-core-dropdown-option>
|
107
|
+
</glide-core-dropdown>`);
|
108
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
109
|
+
options[0]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
110
|
+
options[1]?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
111
|
+
expect(options[0]?.privateActive).to.be.false;
|
112
|
+
expect(options[1]?.privateActive).to.be.true;
|
113
|
+
});
|
114
|
+
it('closes when an option is selected via click', async () => {
|
115
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
116
|
+
<glide-core-dropdown-option
|
117
|
+
label="Label"
|
118
|
+
value="value"
|
119
|
+
></glide-core-dropdown-option>
|
120
|
+
</glide-core-dropdown>`);
|
121
|
+
component.querySelector('glide-core-dropdown-option')?.click();
|
122
|
+
expect(component.open).to.be.false;
|
123
|
+
});
|
124
|
+
it('closes when an option is selected via Enter', async () => {
|
125
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
126
|
+
<glide-core-dropdown-option
|
127
|
+
label="Label"
|
128
|
+
value="value"
|
129
|
+
></glide-core-dropdown-option>
|
130
|
+
</glide-core-dropdown>`);
|
131
|
+
component.querySelector('glide-core-dropdown-option')?.focus();
|
132
|
+
await sendKeys({ press: 'Enter' });
|
133
|
+
expect(component.open).to.be.false;
|
134
|
+
});
|
135
|
+
it('closes when an option is selected via Space', async () => {
|
136
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
137
|
+
<glide-core-dropdown-option
|
138
|
+
label="Label"
|
139
|
+
value="value"
|
140
|
+
></glide-core-dropdown-option>
|
141
|
+
</glide-core-dropdown>`);
|
142
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
143
|
+
option?.focus();
|
144
|
+
await sendKeys({ press: ' ' });
|
145
|
+
expect(component.open).to.be.false;
|
146
|
+
});
|
147
|
+
it('deselects all other options when one is newly selected', async () => {
|
148
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
149
|
+
<glide-core-dropdown-option
|
150
|
+
label="One"
|
151
|
+
value="one"
|
152
|
+
selected
|
153
|
+
></glide-core-dropdown-option>
|
154
|
+
|
155
|
+
<glide-core-dropdown-option
|
156
|
+
label="Two"
|
157
|
+
value="two"
|
158
|
+
></glide-core-dropdown-option>
|
159
|
+
|
160
|
+
<glide-core-dropdown-option
|
161
|
+
label="Three"
|
162
|
+
value="three"
|
163
|
+
></glide-core-dropdown-option>
|
164
|
+
</glide-core-dropdown>`);
|
165
|
+
component.shadowRoot
|
166
|
+
?.querySelector('[data-test="button"]')
|
167
|
+
?.dispatchEvent(new Event('click'));
|
168
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
169
|
+
options[1].click();
|
170
|
+
expect(options[0].selected).to.be.false;
|
171
|
+
expect(options[1].selected).to.be.true;
|
172
|
+
expect(options[2].selected).to.be.false;
|
173
|
+
});
|
174
|
+
it('selects and deselects options when `value` is changed programmatically', async () => {
|
175
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
176
|
+
<glide-core-dropdown-option
|
177
|
+
label="One"
|
178
|
+
value="one"
|
179
|
+
selected
|
180
|
+
></glide-core-dropdown-option>
|
181
|
+
|
182
|
+
<glide-core-dropdown-option
|
183
|
+
label="Two"
|
184
|
+
value="two"
|
185
|
+
></glide-core-dropdown-option>
|
186
|
+
</glide-core-dropdown>`);
|
187
|
+
component.value = ['two'];
|
188
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
189
|
+
expect(options[0].selected).to.be.false;
|
190
|
+
expect(options[1].selected).to.be.true;
|
191
|
+
});
|
192
|
+
it('throws when `value` is changed programmatically to include more than one value', async () => {
|
193
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
194
|
+
<glide-core-dropdown-option
|
195
|
+
label="One"
|
196
|
+
value="one"
|
197
|
+
></glide-core-dropdown-option>
|
198
|
+
|
199
|
+
<glide-core-dropdown-option
|
200
|
+
label="Two"
|
201
|
+
value="two"
|
202
|
+
></glide-core-dropdown-option>
|
203
|
+
</glide-core-dropdown>`);
|
204
|
+
const spy = sinon.spy();
|
205
|
+
try {
|
206
|
+
component.value = ['one', 'two'];
|
207
|
+
}
|
208
|
+
catch (error) {
|
209
|
+
if (error instanceof ArgumentError) {
|
210
|
+
spy();
|
211
|
+
}
|
212
|
+
}
|
213
|
+
expect(spy.called).to.be.true;
|
214
|
+
});
|
215
|
+
it('updates `value` when an option `value` is changed programmatically', async () => {
|
216
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
217
|
+
<glide-core-dropdown-option
|
218
|
+
label="One"
|
219
|
+
value="one"
|
220
|
+
selected
|
221
|
+
></glide-core-dropdown-option>
|
222
|
+
</glide-core-dropdown>`);
|
223
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
224
|
+
assert(option);
|
225
|
+
option.value = 'two';
|
226
|
+
expect(component.value).to.deep.equal(['two']);
|
227
|
+
});
|
228
|
+
it('updates `value` when an option is selected via click', async () => {
|
229
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
230
|
+
<glide-core-dropdown-option
|
231
|
+
label="One"
|
232
|
+
value="one"
|
233
|
+
></glide-core-dropdown-option>
|
234
|
+
|
235
|
+
<glide-core-dropdown-option
|
236
|
+
label="Two"
|
237
|
+
value="two"
|
238
|
+
></glide-core-dropdown-option>
|
239
|
+
|
240
|
+
<glide-core-dropdown-option label="Three"></glide-core-dropdown-option>
|
241
|
+
</glide-core-dropdown>`);
|
242
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
243
|
+
options[1].click();
|
244
|
+
expect(component.value).to.deep.equal(['two']);
|
245
|
+
// Reopen it.
|
246
|
+
component.shadowRoot
|
247
|
+
?.querySelector('[data-test="button"]')
|
248
|
+
?.dispatchEvent(new CustomEvent('click', { detail: 1 }));
|
249
|
+
// Wait for it to open.
|
250
|
+
await elementUpdated(component);
|
251
|
+
options[1].click();
|
252
|
+
expect(component.value).to.deep.equal(['two']);
|
253
|
+
// Reopen it.
|
254
|
+
component.shadowRoot
|
255
|
+
?.querySelector('[data-test="button"]')
|
256
|
+
?.dispatchEvent(new CustomEvent('click', { detail: 1 }));
|
257
|
+
// Wait for it to open.
|
258
|
+
await elementUpdated(component);
|
259
|
+
options[2].click();
|
260
|
+
expect(component.value).to.deep.equal([]);
|
261
|
+
});
|
262
|
+
it('updates `value` when an option is selected via Enter', async () => {
|
263
|
+
const component = await fixture(html `<glide-core-dropdown open>
|
264
|
+
<glide-core-dropdown-option
|
265
|
+
label="One"
|
266
|
+
value="one"
|
267
|
+
></glide-core-dropdown-option>
|
268
|
+
|
269
|
+
<glide-core-dropdown-option
|
270
|
+
label="Two"
|
271
|
+
value="two"
|
272
|
+
></glide-core-dropdown-option>
|
273
|
+
|
274
|
+
<glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
|
275
|
+
</glide-core-dropdown>`);
|
276
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
277
|
+
options[0].focus();
|
278
|
+
await sendKeys({ press: 'Enter' });
|
279
|
+
expect(component.value).to.deep.equal(['one']);
|
280
|
+
// Reopen it.
|
281
|
+
component.shadowRoot
|
282
|
+
?.querySelector('[data-test="button"]')
|
283
|
+
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
284
|
+
// Wait for it to open.
|
285
|
+
await elementUpdated(component);
|
286
|
+
options[1].focus();
|
287
|
+
await sendKeys({ press: 'Enter' });
|
288
|
+
expect(component.value).to.deep.equal(['two']);
|
289
|
+
// Reopen it.
|
290
|
+
component.shadowRoot
|
291
|
+
?.querySelector('[data-test="button"]')
|
292
|
+
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
293
|
+
// Wait for it to open.
|
294
|
+
await elementUpdated(component);
|
295
|
+
options[2].focus();
|
296
|
+
await sendKeys({ press: 'Enter' });
|
297
|
+
expect(component.value).to.deep.equal([]);
|
298
|
+
});
|
299
|
+
it('updates `value` when an option is selected via Space', async () => {
|
300
|
+
const component = await fixture(html `<glide-core-dropdown open>
|
301
|
+
<glide-core-dropdown-option
|
302
|
+
label="One"
|
303
|
+
value="one"
|
304
|
+
></glide-core-dropdown-option>
|
305
|
+
|
306
|
+
<glide-core-dropdown-option
|
307
|
+
label="Two"
|
308
|
+
value="two"
|
309
|
+
></glide-core-dropdown-option>
|
310
|
+
|
311
|
+
<glide-core-dropdown-option label="Three"></glide-core-dropdown-option>
|
312
|
+
</glide-core-dropdown>`);
|
313
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
314
|
+
options[0].focus();
|
315
|
+
await sendKeys({ press: ' ' });
|
316
|
+
expect(component.value).to.deep.equal(['one']);
|
317
|
+
// Reopen it.
|
318
|
+
component.shadowRoot
|
319
|
+
?.querySelector('[data-test="button"]')
|
320
|
+
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
321
|
+
// Wait for it to open.
|
322
|
+
await elementUpdated(component);
|
323
|
+
options[1].focus();
|
324
|
+
await sendKeys({ press: ' ' });
|
325
|
+
expect(component.value).to.deep.equal(['two']);
|
326
|
+
// Reopen it.
|
327
|
+
component.shadowRoot
|
328
|
+
?.querySelector('[data-test="button"]')
|
329
|
+
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
330
|
+
// Wait for it to open.
|
331
|
+
await elementUpdated(component);
|
332
|
+
options[2].focus();
|
333
|
+
await sendKeys({ press: ' ' });
|
334
|
+
expect(component.value).to.deep.equal([]);
|
335
|
+
});
|
336
|
+
it('updates `value` when `multiple` is changed to `false` programmatically', async () => {
|
337
|
+
const component = await fixture(html `<glide-core-dropdown open multiple>
|
338
|
+
<glide-core-dropdown-option
|
339
|
+
label="One"
|
340
|
+
value="one"
|
341
|
+
selected
|
342
|
+
></glide-core-dropdown-option>
|
343
|
+
|
344
|
+
<glide-core-dropdown-option
|
345
|
+
label="Two"
|
346
|
+
value="two"
|
347
|
+
selected
|
348
|
+
></glide-core-dropdown-option>
|
349
|
+
</glide-core-dropdown>`);
|
350
|
+
component.multiple = false;
|
351
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
352
|
+
const checkbox = options[1].shadowRoot?.querySelector('[data-test="checkbox"]');
|
353
|
+
expect(options[0].selected).to.be.false;
|
354
|
+
expect(options[1].selected).to.be.true;
|
355
|
+
expect(checkbox?.checked).to.be.true;
|
356
|
+
expect(component.value).to.deep.equal(['two']);
|
357
|
+
});
|
358
|
+
it('updates `value` when the `value` of the selected option is changed programmatically', async () => {
|
359
|
+
const component = await fixture(html `<glide-core-dropdown open>
|
360
|
+
<glide-core-dropdown-option
|
361
|
+
label="One"
|
362
|
+
value="one"
|
363
|
+
selected
|
364
|
+
></glide-core-dropdown-option>
|
365
|
+
|
366
|
+
<glide-core-dropdown-option
|
367
|
+
label="Two"
|
368
|
+
value="two"
|
369
|
+
></glide-core-dropdown-option>
|
370
|
+
</glide-core-dropdown>`);
|
371
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
372
|
+
assert(option);
|
373
|
+
option.value = 'three';
|
374
|
+
expect(component.value).to.deep.equal(['three']);
|
375
|
+
});
|
376
|
+
it('updates `value` when the `value` of the selected option is removed programmatically', async () => {
|
377
|
+
const component = await fixture(html `<glide-core-dropdown open>
|
378
|
+
<glide-core-dropdown-option
|
379
|
+
label="One"
|
380
|
+
value="one"
|
381
|
+
selected
|
382
|
+
></glide-core-dropdown-option>
|
383
|
+
|
384
|
+
<glide-core-dropdown-option
|
385
|
+
label="Two"
|
386
|
+
value="two"
|
387
|
+
></glide-core-dropdown-option>
|
388
|
+
</glide-core-dropdown>`);
|
389
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
390
|
+
assert(option);
|
391
|
+
option.value = '';
|
392
|
+
expect(component.value).to.deep.equal([]);
|
393
|
+
});
|
394
|
+
it('updates the its internal label when an option is newly selected', async () => {
|
395
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
396
|
+
<glide-core-dropdown-option
|
397
|
+
label="One"
|
398
|
+
value="one"
|
399
|
+
></glide-core-dropdown-option>
|
400
|
+
|
401
|
+
<glide-core-dropdown-option
|
402
|
+
label="Two"
|
403
|
+
value="two"
|
404
|
+
></glide-core-dropdown-option>
|
405
|
+
</glide-core-dropdown>`);
|
406
|
+
const option = component.querySelector('glide-core-dropdown-option:last-of-type');
|
407
|
+
option?.click();
|
408
|
+
await elementUpdated(component);
|
409
|
+
const label = component.shadowRoot?.querySelector('[data-test="internal-label"]');
|
410
|
+
expect(label?.textContent?.trim()).to.equal(option?.label);
|
411
|
+
});
|
412
|
+
it('hides Select All', async () => {
|
413
|
+
const component = await fixture(html `<glide-core-dropdown
|
414
|
+
label="Label"
|
415
|
+
placeholder="Placeholder"
|
416
|
+
select-all
|
417
|
+
>
|
418
|
+
<glide-core-dropdown-option
|
419
|
+
label="One"
|
420
|
+
value="one"
|
421
|
+
selected
|
422
|
+
></glide-core-dropdown-option>
|
423
|
+
|
424
|
+
<glide-core-dropdown-option
|
425
|
+
label="Two"
|
426
|
+
value="two"
|
427
|
+
></glide-core-dropdown-option>
|
428
|
+
</glide-core-dropdown>`);
|
429
|
+
const selectAll = component.shadowRoot?.querySelector('[data-test="select-all"]');
|
430
|
+
expect(selectAll?.checkVisibility()).to.not.be.ok;
|
431
|
+
});
|
432
|
+
it('does not select an option on Enter when the option is not focused', async () => {
|
433
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
434
|
+
<glide-core-dropdown-option
|
435
|
+
label="One"
|
436
|
+
value="one"
|
437
|
+
></glide-core-dropdown-option>
|
438
|
+
|
439
|
+
<glide-core-dropdown-option
|
440
|
+
label="Two"
|
441
|
+
value="two"
|
442
|
+
></glide-core-dropdown-option>
|
443
|
+
</glide-core-dropdown>`);
|
444
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
445
|
+
option?.focus();
|
446
|
+
await sendKeys({ down: 'Tab' });
|
447
|
+
await sendKeys({ down: 'Shift' });
|
448
|
+
await sendKeys({ up: 'Tab' });
|
449
|
+
await sendKeys({ press: 'Enter' });
|
450
|
+
expect(option?.selected).to.be.false;
|
451
|
+
});
|
452
|
+
it('cannot be tabbed to when `disabled`', async () => {
|
453
|
+
await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" disabled>
|
454
|
+
<glide-core-dropdown-option
|
455
|
+
label="One"
|
456
|
+
value="one"
|
457
|
+
></glide-core-dropdown-option>
|
458
|
+
|
459
|
+
<glide-core-dropdown-option
|
460
|
+
label="Two"
|
461
|
+
value="two"
|
462
|
+
></glide-core-dropdown-option>
|
463
|
+
</glide-core-dropdown>`);
|
464
|
+
await sendKeys({ down: 'Tab' });
|
465
|
+
expect(document.activeElement).to.equal(document.body);
|
466
|
+
});
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import './dropdown.option.js';
|
2
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
3
|
+
import GlideCoreDropdown from './dropdown.js';
|
4
|
+
GlideCoreDropdown.shadowRootOptions.mode = 'open';
|
5
|
+
it('is valid if not required and no option is selected', async () => {
|
6
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
7
|
+
<glide-core-dropdown-option
|
8
|
+
label="Label"
|
9
|
+
value="value"
|
10
|
+
selected
|
11
|
+
></glide-core-dropdown-option>
|
12
|
+
</glide-core-dropdown>`);
|
13
|
+
expect(component.validity.valid).to.be.true;
|
14
|
+
expect(component.validity?.valueMissing).to.be.false;
|
15
|
+
expect(component.checkValidity()).to.be.true;
|
16
|
+
expect(component.reportValidity()).to.be.true;
|
17
|
+
});
|
18
|
+
it('is invalid if required and no option is selected', async () => {
|
19
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
|
20
|
+
<glide-core-dropdown-option
|
21
|
+
label="Label"
|
22
|
+
value="value"
|
23
|
+
></glide-core-dropdown-option>
|
24
|
+
</glide-core-dropdown>`);
|
25
|
+
expect(component.validity.valid).to.be.false;
|
26
|
+
expect(component.validity?.valueMissing).to.be.true;
|
27
|
+
expect(component.checkValidity()).to.be.false;
|
28
|
+
expect(component.reportValidity()).to.be.false;
|
29
|
+
});
|
30
|
+
it('is both invalid and valid if required but disabled and no option is selected', async () => {
|
31
|
+
const component = await fixture(html `<glide-core-dropdown
|
32
|
+
label="Label"
|
33
|
+
placeholder="Placeholder"
|
34
|
+
disabled
|
35
|
+
required
|
36
|
+
>
|
37
|
+
<glide-core-dropdown-option
|
38
|
+
label="Label"
|
39
|
+
value="value"
|
40
|
+
></glide-core-dropdown-option>
|
41
|
+
</glide-core-dropdown>`);
|
42
|
+
expect(component.validity.valid).to.be.false;
|
43
|
+
expect(component.validity?.valueMissing).to.be.true;
|
44
|
+
expect(component.checkValidity()).to.be.true;
|
45
|
+
expect(component.reportValidity()).to.be.true;
|
46
|
+
});
|
package/dist/icon-button.d.ts
CHANGED
@@ -11,8 +11,9 @@ export default class GlideCoreIconButton extends LitElement {
|
|
11
11
|
#private;
|
12
12
|
static shadowRootOptions: ShadowRootInit;
|
13
13
|
static styles: import("lit").CSSResult[];
|
14
|
-
|
15
|
-
|
14
|
+
ariaControls: string | null;
|
15
|
+
ariaExpanded: 'true' | 'false' | null;
|
16
|
+
ariaHasPopup: 'true' | 'false' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | null;
|
16
17
|
disabled: boolean;
|
17
18
|
/** Text read aloud for screenreaders. For accessibility, this should always be provided. */
|
18
19
|
label: string;
|
package/dist/icon-button.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var __decorate=this&&this.__decorate||function(t,e,o,r){var i,a=arguments.length,l=a<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(t,e,o,r);else for(var n=t.length-1;n>=0;n--)(i=t[n])&&(l=(a<3?i(l):a>3?i(e,o,l):i(e,o))||l);return a>3&&l&&Object.defineProperty(e,o,l),l};import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{owSlot}from"./library/ow.js";import styles from"./icon-button.styles.js";let GlideCoreIconButton=class GlideCoreIconButton extends LitElement{constructor(){super(...arguments),this.ariaControls=null,this.ariaExpanded=null,this.ariaHasPopup=null,this.disabled=!1,this.label="",this.variant="primary",this.#t=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#t.value)}render(){return html`<button aria-controls="${ifDefined(this.ariaControls??void 0)}" aria-expanded="${ifDefined(this.ariaExpanded??void 0)}" aria-haspopup="${ifDefined(this.ariaHasPopup??void 0)}" aria-label="${this.label}" class="${classMap({component:!0,primary:"primary"===this.variant,secondary:"secondary"===this.variant,tertiary:"tertiary"===this.variant})}" type="button" ?disabled="${this.disabled}"><slot @slotchange="${this.#e}" ${ref(this.#t)}></slot></button>`}#t;#e(){owSlot(this.#t.value)}};__decorate([property({attribute:"aria-controls",reflect:!0})],GlideCoreIconButton.prototype,"ariaControls",void 0),__decorate([property({attribute:"aria-expanded",reflect:!0})],GlideCoreIconButton.prototype,"ariaExpanded",void 0),__decorate([property({attribute:"aria-haspopup",reflect:!0})],GlideCoreIconButton.prototype,"ariaHasPopup",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreIconButton.prototype,"disabled",void 0),__decorate([property()],GlideCoreIconButton.prototype,"label",void 0),__decorate([property({reflect:!0})],GlideCoreIconButton.prototype,"variant",void 0),GlideCoreIconButton=__decorate([customElement("glide-core-icon-button")],GlideCoreIconButton);export default GlideCoreIconButton;
|
@@ -1,14 +1,14 @@
|
|
1
|
-
|
1
|
+
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
|
2
2
|
:host {
|
3
3
|
/* Contains elements with "padding" and "width". Inline by default. */
|
4
|
-
display: inline-
|
4
|
+
display: inline-flex;
|
5
5
|
}
|
6
6
|
|
7
7
|
.component {
|
8
8
|
align-items: center;
|
9
9
|
block-size: var(--size, 1.625rem);
|
10
10
|
border-color: transparent;
|
11
|
-
border-radius:
|
11
|
+
border-radius: 0.5rem;
|
12
12
|
border-style: solid;
|
13
13
|
border-width: 1px;
|
14
14
|
cursor: pointer;
|
@@ -25,12 +25,11 @@
|
|
25
25
|
}
|
26
26
|
|
27
27
|
&:focus-visible {
|
28
|
-
${
|
29
|
-
outline-offset: 3px;
|
28
|
+
${focusOutline};
|
30
29
|
}
|
31
30
|
|
32
31
|
&:disabled {
|
33
|
-
cursor:
|
32
|
+
cursor: not-allowed;
|
34
33
|
opacity: 1;
|
35
34
|
}
|
36
35
|
|
@@ -61,12 +60,11 @@
|
|
61
60
|
|
62
61
|
&.secondary {
|
63
62
|
background-color: var(--glide-core-surface-page);
|
64
|
-
border-color:
|
65
|
-
color: var(--icon-color, var(--glide-core-icon-
|
63
|
+
border-color: transparent;
|
64
|
+
color: var(--icon-color, var(--glide-core-icon-default));
|
66
65
|
|
67
66
|
&:disabled {
|
68
67
|
background-color: transparent;
|
69
|
-
border-color: var(--glide-core-border-base-light);
|
70
68
|
color: var(--glide-core-icon-tertiary-disabled);
|
71
69
|
}
|
72
70
|
|
@@ -79,18 +77,20 @@
|
|
79
77
|
&:not(:active):hover:not(:disabled) {
|
80
78
|
background-color: var(--glide-core-surface-hover);
|
81
79
|
border-color: transparent;
|
82
|
-
box-shadow: var(--glide-core-glow-sm);
|
83
80
|
color: var(--glide-core-icon-primary);
|
84
81
|
}
|
85
82
|
}
|
86
83
|
|
87
84
|
&.tertiary {
|
88
85
|
background-color: transparent;
|
86
|
+
block-size: var(--size, 1rem);
|
89
87
|
border-color: transparent;
|
90
88
|
color: var(--icon-color, var(--glide-core-icon-default));
|
89
|
+
inline-size: var(--size, 1rem);
|
90
|
+
padding: 0;
|
91
91
|
|
92
92
|
&:focus-visible {
|
93
|
-
|
93
|
+
border-radius: 0.0625rem;
|
94
94
|
}
|
95
95
|
|
96
96
|
&:disabled {
|
@@ -109,4 +109,4 @@
|
|
109
109
|
}
|
110
110
|
}
|
111
111
|
}
|
112
|
-
`];
|
112
|
+
`];
|