@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,59 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreDropdownOption from './dropdown.option.js';
|
3
|
+
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
4
|
+
it('registers', async () => {
|
5
|
+
expect(window.customElements.get('glide-core-dropdown-option')).to.equal(GlideCoreDropdownOption);
|
6
|
+
});
|
7
|
+
it('has defaults', async () => {
|
8
|
+
// Required attributes are supplied and not asserted below. The idea is that
|
9
|
+
// this test shouldn't fail to typecheck if these templates are eventually
|
10
|
+
// typechecked, which means supplying required attributes and slots.
|
11
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
12
|
+
label="Label"
|
13
|
+
></glide-core-dropdown-option>`);
|
14
|
+
expect(component.privateMultiple).to.equal(false);
|
15
|
+
expect(component.getAttribute('private-multiple')).to.equal(null);
|
16
|
+
expect(component.privateSize).to.equal('large');
|
17
|
+
expect(component.getAttribute('private-size')).to.equal('large');
|
18
|
+
// None are reflected, so no attribute assertions are necessary.
|
19
|
+
expect(component.privateActive).to.equal(false);
|
20
|
+
expect(component.privateIndeterminate).to.equal(false);
|
21
|
+
expect(component.selected).to.equal(false);
|
22
|
+
expect(component.value).to.equal('');
|
23
|
+
});
|
24
|
+
it('can have a label', async () => {
|
25
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
26
|
+
label="Label"
|
27
|
+
value="value"
|
28
|
+
></glide-core-dropdown-option>`);
|
29
|
+
expect(component.shadowRoot?.textContent?.trim()).to.equal('Label');
|
30
|
+
});
|
31
|
+
it('can have an icon', async () => {
|
32
|
+
const component = await fixture(html `<glide-core-dropdown-option label="Label" value="value">
|
33
|
+
<svg slot="icon" width="16" height="16" viewBox="0 0 24 24" fill="none">
|
34
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" />
|
35
|
+
|
36
|
+
<path
|
37
|
+
d="M12 16L12 12"
|
38
|
+
stroke="currentColor"
|
39
|
+
stroke-width="2"
|
40
|
+
stroke-linecap="round"
|
41
|
+
/>
|
42
|
+
|
43
|
+
<circle cx="12" cy="8" r="1" fill="currentColor" />
|
44
|
+
</svg>
|
45
|
+
</glide-core-dropdown-option>`);
|
46
|
+
const icon = component?.shadowRoot
|
47
|
+
?.querySelector('slot[name="icon"]')
|
48
|
+
?.assignedElements()
|
49
|
+
.at(0);
|
50
|
+
expect(icon instanceof SVGElement).to.be.true;
|
51
|
+
});
|
52
|
+
it('can have a value', async () => {
|
53
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
54
|
+
label="Label"
|
55
|
+
value="value"
|
56
|
+
></glide-core-dropdown-option>`);
|
57
|
+
expect(component.getAttribute('value')).to.equal('value');
|
58
|
+
expect(component.value).to.equal('value');
|
59
|
+
});
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreDropdownOption from './dropdown.option.js';
|
3
|
+
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
4
|
+
it('is selected when initially selected', async () => {
|
5
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
6
|
+
label="Label"
|
7
|
+
value="value"
|
8
|
+
private-multiple
|
9
|
+
selected
|
10
|
+
></glide-core-dropdown-option>`);
|
11
|
+
const checkbox = component.shadowRoot?.querySelector('glide-core-checkbox');
|
12
|
+
expect(component.selected).to.be.true;
|
13
|
+
expect(component.ariaSelected).to.equal('true');
|
14
|
+
expect(checkbox?.checked).to.be.true;
|
15
|
+
});
|
16
|
+
it('is deselected when initially deselected', async () => {
|
17
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
18
|
+
label="Label"
|
19
|
+
value="value"
|
20
|
+
private-multiple
|
21
|
+
></glide-core-dropdown-option>`);
|
22
|
+
const checkbox = component.shadowRoot?.querySelector('glide-core-checkbox');
|
23
|
+
expect(component.selected).to.be.false;
|
24
|
+
expect(component.ariaSelected).to.equal('false');
|
25
|
+
expect(checkbox?.checked).to.be.false;
|
26
|
+
});
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreDropdownOption from './dropdown.option.js';
|
3
|
+
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
4
|
+
it('is selected when initially selected', async () => {
|
5
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
6
|
+
label="Label"
|
7
|
+
value="value"
|
8
|
+
selected
|
9
|
+
></glide-core-dropdown-option>`);
|
10
|
+
expect(component.selected).to.be.true;
|
11
|
+
expect(component.ariaSelected).to.equal('true');
|
12
|
+
});
|
13
|
+
it('is deselected when initially deselected', async () => {
|
14
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
15
|
+
label="Label"
|
16
|
+
value="value"
|
17
|
+
></glide-core-dropdown-option>`);
|
18
|
+
expect(component.selected).to.be.false;
|
19
|
+
expect(component.ariaSelected).to.equal('false');
|
20
|
+
});
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { expect, fixture, html, oneEvent } from '@open-wc/testing';
|
2
|
+
import GlideCoreDropdownOption from './dropdown.option.js';
|
3
|
+
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
4
|
+
it('dispatches a "private-selected-change" event', async () => {
|
5
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
6
|
+
label="Label"
|
7
|
+
value="value"
|
8
|
+
></glide-core-dropdown-option>`);
|
9
|
+
setTimeout(() => {
|
10
|
+
component.click();
|
11
|
+
});
|
12
|
+
const event = await oneEvent(component, 'private-selected-change');
|
13
|
+
expect(event instanceof Event).to.be.true;
|
14
|
+
expect(event.bubbles).to.be.true;
|
15
|
+
});
|
16
|
+
it('dispatches a "private-value-change" event', async () => {
|
17
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
18
|
+
label="Label"
|
19
|
+
value="value"
|
20
|
+
></glide-core-dropdown-option>`);
|
21
|
+
setTimeout(() => {
|
22
|
+
component.value = '';
|
23
|
+
});
|
24
|
+
const event = await oneEvent(component, 'private-value-change');
|
25
|
+
expect(event instanceof Event).to.be.true;
|
26
|
+
expect(event.bubbles).to.be.true;
|
27
|
+
});
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreDropdownOption from './dropdown.option.js';
|
3
|
+
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
4
|
+
it('focuses itself when `focus` is called', async () => {
|
5
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
6
|
+
label="Label"
|
7
|
+
value="value"
|
8
|
+
></glide-core-dropdown-option>`);
|
9
|
+
component.focus();
|
10
|
+
expect(document.activeElement).to.equal(component);
|
11
|
+
});
|
@@ -0,0 +1,82 @@
|
|
1
|
+
import { elementUpdated, expect, fixture, html, waitUntil, } from '@open-wc/testing';
|
2
|
+
import GlideCoreCheckbox from './checkbox.js';
|
3
|
+
import GlideCoreDropdownOption from './dropdown.option.js';
|
4
|
+
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
5
|
+
it('is selected on click', async () => {
|
6
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
7
|
+
label="Label"
|
8
|
+
private-multiple
|
9
|
+
></glide-core-dropdown-option>`);
|
10
|
+
component.click();
|
11
|
+
await elementUpdated(component);
|
12
|
+
expect(component.selected).to.be.true;
|
13
|
+
expect(component.ariaSelected).to.equal('true');
|
14
|
+
});
|
15
|
+
it('is deselected on click', async () => {
|
16
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
17
|
+
label="Label"
|
18
|
+
private-multiple
|
19
|
+
selected
|
20
|
+
></glide-core-dropdown-option>`);
|
21
|
+
component.click();
|
22
|
+
await elementUpdated(component);
|
23
|
+
expect(component.selected).to.be.false;
|
24
|
+
expect(component.ariaSelected).to.equal('false');
|
25
|
+
});
|
26
|
+
it('is selected on click when the checkbox itself is clicked', async () => {
|
27
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
28
|
+
label="Label"
|
29
|
+
private-multiple
|
30
|
+
></glide-core-dropdown-option>`);
|
31
|
+
const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
|
32
|
+
checkbox?.click();
|
33
|
+
await elementUpdated(component);
|
34
|
+
expect(component.selected).to.be.true;
|
35
|
+
expect(component.ariaSelected).to.equal('true');
|
36
|
+
expect(checkbox?.checked).to.be.true;
|
37
|
+
});
|
38
|
+
it('is deselected on click when the checkbox itself is clicked', async () => {
|
39
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
40
|
+
label="Label"
|
41
|
+
private-multiple
|
42
|
+
selected
|
43
|
+
></glide-core-dropdown-option>`);
|
44
|
+
// Checkbox has its own lifecycle. Wait until it's ready.
|
45
|
+
await waitUntil(() => {
|
46
|
+
return (component.shadowRoot?.querySelector('[data-test="checkbox"]') instanceof
|
47
|
+
GlideCoreCheckbox);
|
48
|
+
});
|
49
|
+
const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
|
50
|
+
checkbox?.click();
|
51
|
+
await elementUpdated(component);
|
52
|
+
expect(component.selected).to.be.false;
|
53
|
+
expect(component.ariaSelected).to.equal('false');
|
54
|
+
expect(checkbox?.checked).to.be.false;
|
55
|
+
});
|
56
|
+
it('is selected when programmatically selected', async () => {
|
57
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
58
|
+
label="Label"
|
59
|
+
value="value"
|
60
|
+
private-multiple
|
61
|
+
></glide-core-dropdown-option>`);
|
62
|
+
component.selected = true;
|
63
|
+
await elementUpdated(component);
|
64
|
+
const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
|
65
|
+
expect(component.selected).to.be.true;
|
66
|
+
expect(component.ariaSelected).to.equal('true');
|
67
|
+
expect(checkbox?.checked).to.be.true;
|
68
|
+
});
|
69
|
+
it('is deselected when programmatically deselected', async () => {
|
70
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
71
|
+
label="Label"
|
72
|
+
value="value"
|
73
|
+
private-multiple
|
74
|
+
selected
|
75
|
+
></glide-core-dropdown-option>`);
|
76
|
+
component.selected = false;
|
77
|
+
await elementUpdated(component);
|
78
|
+
const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
|
79
|
+
expect(component.selected).to.be.false;
|
80
|
+
expect(component.ariaSelected).to.equal('false');
|
81
|
+
expect(checkbox?.checked).to.be.false;
|
82
|
+
});
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreDropdownOption from './dropdown.option.js';
|
3
|
+
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
4
|
+
it('is selected on click', async () => {
|
5
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
6
|
+
label="Label"
|
7
|
+
></glide-core-dropdown-option>`);
|
8
|
+
component.click();
|
9
|
+
await elementUpdated(component);
|
10
|
+
expect(component.selected).to.be.true;
|
11
|
+
expect(component.ariaSelected).to.equal('true');
|
12
|
+
});
|
13
|
+
it('is selected when programmatically selected', async () => {
|
14
|
+
const component = await fixture(html `<glide-core-dropdown-option
|
15
|
+
label="Label"
|
16
|
+
value="value"
|
17
|
+
></glide-core-dropdown-option>`);
|
18
|
+
component.selected = true;
|
19
|
+
await elementUpdated(component);
|
20
|
+
expect(component.selected).to.be.true;
|
21
|
+
expect(component.ariaSelected).to.equal('true');
|
22
|
+
});
|
package/dist/dropdown.styles.js
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
|
1
|
+
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
|
2
2
|
.component {
|
3
3
|
--min-inline-size: 9.375rem;
|
4
4
|
|
5
5
|
font-family: var(--glide-core-font-sans);
|
6
6
|
}
|
7
7
|
|
8
|
+
.selected-option-labels {
|
9
|
+
${visuallyHidden};
|
10
|
+
}
|
11
|
+
|
8
12
|
.dropdown-and-options {
|
9
13
|
display: flex;
|
10
14
|
position: relative;
|
@@ -14,6 +18,7 @@
|
|
14
18
|
--button-and-input-height: 1.25rem;
|
15
19
|
|
16
20
|
align-items: center;
|
21
|
+
background-color: var(--glide-core-surface-base-lighter);
|
17
22
|
block-size: 2.125rem;
|
18
23
|
border: 1px solid var(--glide-core-border-base-lighter);
|
19
24
|
border-radius: var(--glide-core-spacing-xs);
|
@@ -46,7 +51,7 @@
|
|
46
51
|
}
|
47
52
|
|
48
53
|
&.disabled {
|
49
|
-
background: var(--glide-core-surface-
|
54
|
+
background: var(--glide-core-surface-disabled);
|
50
55
|
color: var(--glide-core-text-tertiary-disabled);
|
51
56
|
}
|
52
57
|
|
@@ -55,15 +60,20 @@
|
|
55
60
|
color: var(--glide-core-status-error);
|
56
61
|
}
|
57
62
|
|
63
|
+
&.readonly {
|
64
|
+
border-color: transparent;
|
65
|
+
padding-inline-start: 0;
|
66
|
+
}
|
67
|
+
|
58
68
|
&:has(.button:focus-visible, .input:focus-visible) {
|
59
|
-
${
|
69
|
+
${focusOutline};
|
60
70
|
}
|
61
71
|
|
62
|
-
&:hover:not(&.error, &.disabled) {
|
72
|
+
&:hover:not(&.error, &.disabled, &.readonly) {
|
63
73
|
border-color: var(--glide-core-border-base);
|
64
74
|
}
|
65
75
|
|
66
|
-
&.quiet:hover:not(&.error, &.disabled, &.multiple) {
|
76
|
+
&.quiet:hover:not(&.error, &.disabled, &.multiple, &.readonly) {
|
67
77
|
background-color: var(--glide-core-surface-hover);
|
68
78
|
}
|
69
79
|
}
|
@@ -130,6 +140,7 @@
|
|
130
140
|
background: none;
|
131
141
|
block-size: var(--button-and-input-height);
|
132
142
|
border: none;
|
143
|
+
cursor: inherit;
|
133
144
|
display: flex;
|
134
145
|
padding: 0;
|
135
146
|
|
@@ -139,8 +150,10 @@
|
|
139
150
|
}
|
140
151
|
|
141
152
|
.input {
|
153
|
+
background-color: transparent;
|
142
154
|
block-size: var(--button-and-input-height);
|
143
155
|
border: none;
|
156
|
+
cursor: inherit;
|
144
157
|
font-size: inherit;
|
145
158
|
min-inline-size: var(--min-inline-size);
|
146
159
|
padding: 0;
|
@@ -159,4 +172,11 @@
|
|
159
172
|
font-family: var(--glide-core-font-sans);
|
160
173
|
}
|
161
174
|
}
|
162
|
-
|
175
|
+
|
176
|
+
.caret-icon {
|
177
|
+
&.disabled,
|
178
|
+
&.readonly {
|
179
|
+
color: var(--glide-core-surface-selected-disabled);
|
180
|
+
}
|
181
|
+
}
|
182
|
+
`];
|
@@ -0,0 +1,84 @@
|
|
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
|
+
const defaultSlot = html `
|
6
|
+
<glide-core-dropdown-option
|
7
|
+
label="One"
|
8
|
+
value="one"
|
9
|
+
></glide-core-dropdown-option>
|
10
|
+
|
11
|
+
<glide-core-dropdown-option
|
12
|
+
label="Two"
|
13
|
+
value="two"
|
14
|
+
></glide-core-dropdown-option>
|
15
|
+
|
16
|
+
<glide-core-dropdown-option
|
17
|
+
label="Three"
|
18
|
+
value="three"
|
19
|
+
></glide-core-dropdown-option>
|
20
|
+
|
21
|
+
<glide-core-dropdown-option
|
22
|
+
label="Four"
|
23
|
+
value="four"
|
24
|
+
></glide-core-dropdown-option>
|
25
|
+
|
26
|
+
<glide-core-dropdown-option
|
27
|
+
label="Five"
|
28
|
+
value="five"
|
29
|
+
></glide-core-dropdown-option>
|
30
|
+
|
31
|
+
<glide-core-dropdown-option
|
32
|
+
label="Six"
|
33
|
+
value="six"
|
34
|
+
></glide-core-dropdown-option>
|
35
|
+
|
36
|
+
<glide-core-dropdown-option
|
37
|
+
label="Seven"
|
38
|
+
value="seven"
|
39
|
+
></glide-core-dropdown-option>
|
40
|
+
|
41
|
+
<glide-core-dropdown-option
|
42
|
+
label="Eight"
|
43
|
+
value="eight"
|
44
|
+
></glide-core-dropdown-option>
|
45
|
+
|
46
|
+
<glide-core-dropdown-option
|
47
|
+
label="Nine"
|
48
|
+
value="nine"
|
49
|
+
></glide-core-dropdown-option>
|
50
|
+
|
51
|
+
<glide-core-dropdown-option
|
52
|
+
label="Ten"
|
53
|
+
value="ten"
|
54
|
+
></glide-core-dropdown-option>
|
55
|
+
|
56
|
+
<glide-core-dropdown-option
|
57
|
+
label="Eleven"
|
58
|
+
value="eleven"
|
59
|
+
></glide-core-dropdown-option>
|
60
|
+
`;
|
61
|
+
it('is accessible', async () => {
|
62
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
|
63
|
+
${defaultSlot}
|
64
|
+
</glide-core-dropdown>`);
|
65
|
+
await expect(component).to.be.accessible({
|
66
|
+
// Axe doesn't search within slots when determining whether an element
|
67
|
+
// has an ID that matches `aria-activedescendant` exists.
|
68
|
+
ignoredRules: ['aria-valid-attr-value'],
|
69
|
+
});
|
70
|
+
});
|
71
|
+
it('is filterable', async () => {
|
72
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
|
73
|
+
${defaultSlot}
|
74
|
+
</glide-core-dropdown>`);
|
75
|
+
const input = component.shadowRoot?.querySelector('[data-test="input"]');
|
76
|
+
expect(input?.checkVisibility()).to.be.true;
|
77
|
+
});
|
78
|
+
it('uses `placeholder` as a placeholder when not `multiple` and no option is selected', async () => {
|
79
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
80
|
+
${defaultSlot}
|
81
|
+
</glide-core-dropdown>`);
|
82
|
+
const input = component.shadowRoot?.querySelector('[data-test="input"]');
|
83
|
+
expect(input?.placeholder).to.equal('Placeholder');
|
84
|
+
});
|
@@ -0,0 +1,233 @@
|
|
1
|
+
import './dropdown.option.js';
|
2
|
+
import { ArgumentError } from 'ow';
|
3
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
4
|
+
import { repeat } from 'lit/directives/repeat.js';
|
5
|
+
import GlideCoreDropdown from './dropdown.js';
|
6
|
+
import expectArgumentError from './library/expect-argument-error.js';
|
7
|
+
import sinon from 'sinon';
|
8
|
+
// You'll notice quite a few duplicated tests among the "*.single.ts", "*.multiple.ts",
|
9
|
+
// and "*.filterable.ts" test suites. The thinking is that a test warrants
|
10
|
+
// duplication whenever Dropdown's internal logic isn't shared among all three
|
11
|
+
// of those states or if one state goes down a significantly different code path.
|
12
|
+
//
|
13
|
+
// There are still gaps. And there are exceptions to avoid excessive duplication
|
14
|
+
// for the sake of organization. Many of the tests in `dropdown.test.interactions.ts`,
|
15
|
+
// for example, don't apply to the filterable case and so aren't common among all
|
16
|
+
// three states. They nonetheless reside there because moving them out and
|
17
|
+
// duplicating them in both `dropdown.test.interactions.single.ts` and
|
18
|
+
// `dropdown.test.interactions.multiple.ts` would add a ton of test weight.
|
19
|
+
GlideCoreDropdown.shadowRootOptions.mode = 'open';
|
20
|
+
it('registers', async () => {
|
21
|
+
expect(window.customElements.get('glide-core-dropdown')).to.equal(GlideCoreDropdown);
|
22
|
+
});
|
23
|
+
it('has defaults', async () => {
|
24
|
+
// Required attributes are supplied here and thus left unasserted below. The
|
25
|
+
// idea is that this test shouldn't fail to typecheck if these templates are
|
26
|
+
// eventually typechecked, which means supplying all required attributes and slots.
|
27
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
28
|
+
<glide-core-dropdown-option
|
29
|
+
label="Label"
|
30
|
+
value="value"
|
31
|
+
></glide-core-dropdown-option>
|
32
|
+
</glide-core-dropdown>`);
|
33
|
+
expect(component.hasAttribute('disabled')).to.be.false;
|
34
|
+
expect(component.disabled).to.equal(false);
|
35
|
+
expect(component.getAttribute('name')).to.be.null;
|
36
|
+
expect(component.name).to.equal(undefined);
|
37
|
+
expect(component.hasAttribute('required')).to.be.false;
|
38
|
+
expect(component.required).to.equal(false);
|
39
|
+
expect(component.getAttribute('size')).to.equal('large');
|
40
|
+
expect(component.size).to.equal('large');
|
41
|
+
// Not reflected, so no attribute assertion is necessary.
|
42
|
+
expect(component.value).to.deep.equal([]);
|
43
|
+
});
|
44
|
+
it('can have a label', async () => {
|
45
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
46
|
+
<glide-core-dropdown-option
|
47
|
+
label="Label"
|
48
|
+
value="value"
|
49
|
+
></glide-core-dropdown-option>
|
50
|
+
</glide-core-dropdown>`);
|
51
|
+
expect(component.getAttribute('label')).to.equal('Label');
|
52
|
+
expect(component.label).to.equal('Label');
|
53
|
+
});
|
54
|
+
it('can have a placeholder', async () => {
|
55
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
56
|
+
<glide-core-dropdown-option
|
57
|
+
label="Label"
|
58
|
+
value="value"
|
59
|
+
></glide-core-dropdown-option>
|
60
|
+
</glide-core-dropdown>`);
|
61
|
+
expect(component.getAttribute('placeholder')).to.equal('Placeholder');
|
62
|
+
expect(component.placeholder).to.equal('Placeholder');
|
63
|
+
});
|
64
|
+
it('can have a description', async () => {
|
65
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
66
|
+
<div slot="description">Description</div>
|
67
|
+
<glide-core-dropdown-option
|
68
|
+
label="Label"
|
69
|
+
value="value"
|
70
|
+
></glide-core-dropdown-option>
|
71
|
+
</glide-core-dropdown>`);
|
72
|
+
const assignedElements = component.shadowRoot
|
73
|
+
?.querySelector('slot[name="description"]')
|
74
|
+
?.assignedElements();
|
75
|
+
expect(assignedElements?.at(0)?.textContent).to.equal('Description');
|
76
|
+
});
|
77
|
+
it('can have a tooltip', async () => {
|
78
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
79
|
+
<glide-core-dropdown-option
|
80
|
+
label="Label"
|
81
|
+
value="value"
|
82
|
+
></glide-core-dropdown-option>
|
83
|
+
<div slot="tooltip">Tooltip</div>
|
84
|
+
</glide-core-dropdown>`);
|
85
|
+
const assignedElements = component.shadowRoot
|
86
|
+
?.querySelector('slot[name="tooltip"]')
|
87
|
+
?.assignedElements();
|
88
|
+
expect(assignedElements?.at(0)?.textContent).to.equal('Tooltip');
|
89
|
+
});
|
90
|
+
it('can have a `name`', async () => {
|
91
|
+
const component = await fixture(html `<glide-core-dropdown
|
92
|
+
label="Label"
|
93
|
+
placeholder="Placeholder"
|
94
|
+
name="name"
|
95
|
+
>
|
96
|
+
<glide-core-dropdown-option
|
97
|
+
label="Label"
|
98
|
+
value="value"
|
99
|
+
></glide-core-dropdown-option>
|
100
|
+
</glide-core-dropdown>`);
|
101
|
+
expect(component.getAttribute('name')).to.equal('name');
|
102
|
+
expect(component.name).to.equal('name');
|
103
|
+
});
|
104
|
+
it('can have a `size`', async () => {
|
105
|
+
const component = await fixture(html `<glide-core-dropdown
|
106
|
+
label="Label"
|
107
|
+
placeholder="Placeholder"
|
108
|
+
size="small"
|
109
|
+
>
|
110
|
+
<glide-core-dropdown-option
|
111
|
+
label="Label"
|
112
|
+
value="value"
|
113
|
+
></glide-core-dropdown-option>
|
114
|
+
</glide-core-dropdown>`);
|
115
|
+
expect(component.getAttribute('size')).to.equal('small');
|
116
|
+
expect(component.size).to.equal('small');
|
117
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
118
|
+
expect(option?.privateSize).to.equal('small');
|
119
|
+
});
|
120
|
+
it('can be `disabled`', async () => {
|
121
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" disabled>
|
122
|
+
<glide-core-dropdown-option
|
123
|
+
label="Label"
|
124
|
+
value="value"
|
125
|
+
></glide-core-dropdown-option>
|
126
|
+
</glide-core-dropdown>`);
|
127
|
+
expect(component.hasAttribute('disabled')).to.be.true;
|
128
|
+
expect(component.disabled).to.equal(true);
|
129
|
+
});
|
130
|
+
it('can be `required`', async () => {
|
131
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" required>
|
132
|
+
<glide-core-dropdown-option
|
133
|
+
label="Label"
|
134
|
+
value="value"
|
135
|
+
></glide-core-dropdown-option>
|
136
|
+
</glide-core-dropdown>`);
|
137
|
+
expect(component.hasAttribute('required')).to.be.true;
|
138
|
+
expect(component.required).to.equal(true);
|
139
|
+
});
|
140
|
+
it('can be `multiple`', async () => {
|
141
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
|
142
|
+
<glide-core-dropdown-option
|
143
|
+
label="One"
|
144
|
+
value="one"
|
145
|
+
></glide-core-dropdown-option>
|
146
|
+
|
147
|
+
<glide-core-dropdown-option
|
148
|
+
label="Two"
|
149
|
+
value="two"
|
150
|
+
></glide-core-dropdown-option>
|
151
|
+
</glide-core-dropdown>`);
|
152
|
+
expect(component.hasAttribute('multiple')).to.be.true;
|
153
|
+
expect(component.multiple).to.equal(true);
|
154
|
+
});
|
155
|
+
it('can be `select-all`', async () => {
|
156
|
+
const component = await fixture(html `<glide-core-dropdown
|
157
|
+
label="Label"
|
158
|
+
placeholder="Placeholder"
|
159
|
+
multiple
|
160
|
+
select-all
|
161
|
+
>
|
162
|
+
<glide-core-dropdown-option
|
163
|
+
label="Label"
|
164
|
+
value="value"
|
165
|
+
></glide-core-dropdown-option>
|
166
|
+
</glide-core-dropdown>`);
|
167
|
+
expect(component.hasAttribute('select-all')).to.be.true;
|
168
|
+
expect(component.selectAll).to.equal(true);
|
169
|
+
});
|
170
|
+
it('activates the first option when no options are initially selected', async () => {
|
171
|
+
const component = await fixture(html `<glide-core-dropdown open>
|
172
|
+
<glide-core-dropdown-option
|
173
|
+
label="One"
|
174
|
+
value="one"
|
175
|
+
></glide-core-dropdown-option>
|
176
|
+
|
177
|
+
<glide-core-dropdown-option
|
178
|
+
label="Two"
|
179
|
+
value="two"
|
180
|
+
></glide-core-dropdown-option>
|
181
|
+
</glide-core-dropdown>`);
|
182
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
183
|
+
expect(options[0]?.privateActive).to.be.true;
|
184
|
+
expect(options[1]?.privateActive).to.be.false;
|
185
|
+
});
|
186
|
+
it('activates the last selected option when options are initially selected', async () => {
|
187
|
+
const component = await fixture(html `<glide-core-dropdown open>
|
188
|
+
<glide-core-dropdown-option
|
189
|
+
label="One"
|
190
|
+
value="one"
|
191
|
+
></glide-core-dropdown-option>
|
192
|
+
|
193
|
+
<glide-core-dropdown-option
|
194
|
+
label="Two"
|
195
|
+
value="two"
|
196
|
+
selected
|
197
|
+
></glide-core-dropdown-option>
|
198
|
+
|
199
|
+
<glide-core-dropdown-option
|
200
|
+
label="Three"
|
201
|
+
value="three"
|
202
|
+
selected
|
203
|
+
></glide-core-dropdown-option>
|
204
|
+
</glide-core-dropdown>`);
|
205
|
+
const options = component.querySelectorAll('glide-core-dropdown-option');
|
206
|
+
expect(options[0]?.privateActive).to.be.false;
|
207
|
+
expect(options[1]?.privateActive).to.be.false;
|
208
|
+
expect(options[2]?.privateActive).to.be.true;
|
209
|
+
});
|
210
|
+
it('throws if the default slot is the incorrect type', async () => {
|
211
|
+
await expectArgumentError(() => {
|
212
|
+
return fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
213
|
+
<button>Button</button>
|
214
|
+
</glide-core-dropdown>`);
|
215
|
+
});
|
216
|
+
});
|
217
|
+
it('does not throw if the default slot only contains whitespace', async () => {
|
218
|
+
const spy = sinon.spy();
|
219
|
+
try {
|
220
|
+
await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
221
|
+
${repeat([], () => html `<glide-core-dropdown-option
|
222
|
+
label="Option"
|
223
|
+
value="option"
|
224
|
+
></glide-core-dropdown-option>`)}
|
225
|
+
</glide-core-dropdown>`);
|
226
|
+
}
|
227
|
+
catch (error) {
|
228
|
+
if (error instanceof ArgumentError) {
|
229
|
+
spy();
|
230
|
+
}
|
231
|
+
}
|
232
|
+
expect(spy.notCalled).to.be.true;
|
233
|
+
});
|