@crowdstrike/glide-core 0.5.0 → 0.5.2
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/dist/accordion.js +1 -1
- package/dist/accordion.styles.js +4 -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 +4 -4
- 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.js +1 -1
- package/dist/button.styles.js +4 -4
- package/dist/button.test.basics.js +196 -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 +3 -3
- 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 +18 -3
- 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.methods.js +34 -0
- package/dist/dropdown.d.ts +4 -2
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.d.ts +1 -3
- 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 +87 -0
- package/dist/dropdown.option.test.interactions.single.js +22 -0
- package/dist/dropdown.styles.js +28 -9
- 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 +18 -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 +385 -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.js +1 -1
- package/dist/icon-button.styles.js +3 -3
- package/dist/icon-button.test.basics.js +103 -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 +3 -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 +3 -3
- package/dist/label.test.basics.js +129 -0
- package/dist/library/expect-argument-error.js +1 -1
- package/dist/library/ow.js +1 -1
- package/dist/library/ow.test.js +55 -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 +4 -0
- 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.styles.js +13 -6
- package/dist/menu.test.basics.js +161 -0
- package/dist/menu.test.focus.d.ts +0 -1
- package/dist/menu.test.focus.js +66 -0
- package/dist/menu.test.interactions.d.ts +0 -1
- package/dist/menu.test.interactions.js +522 -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 -4
- 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.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 +2 -2
- 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 +4 -4
- package/dist/split-button.d.ts +24 -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 +103 -0
- package/dist/split-button.test.basics.d.ts +1 -0
- package/dist/split-button.test.basics.js +84 -0
- package/dist/split-container.d.ts +30 -0
- package/dist/split-container.js +1 -0
- package/dist/split-container.styles.d.ts +2 -0
- package/dist/split-container.styles.js +132 -0
- package/dist/split-container.test.basics.d.ts +3 -0
- package/dist/split-container.test.basics.js +445 -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/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 +2 -2
- package/dist/tab.test.basics.js +71 -0
- package/dist/tag.js +1 -1
- package/dist/tag.styles.js +3 -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/textarea.js +2 -2
- package/dist/textarea.styles.js +3 -3
- 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 +64 -0
- package/dist/toggle.test.events.js +29 -0
- package/dist/toggle.test.focus.js +9 -0
- package/dist/toggle.test.states.js +35 -0
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +3 -3
- package/dist/tooltip.test.basics.js +64 -0
- package/dist/tooltip.test.interactions.js +78 -0
- 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.js +1 -1
- package/dist/tree.item.menu.styles.js +2 -2
- package/dist/tree.item.menu.test.basics.js +34 -0
- package/dist/tree.item.styles.js +2 -2
- package/dist/tree.item.test.basics.js +102 -0
- package/dist/tree.js +1 -1
- 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 +20 -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
package/dist/toggle.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,i){var l,r=arguments.length,s=r<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,i);else for(var d=e.length-1;d>=0;d--)(l=e[d])&&(s=(r<3?l(s):r>3?l(t,o,s):l(t,o))||s);return r>3&&s&&Object.defineProperty(t,o,s),s};import"./label.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import styles from"./toggle.styles.js";let GlideCoreToggle=class GlideCoreToggle extends LitElement{constructor(){super(...arguments),this.checked=!1,this.disabled=!1,this.hideLabel=!1,this.orientation="horizontal",this.#e=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}click(){this.#e.value?.click()}focus(e){this.#e.value?.focus(e)}render(){return html`<div data-test="component"><glide-core-label orientation="${this.orientation}" ?disabled="${this.disabled}" ?hide="${this.hideLabel}"><slot name="tooltip" slot="tooltip"></slot><label for="input">${this.label}</label><div class="toggle-and-input" slot="control"><input aria-describedby="summary description" data-test="input" id="input" type="checkbox" ?checked="${this.checked}" ?disabled="${this.disabled}" @change="${this.#t}" ${ref(this.#e)}></div><div slot="summary" id="summary">${this.summary}</div><slot class="description" id="description" name="description" slot="description"></slot></glide-core-label></div>`}#e;#t(e){e.target instanceof HTMLInputElement&&(this.checked=e.target.checked),this.dispatchEvent(new Event(e.type,e))}};__decorate([property({type:Boolean})],GlideCoreToggle.prototype,"checked",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreToggle.prototype,"disabled",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreToggle.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreToggle.prototype,"label",void 0),__decorate([property({reflect:!0})],GlideCoreToggle.prototype,"orientation",void 0),__decorate([property({reflect:!0})],GlideCoreToggle.prototype,"name",void 0),__decorate([property({reflect:!0})],GlideCoreToggle.prototype,"summary",void 0),GlideCoreToggle=__decorate([customElement("glide-core-toggle")],GlideCoreToggle);export default GlideCoreToggle;
|
package/dist/toggle.styles.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
|
2
2
|
/*
|
3
3
|
Most states are handled on the host. But ":checked" is handled on the input
|
4
4
|
because browsers don't support that class on the host. And using attribute
|
@@ -30,7 +30,7 @@ Use the ":checked" pseudo class on the host and throughout when browsers support
|
|
30
30
|
position: relative;
|
31
31
|
|
32
32
|
&:has(input:focus-visible) {
|
33
|
-
${
|
33
|
+
${focusOutline};
|
34
34
|
outline-offset: 4px;
|
35
35
|
}
|
36
36
|
|
@@ -78,4 +78,4 @@ Use the ":checked" pseudo class on the host and throughout when browsers support
|
|
78
78
|
opacity: 0;
|
79
79
|
position: absolute;
|
80
80
|
}
|
81
|
-
`];
|
81
|
+
`];
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreToggle from './toggle.js';
|
3
|
+
GlideCoreToggle.shadowRootOptions.mode = 'open';
|
4
|
+
it('registers', async () => {
|
5
|
+
expect(window.customElements.get('glide-core-toggle')).to.equal(GlideCoreToggle);
|
6
|
+
});
|
7
|
+
it('has defaults', async () => {
|
8
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
9
|
+
expect(component.hasAttribute('checked')).to.be.false;
|
10
|
+
expect(component.checked).to.be.false;
|
11
|
+
expect(component.hasAttribute('disabled')).to.be.false;
|
12
|
+
expect(component.disabled).to.be.false;
|
13
|
+
expect(component.hasAttribute('hide-label')).to.be.false;
|
14
|
+
expect(component.hideLabel).to.be.false;
|
15
|
+
expect(component.getAttribute('orientation')).to.equal('horizontal');
|
16
|
+
expect(component.orientation).to.equal('horizontal');
|
17
|
+
expect(component.getAttribute('summary')).to.be.null;
|
18
|
+
expect(component.summary).to.equal(undefined);
|
19
|
+
});
|
20
|
+
it('is accessible', async () => {
|
21
|
+
const component = await fixture(html `<glide-core-toggle label="Label">
|
22
|
+
<div slot="tooltip">Tooltip</div>
|
23
|
+
<div slot="description">Description</div>
|
24
|
+
</glide-core-toggle>`);
|
25
|
+
await expect(component).to.be.accessible();
|
26
|
+
});
|
27
|
+
it('can have a label', async () => {
|
28
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle> `);
|
29
|
+
expect(component.getAttribute('label')).to.equal('Label');
|
30
|
+
expect(component.label).to.equal('Label');
|
31
|
+
});
|
32
|
+
it('can have a description', async () => {
|
33
|
+
const component = await fixture(html `<glide-core-toggle label="Label">
|
34
|
+
<div slot="description">Description</div>
|
35
|
+
</glide-core-toggle>`);
|
36
|
+
const assignedElements = component.shadowRoot
|
37
|
+
?.querySelector('slot[name="description"]')
|
38
|
+
?.assignedElements();
|
39
|
+
expect(assignedElements?.at(0)?.textContent).to.equal('Description');
|
40
|
+
});
|
41
|
+
it('can have a summary', async () => {
|
42
|
+
const component = await fixture(html `<glide-core-toggle summary="Summary"></glide-core-toggle> `);
|
43
|
+
expect(component.getAttribute('summary')).to.equal('Summary');
|
44
|
+
expect(component.summary).to.equal('Summary');
|
45
|
+
});
|
46
|
+
it('can have a tooltip', async () => {
|
47
|
+
const component = await fixture(html `<glide-core-toggle label="Label">
|
48
|
+
<div slot="tooltip">Tooltip</div>
|
49
|
+
</glide-core-toggle>`);
|
50
|
+
const assignedElements = component.shadowRoot
|
51
|
+
?.querySelector('slot[name="tooltip"]')
|
52
|
+
?.assignedElements();
|
53
|
+
expect(assignedElements?.at(0)?.textContent).to.equal('Tooltip');
|
54
|
+
});
|
55
|
+
it('can be checked', async () => {
|
56
|
+
const component = await fixture(html `<glide-core-toggle checked></glide-core-toggle> `);
|
57
|
+
expect(component.hasAttribute('checked')).to.be.true;
|
58
|
+
expect(component.checked).to.equal(true);
|
59
|
+
});
|
60
|
+
it('can be disabled', async () => {
|
61
|
+
const component = await fixture(html `<glide-core-toggle disabled></glide-core-toggle> `);
|
62
|
+
expect(component.hasAttribute('disabled')).to.be.true;
|
63
|
+
expect(component.disabled).to.equal(true);
|
64
|
+
});
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { expect, fixture, html, oneEvent } from '@open-wc/testing';
|
2
|
+
import GlideCoreToggle from './toggle.js';
|
3
|
+
GlideCoreToggle.shadowRootOptions.mode = 'open';
|
4
|
+
// `await aTimeout(0)` is used throughout. Using `oneEvent` instead and
|
5
|
+
// expecting it to throw would work. But it wouldn't throw until its
|
6
|
+
// timeout, which would make for a slow test. Its timeout can likely be
|
7
|
+
// configured. But waiting a turn of the event loop, after which the event
|
8
|
+
// will have been dispatched, gets the job done as well.
|
9
|
+
it('dispatches a "click" event when clicked', async () => {
|
10
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
11
|
+
setTimeout(() => component.click());
|
12
|
+
const event = await oneEvent(component, 'click');
|
13
|
+
expect(event instanceof PointerEvent).to.be.true;
|
14
|
+
expect(event.bubbles).to.be.true;
|
15
|
+
});
|
16
|
+
it('dispatches a "change" event when clicked', async () => {
|
17
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
18
|
+
setTimeout(() => component.click());
|
19
|
+
const event = await oneEvent(component, 'change');
|
20
|
+
expect(event instanceof Event).to.be.true;
|
21
|
+
expect(event.bubbles).to.be.true;
|
22
|
+
});
|
23
|
+
it('dispatches an "input" event when clicked', async () => {
|
24
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
25
|
+
setTimeout(() => component.click());
|
26
|
+
const event = await oneEvent(component, 'input');
|
27
|
+
expect(event instanceof Event).to.be.true;
|
28
|
+
expect(event.bubbles).to.be.true;
|
29
|
+
});
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreToggle from './toggle.js';
|
3
|
+
GlideCoreToggle.shadowRootOptions.mode = 'open';
|
4
|
+
it('focuses the input when `focus` is called', async () => {
|
5
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
6
|
+
component.focus();
|
7
|
+
const input = component.shadowRoot?.querySelector('[data-test="input"]');
|
8
|
+
expect(component.shadowRoot?.activeElement).to.equal(input);
|
9
|
+
});
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreToggle from './toggle.js';
|
3
|
+
GlideCoreToggle.shadowRootOptions.mode = 'open';
|
4
|
+
it('is checked after being clicked', async () => {
|
5
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
6
|
+
component.click();
|
7
|
+
await elementUpdated(component);
|
8
|
+
expect(component.checked).to.equal(true);
|
9
|
+
expect(component.hasAttribute('checked')).to.be.false;
|
10
|
+
});
|
11
|
+
it('is unchecked after being clicked', async () => {
|
12
|
+
const component = await fixture(html `<glide-core-toggle label="Label" checked></glide-core-toggle>`);
|
13
|
+
component.click();
|
14
|
+
await elementUpdated(component);
|
15
|
+
expect(component.checked).to.equal(false);
|
16
|
+
expect(component.hasAttribute('checked')).to.be.true;
|
17
|
+
});
|
18
|
+
it('is still checked after being clicked when checked but disabled', async () => {
|
19
|
+
const component = await fixture(html `<glide-core-toggle
|
20
|
+
label="Label"
|
21
|
+
checked
|
22
|
+
disabled
|
23
|
+
></glide-core-toggle>`);
|
24
|
+
component.click();
|
25
|
+
await elementUpdated(component);
|
26
|
+
expect(component.checked).to.equal(true);
|
27
|
+
expect(component.hasAttribute('checked')).to.be.true;
|
28
|
+
});
|
29
|
+
it('is still unchecked after being clicked when unchecked and disabled', async () => {
|
30
|
+
const component = await fixture(html `<glide-core-toggle label="Label" disabled></glide-core-toggle>`);
|
31
|
+
component.click();
|
32
|
+
await elementUpdated(component);
|
33
|
+
expect(component.hasAttribute('checked')).to.be.false;
|
34
|
+
expect(component.checked).to.equal(false);
|
35
|
+
});
|
package/dist/tooltip.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,i){var l,s=arguments.length,a=s<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,o,i);else for(var r=e.length-1;r>=0;r--)(l=e[r])&&(a=(s<3?l(a):s>3?l(t,o,a):l(t,o))||a);return s>3&&a&&Object.defineProperty(t,o,a),a};import{LitElement,html}from"lit";import{arrow,autoUpdate,computePosition,flip,offset,shift}from"@floating-ui/dom";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{owSlot}from"./library/ow.js";import styles from"./tooltip.styles.js";let GlideCoreTooltip=class GlideCoreTooltip extends LitElement{static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#e.value),owSlot(this.#t.value),this.#o()}get isVisible(){return this.#i}set isVisible(e){this.#i=e,this.isVisible?this.#o():this.#l?.()}render(){return html`<div class="component" @mouseover="${this.#s}" @mouseout="${this.#a}"><div aria-labelledby="tooltip" class="target" slot="target" @focusin="${this.#r}" @focusout="${this.#n}" @keydown="${this.#f}" ${ref(this.#c)}><slot @slotchange="${this.#p}" ${ref(this.#t)} name="target"></slot></div><div class="${classMap({tooltip:!0,visible:this.isVisible})}" id="tooltip" role="tooltip" ${ref(this.#m)}><span aria-label="Tooltip: "></span><slot @slotchange="${this.#h}" ${ref(this.#e)}></slot><div class="arrow" ${ref(this.#u)}></div></div></div>`}#u=createRef();#l;#d;#e=createRef();#i=!1;#c=createRef();#t=createRef();#m=createRef();#g(){clearTimeout(this.#d)}#h(){owSlot(this.#e.value)}#r(){this.isVisible=!0}#n(){this.isVisible=!1}#f(e){"Escape"===e.key&&(this.isVisible=!1)}#a(){this.#v()}#s(){this.#g(),this.isVisible=!0}#p(){owSlot(this.#t.value)}#v(){this.#d=setTimeout((()=>{this.isVisible=!1}),200)}#o(){this.#c.value&&this.#m.value&&(this.#l=autoUpdate(this.#c.value,this.#m.value,(()=>{(async()=>{if(this.#c.value&&this.#m.value){const e=this.#u.value,{placement:t,x:o,y:i,middlewareData:l}=await computePosition(this.#c.value,this.#m.value,{placement:this.placement,strategy:"fixed",middleware:[offset(10),flip({fallbackStrategy:"initialPlacement"}),shift(),arrow({element:e})]});Object.assign(this.#m.value.style,{left:`${o}px`,top:`${i}px`});const s=l.arrow?.x??null,a=l.arrow?.y??null,r={top:"bottom",right:"left",bottom:"top",left:"right"}[t.split("-")[0]];Object.assign(e.style,{left:null===s?"":`${s}px`,top:null===a?"":`${a}px`,right:"",bottom:"",[r]:"-3px"}),this.effectivePlacement=t}})()})))}};__decorate([property()],GlideCoreTooltip.prototype,"placement",void 0),__decorate([state()],GlideCoreTooltip.prototype,"isVisible",null),__decorate([state()],GlideCoreTooltip.prototype,"effectivePlacement",void 0),GlideCoreTooltip=__decorate([customElement("glide-core-tooltip")],GlideCoreTooltip);export default GlideCoreTooltip;
|
package/dist/tooltip.styles.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
|
2
2
|
.component {
|
3
3
|
/* https://github.com/CrowdStrike/glide-core/pull/119#issuecomment-2113314591 */
|
4
4
|
display: flex;
|
@@ -19,7 +19,7 @@
|
|
19
19
|
}
|
20
20
|
|
21
21
|
&:focus-visible {
|
22
|
-
${
|
22
|
+
${focusOutline};
|
23
23
|
}
|
24
24
|
|
25
25
|
::slotted svg {
|
@@ -63,4 +63,4 @@
|
|
63
63
|
position: absolute;
|
64
64
|
transform: rotate(45deg);
|
65
65
|
}
|
66
|
-
`];
|
66
|
+
`];
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import './tooltip.js';
|
2
|
+
import { ArgumentError } from 'ow';
|
3
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
4
|
+
import GlideCoreTooltip from './tooltip.js';
|
5
|
+
import sinon from 'sinon';
|
6
|
+
GlideCoreTooltip.shadowRootOptions.mode = 'open';
|
7
|
+
it('registers', async () => {
|
8
|
+
expect(window.customElements.get('glide-core-tooltip')).to.equal(GlideCoreTooltip);
|
9
|
+
});
|
10
|
+
it('is accessible', async () => {
|
11
|
+
const component = await fixture(html `<glide-core-tooltip>
|
12
|
+
Tooltip
|
13
|
+
<span slot="target" tabindex="0">Target</span>
|
14
|
+
</glide-core-tooltip>`);
|
15
|
+
// See the comment in the component's `render` method for an explanation.
|
16
|
+
await expect(component).to.be.accessible({
|
17
|
+
ignoredRules: ['aria-tooltip-name'],
|
18
|
+
});
|
19
|
+
});
|
20
|
+
it('can have a tooltip', async () => {
|
21
|
+
const component = await fixture(html `<glide-core-tooltip aria-label="Label">
|
22
|
+
Tooltip
|
23
|
+
<span slot="target" tabindex="0">Target</span>
|
24
|
+
</glide-core-tooltip>`);
|
25
|
+
const tooltip = component?.shadowRoot
|
26
|
+
?.querySelector('slot:not([name])')
|
27
|
+
?.assignedNodes()
|
28
|
+
.at(0);
|
29
|
+
expect(tooltip?.textContent?.trim()).to.equal('Tooltip');
|
30
|
+
});
|
31
|
+
it('can have a target', async () => {
|
32
|
+
const component = await fixture(html `<glide-core-tooltip>
|
33
|
+
Tooltip
|
34
|
+
<span slot="target" tabindex="0">Target</span>
|
35
|
+
</glide-core-tooltip>`);
|
36
|
+
const assignedElements = component.shadowRoot
|
37
|
+
?.querySelector('slot[name="target"]')
|
38
|
+
?.assignedElements();
|
39
|
+
expect(assignedElements?.at(0)?.textContent).to.equal('Target');
|
40
|
+
});
|
41
|
+
it('throws if it does not have a default slot', async () => {
|
42
|
+
const spy = sinon.spy();
|
43
|
+
try {
|
44
|
+
await fixture(html `<glide-core-tooltip></glide-core-tooltip>`);
|
45
|
+
}
|
46
|
+
catch (error) {
|
47
|
+
if (error instanceof ArgumentError) {
|
48
|
+
spy();
|
49
|
+
}
|
50
|
+
}
|
51
|
+
expect(spy.called).to.be.true;
|
52
|
+
});
|
53
|
+
it('throws if it does not have a "target" slot', async () => {
|
54
|
+
const spy = sinon.spy();
|
55
|
+
try {
|
56
|
+
await fixture(html `<glide-core-tooltip> Tooltip </glide-core-tooltip>`);
|
57
|
+
}
|
58
|
+
catch (error) {
|
59
|
+
if (error instanceof ArgumentError) {
|
60
|
+
spy();
|
61
|
+
}
|
62
|
+
}
|
63
|
+
expect(spy.called).to.be.true;
|
64
|
+
});
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import './tooltip.js';
|
2
|
+
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
|
3
|
+
import { sendKeys } from '@web/test-runner-commands';
|
4
|
+
import GlideCoreTooltip from './tooltip.js';
|
5
|
+
import sinon from 'sinon';
|
6
|
+
GlideCoreTooltip.shadowRootOptions.mode = 'open';
|
7
|
+
it('is visible on "focusin"', async () => {
|
8
|
+
const component = await fixture(html `<glide-core-tooltip>
|
9
|
+
Tooltip
|
10
|
+
<span slot="target" tabindex="0">Target</span>
|
11
|
+
</glide-core-tooltip>`);
|
12
|
+
component.shadowRoot
|
13
|
+
?.querySelector('[aria-labelledby="tooltip"]')
|
14
|
+
?.dispatchEvent(new FocusEvent('focusin'));
|
15
|
+
await elementUpdated(component);
|
16
|
+
expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.true;
|
17
|
+
});
|
18
|
+
it('is hidden on "blur"', async () => {
|
19
|
+
const component = await fixture(html `<glide-core-tooltip>
|
20
|
+
Tooltip
|
21
|
+
<span slot="target" tabindex="0">Target</span>
|
22
|
+
</glide-core-tooltip>`);
|
23
|
+
component.shadowRoot
|
24
|
+
?.querySelector('[aria-labelledby="tooltip"]')
|
25
|
+
?.dispatchEvent(new FocusEvent('focusin'));
|
26
|
+
await elementUpdated(component);
|
27
|
+
component.shadowRoot
|
28
|
+
?.querySelector('[aria-labelledby="tooltip"]')
|
29
|
+
?.dispatchEvent(new FocusEvent('focusout'));
|
30
|
+
await elementUpdated(component);
|
31
|
+
expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.false;
|
32
|
+
});
|
33
|
+
it('is hidden on Escape', async () => {
|
34
|
+
const component = await fixture(html `<glide-core-tooltip>
|
35
|
+
Tooltip
|
36
|
+
<span slot="target" tabindex="0">Target</span>
|
37
|
+
</glide-core-tooltip>`);
|
38
|
+
component.shadowRoot
|
39
|
+
?.querySelector('[aria-labelledby="tooltip"]')
|
40
|
+
?.dispatchEvent(new FocusEvent('focusin'));
|
41
|
+
await elementUpdated(component);
|
42
|
+
// So the key is sent to the component instead of `<body>`. It's not
|
43
|
+
// clear why `component.focus()` doesn't focus the span when using
|
44
|
+
// Playwright.
|
45
|
+
component.querySelector('span')?.focus();
|
46
|
+
await sendKeys({ press: 'Escape' });
|
47
|
+
await elementUpdated(component);
|
48
|
+
expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.false;
|
49
|
+
});
|
50
|
+
it('is visible on "mouseover"', async () => {
|
51
|
+
const component = await fixture(html `<glide-core-tooltip>
|
52
|
+
Tooltip
|
53
|
+
<span slot="target" tabindex="0">Target</span>
|
54
|
+
</glide-core-tooltip>`);
|
55
|
+
component.shadowRoot
|
56
|
+
?.querySelector('.component')
|
57
|
+
?.dispatchEvent(new MouseEvent('mouseover'));
|
58
|
+
await elementUpdated(component);
|
59
|
+
expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.true;
|
60
|
+
});
|
61
|
+
it('is hidden on "mouseout"', async () => {
|
62
|
+
const clock = sinon.useFakeTimers();
|
63
|
+
const component = await fixture(html `<glide-core-tooltip>
|
64
|
+
Tooltip
|
65
|
+
<span slot="target" tabindex="0">Target</span>
|
66
|
+
</glide-core-tooltip>`);
|
67
|
+
component.shadowRoot
|
68
|
+
?.querySelector('.component')
|
69
|
+
?.dispatchEvent(new MouseEvent('mouseover'));
|
70
|
+
await elementUpdated(component);
|
71
|
+
component.shadowRoot
|
72
|
+
?.querySelector('.component')
|
73
|
+
?.dispatchEvent(new MouseEvent('mouseout'));
|
74
|
+
clock.tick(300);
|
75
|
+
await elementUpdated(component);
|
76
|
+
expect(component.shadowRoot?.querySelector('[role="tooltip"]')?.checkVisibility()).to.be.false;
|
77
|
+
clock.restore();
|
78
|
+
});
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,r){var l,n=arguments.length,i=n<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,r);else for(var s=e.length-1;s>=0;s--)(l=e[s])&&(i=(n<3?l(i):n>3?l(t,o,i):l(t,o))||i);return n>3&&i&&Object.defineProperty(t,o,i),i};import"./icon-button.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement}from"lit/decorators.js";import{owSlot}from"./library/ow.js";import styles from"./tree.item.icon-button.styles.js";let GlideCoreTreeItemIconButton=class GlideCoreTreeItemIconButton extends LitElement{static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#e.value)}render(){return html`<glide-core-icon-button class="component" variant="tertiary"><slot @slotchange="${this.#t}" ${ref(this.#e)}></slot></glide-core-icon-button>`}#e=createRef();#t(){owSlot(this.#e.value)}};GlideCoreTreeItemIconButton=__decorate([customElement("glide-core-tree-item-icon-button")],GlideCoreTreeItemIconButton);export default GlideCoreTreeItemIconButton;
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreTreeItemIconButton from './tree.item.icon-button.js';
|
3
|
+
import expectArgumentError from './library/expect-argument-error.js';
|
4
|
+
it('registers', async () => {
|
5
|
+
expect(window.customElements.get('glide-core-tree-item-icon-button')).to.equal(GlideCoreTreeItemIconButton);
|
6
|
+
});
|
7
|
+
it('throws if it does not have a default slot', async () => {
|
8
|
+
await expectArgumentError(() => {
|
9
|
+
return fixture(html `
|
10
|
+
<glide-core-tree-item-icon-button></glide-core-tree-item-icon-button>
|
11
|
+
`);
|
12
|
+
});
|
13
|
+
});
|
package/dist/tree.item.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,s,i){var o,r=arguments.length,l=r<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,s,i);else for(var d=e.length-1;d>=0;d--)(o=e[d])&&(l=(r<3?o(l):r>3?o(t,s,l):o(t,s))||l);return r>3&&l&&Object.defineProperty(t,s,l),l};import"./tree.item.menu.js";import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,queryAssignedElements,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{when}from"lit/directives/when.js";import styles from"./tree.item.styles.js";let GlideCoreTreeItem=class GlideCoreTreeItem extends LitElement{constructor(){super(...arguments),this.expanded=!1,this.label="",this.level=1,this.selected=!1,this.childTreeItems=[],this.hasMenuSlot=!1,this.hasPrefixSlot=!1,this.hasSuffixSlot=!1,this.#e=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}firstUpdated(){this.#t()}focus(){this.#e.value?.focus()}get hasChildTreeItems(){return this.childTreeItems.length>0}render(){return html`<div class="${classMap({component:!0,expanded:this.expanded,selected:this.selected})}" role="treeitem" aria-label="${this.label}" aria-selected="${ifDefined(this.#s)}" aria-expanded="${ifDefined(this.#i)}"><div class="${classMap({"label-container":!0})}" tabindex="-1" ${ref(this.#e)}><div style="width:${this.#o};"></div><div class="expand-icon-container">${when(this.hasChildTreeItems,(()=>html`<div><svg aria-hidden="true" class="${classMap({"expand-icon":!0,"expand-icon-expanded":this.expanded})}" width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></div>`))}</div><slot name="prefix" @slotchange="${this.#r}"></slot><div class="label">${this.label}</div><slot name="menu" @slotchange="${this.#l}"></slot><slot name="suffix" @slotchange="${this.#d}"></slot></div><div class="child-items" role="group"><slot></slot></div></div>`}selectItem(e){let t;for(const s of this.slotElements)if(e===s)s.setAttribute("selected","true"),t=s;else{s.removeAttribute("selected");const i=s.selectItem(e);i&&(t=i)}return t}toggleExpand(){this.expanded=!this.expanded}#e;get#i(){return this.hasChildTreeItems?this.expanded?"true":"false":void 0}get#s(){return this.hasChildTreeItems?void 0:this.selected?"true":"false"}get#o(){return 20*(this.level-1)+"px"}#l(){this.hasMenuSlot=this.menuSlotAssignedElements.length>0}#r(){this.hasPrefixSlot=this.prefixSlotAssignedElements.length>0}#d(){this.hasSuffixSlot=this.suffixSlotAssignedElements.length>0}#t(){const e=[];for(const t of this.slotElements)t.level=this.level+1,e.push(t);this.childTreeItems=e}};__decorate([property({type:Boolean})],GlideCoreTreeItem.prototype,"expanded",void 0),__decorate([property({reflect:!0})],GlideCoreTreeItem.prototype,"label",void 0),__decorate([property({type:Number})],GlideCoreTreeItem.prototype,"level",void 0),__decorate([property({type:Boolean})],GlideCoreTreeItem.prototype,"selected",void 0),__decorate([queryAssignedElements({slot:"menu"})],GlideCoreTreeItem.prototype,"menuSlotAssignedElements",void 0),__decorate([queryAssignedElements({slot:"prefix"})],GlideCoreTreeItem.prototype,"prefixSlotAssignedElements",void 0),__decorate([queryAssignedElements()],GlideCoreTreeItem.prototype,"slotElements",void 0),__decorate([queryAssignedElements({slot:"suffix"})],GlideCoreTreeItem.prototype,"suffixSlotAssignedElements",void 0),__decorate([state()],GlideCoreTreeItem.prototype,"childTreeItems",void 0),__decorate([state()],GlideCoreTreeItem.prototype,"hasMenuSlot",void 0),__decorate([state()],GlideCoreTreeItem.prototype,"hasPrefixSlot",void 0),__decorate([state()],GlideCoreTreeItem.prototype,"hasSuffixSlot",void 0),GlideCoreTreeItem=__decorate([customElement("glide-core-tree-item")],GlideCoreTreeItem);export default GlideCoreTreeItem;
|
package/dist/tree.item.menu.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,l){var r,i=arguments.length,n=i<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,o,l);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(n=(i<3?r(n):i>3?r(t,o,n):r(t,o))||n);return i>3&&n&&Object.defineProperty(t,o,n),n};import"./icon-button.js";import"./menu.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement}from"lit/decorators.js";import{owSlot,owSlotType}from"./library/ow.js";import GlideCoreMenuButton from"./menu.button.js";import GlideCoreMenuLink from"./menu.link.js";import styles from"./tree.item.menu.styles.js";let GlideCoreTreeItemMenu=class GlideCoreTreeItemMenu extends LitElement{static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#e.value),owSlotType(this.#e.value,[GlideCoreMenuButton,GlideCoreMenuLink])}render(){return html`<glide-core-menu class="component"><slot @slotchange="${this.#t}" ${ref(this.#e)}></slot><glide-core-icon-button slot="target" variant="tertiary"><svg width="4" height="14" viewBox="0 0 4 18" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 15C2.55228 15 3 15.4477 3 16C3 16.5523 2.55228 17 2 17C1.44772 17 1 16.5523 1 16C1 15.4477 1.44772 15 2 15Z"/><path d="M2 8C2.55228 8 3 8.44772 3 9C3 9.55228 2.55228 10 2 10C1.44772 10 1 9.55228 1 9C1 8.44772 1.44772 8 2 8Z"/><path d="M2 1C2.55228 1 3 1.44772 3 2C3 2.55228 2.55228 3 2 3C1.44772 3 1 2.55228 1 2C1 1.44772 1.44772 1 2 1Z"/></svg></glide-core-icon-button></glide-core-menu>`}#e=createRef();#t(){owSlot(this.#e.value),owSlotType(this.#e.value,[GlideCoreMenuButton,GlideCoreMenuLink])}};GlideCoreTreeItemMenu=__decorate([customElement("glide-core-tree-item-menu")],GlideCoreTreeItemMenu);export default GlideCoreTreeItemMenu;
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { expect, fixture, html, waitUntil } from '@open-wc/testing';
|
2
|
+
import GlideCoreTreeItemMenu from './tree.item.menu.js';
|
3
|
+
import expectArgumentError from './library/expect-argument-error.js';
|
4
|
+
import sinon from 'sinon';
|
5
|
+
it('registers', async () => {
|
6
|
+
expect(window.customElements.get('glide-core-tree-item-menu')).to.equal(GlideCoreTreeItemMenu);
|
7
|
+
});
|
8
|
+
it('throws if it does not have a default slot', async () => {
|
9
|
+
await expectArgumentError(() => {
|
10
|
+
return fixture(html `
|
11
|
+
<glide-core-tree-item-menu></glide-core-tree-item-menu>
|
12
|
+
`);
|
13
|
+
});
|
14
|
+
});
|
15
|
+
it('throws if the default slot is the incorrect type', async () => {
|
16
|
+
await expectArgumentError(() => {
|
17
|
+
return fixture(html `
|
18
|
+
<glide-core-tree-item-menu>
|
19
|
+
<button>Button</button>
|
20
|
+
</glide-core-tree-item-menu>
|
21
|
+
`);
|
22
|
+
});
|
23
|
+
// Menu is rendered asynchronously outside of Tree Menu Item's lifecycle
|
24
|
+
// and asserts against its default slot. That assertion, which is expected
|
25
|
+
// to fail, results in an unhandled rejection that gets logged.
|
26
|
+
const stub = sinon.stub(console, 'error');
|
27
|
+
// Menu asserts against its default slot once on `firstUpdated` and
|
28
|
+
// again on "slotchange". It also renders asynchronously. So we have
|
29
|
+
// to wait until the stub has been called before restoring it.
|
30
|
+
await waitUntil(() => stub.called);
|
31
|
+
stub.restore();
|
32
|
+
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
33
|
+
window.onerror = onerror;
|
34
|
+
});
|
package/dist/tree.item.styles.js
CHANGED
@@ -0,0 +1,102 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import TreeItem from './tree.item.js';
|
3
|
+
TreeItem.shadowRootOptions.mode = 'open';
|
4
|
+
it('registers', () => {
|
5
|
+
expect(window.customElements.get('glide-core-tree-item')).to.equal(TreeItem);
|
6
|
+
});
|
7
|
+
it('renders and sets default attributes', async () => {
|
8
|
+
const treeItem = await fixture(html `
|
9
|
+
<glide-core-tree-item label="Item"></glide-core-tree-item>
|
10
|
+
`);
|
11
|
+
expect(treeItem.expanded).to.equal(false);
|
12
|
+
expect(treeItem.label).to.equal('Item');
|
13
|
+
expect(treeItem.level).to.equal(1);
|
14
|
+
});
|
15
|
+
it('renders with a prefix slot', async () => {
|
16
|
+
await fixture(html `
|
17
|
+
<glide-core-tree-item label="Item">
|
18
|
+
<span slot="prefix" data-prefix>prefix</span>
|
19
|
+
</glide-core-tree-item>
|
20
|
+
`);
|
21
|
+
expect(document.querySelector('[data-prefix]')).to.be.ok;
|
22
|
+
});
|
23
|
+
it('renders with a menu slot', async () => {
|
24
|
+
await fixture(html `
|
25
|
+
<glide-core-tree-item label="Item">
|
26
|
+
<span slot="menu" data-menu>menu</span>
|
27
|
+
</glide-core-tree-item>
|
28
|
+
`);
|
29
|
+
expect(document.querySelector('[data-menu]')).to.be.ok;
|
30
|
+
});
|
31
|
+
it('renders with a suffix slot', async () => {
|
32
|
+
await fixture(html `
|
33
|
+
<glide-core-tree-item label="Item">
|
34
|
+
<span slot="suffix" data-suffix>suffix</span>
|
35
|
+
</glide-core-tree-item>
|
36
|
+
`);
|
37
|
+
expect(document.querySelector('[data-suffix]')).to.be.ok;
|
38
|
+
});
|
39
|
+
it('does not have an expand icon if there are no child tree items', async () => {
|
40
|
+
const treeItem = await fixture(html `
|
41
|
+
<glide-core-tree-item label="Item"></glide-core-tree-item>
|
42
|
+
`);
|
43
|
+
expect(treeItem.shadowRoot?.querySelector('.expand-icon')).to.equal(null);
|
44
|
+
});
|
45
|
+
it('can expand', async () => {
|
46
|
+
const treeItem = await fixture(html `
|
47
|
+
<glide-core-tree-item label="Item">
|
48
|
+
<glide-core-tree-item label="Child Item 1"></glide-core-tree-item>
|
49
|
+
</glide-core-tree-item>
|
50
|
+
`);
|
51
|
+
expect([
|
52
|
+
...treeItem.shadowRoot.querySelector('.component').classList,
|
53
|
+
]).to.deep.equal(['component']);
|
54
|
+
expect([
|
55
|
+
...treeItem.shadowRoot.querySelector('.expand-icon').classList,
|
56
|
+
]).to.deep.equal(['expand-icon']);
|
57
|
+
treeItem.toggleExpand();
|
58
|
+
await treeItem.updateComplete;
|
59
|
+
expect([
|
60
|
+
...treeItem.shadowRoot.querySelector('.component').classList,
|
61
|
+
]).to.deep.equal(['component', 'expanded']);
|
62
|
+
expect([
|
63
|
+
...treeItem.shadowRoot.querySelector('.expand-icon').classList,
|
64
|
+
]).to.deep.equal(['expand-icon', 'expand-icon-expanded']);
|
65
|
+
});
|
66
|
+
it('renders child and grandchild tree items', async () => {
|
67
|
+
const treeItem = await fixture(html `
|
68
|
+
<glide-core-tree-item expanded label="Item">
|
69
|
+
<glide-core-tree-item label="Child Item 1"></glide-core-tree-item>
|
70
|
+
<glide-core-tree-item label="Child Item 2">
|
71
|
+
<glide-core-tree-item label="Grandchild Item 1"></glide-core-tree-item>
|
72
|
+
</glide-core-tree-item>
|
73
|
+
</glide-core-tree-item>
|
74
|
+
`);
|
75
|
+
expect(treeItem.shadowRoot?.querySelector('.expand-icon')).to.be.ok;
|
76
|
+
const childItems = treeItem.slotElements;
|
77
|
+
expect(childItems?.length).to.equal(2);
|
78
|
+
expect(childItems?.[0].level).to.equal(2, 'Children are level 2');
|
79
|
+
const grandchildItems = childItems?.[1].slotElements;
|
80
|
+
expect(grandchildItems?.length).to.equal(1);
|
81
|
+
expect(grandchildItems?.[0].level).to.equal(3, 'Grandchildren are level 3');
|
82
|
+
});
|
83
|
+
it('can select child and grandchild items', async () => {
|
84
|
+
const treeItem = await fixture(html `
|
85
|
+
<glide-core-tree-item expanded label="Item">
|
86
|
+
<glide-core-tree-item label="Child Item 1"></glide-core-tree-item>
|
87
|
+
<glide-core-tree-item label="Child Item 2">
|
88
|
+
<glide-core-tree-item label="Grandchild Item 1"></glide-core-tree-item>
|
89
|
+
</glide-core-tree-item>
|
90
|
+
</glide-core-tree-item>
|
91
|
+
`);
|
92
|
+
const childItems = treeItem.slotElements;
|
93
|
+
const grandchildItems = childItems?.[1].slotElements;
|
94
|
+
treeItem.selectItem(childItems[0]);
|
95
|
+
expect(childItems[0].selected).to.equal(true);
|
96
|
+
expect(childItems[1].selected).to.equal(false);
|
97
|
+
expect(grandchildItems[0].selected).to.equal(false);
|
98
|
+
treeItem.selectItem(grandchildItems[0]);
|
99
|
+
expect(childItems[0].selected).to.equal(false);
|
100
|
+
expect(childItems[1].selected).to.equal(false);
|
101
|
+
expect(grandchildItems[0].selected).to.equal(true);
|
102
|
+
});
|