@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
@@ -0,0 +1,71 @@
|
|
1
|
+
import './tab.js';
|
2
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
3
|
+
import GlideCoreTab from './tab.js';
|
4
|
+
GlideCoreTab.shadowRootOptions.mode = 'open';
|
5
|
+
it('registers', async () => {
|
6
|
+
expect(window.customElements.get('glide-core-tab')).to.equal(GlideCoreTab);
|
7
|
+
});
|
8
|
+
it('renders correct markup and sets correct attributes for the default case', async () => {
|
9
|
+
const element = await fixture(html `
|
10
|
+
<glide-core-tab>Tab</glide-core-tab>
|
11
|
+
`);
|
12
|
+
await expect(element).to.not.be.accessible();
|
13
|
+
expect(element.active).to.equal(false, 'active defaults to false');
|
14
|
+
expect(element.disabled).to.equal(false, 'disabled defaults to false');
|
15
|
+
expect(element.variant).to.equal('primary');
|
16
|
+
expect(element.getAttribute('aria-disabled')).to.equal(null, 'does not set aria-disabled');
|
17
|
+
expect([...element.shadowRoot.firstElementChild.classList]).to.deep.equal([
|
18
|
+
'component',
|
19
|
+
'primary',
|
20
|
+
]);
|
21
|
+
});
|
22
|
+
it('renders a secondary variant', async () => {
|
23
|
+
const element = await fixture(html `
|
24
|
+
<glide-core-tab variant="secondary">Tab</glide-core-tab>
|
25
|
+
`);
|
26
|
+
expect([...element.shadowRoot.firstElementChild.classList]).to.deep.equal([
|
27
|
+
'component',
|
28
|
+
'secondary',
|
29
|
+
]);
|
30
|
+
});
|
31
|
+
it('renders a vertical variant', async () => {
|
32
|
+
const element = await fixture(html `
|
33
|
+
<glide-core-tab variant="vertical">Tab</glide-core-tab>
|
34
|
+
`);
|
35
|
+
expect([...element.shadowRoot.firstElementChild.classList]).to.deep.equal([
|
36
|
+
'component',
|
37
|
+
'vertical',
|
38
|
+
]);
|
39
|
+
});
|
40
|
+
it('sets the panel attribute', async () => {
|
41
|
+
const element = await fixture(html `
|
42
|
+
<glide-core-tab panel="details">Tab</glide-core-tab>
|
43
|
+
`);
|
44
|
+
expect(element.panel).to.equal('details');
|
45
|
+
});
|
46
|
+
it('sets the active attribute', async () => {
|
47
|
+
const element = await fixture(html `
|
48
|
+
<glide-core-tab active>Tab</glide-core-tab>
|
49
|
+
`);
|
50
|
+
expect(element.active).to.equal(true);
|
51
|
+
});
|
52
|
+
it('sets the disabled attribute', async () => {
|
53
|
+
const element = await fixture(html `
|
54
|
+
<glide-core-tab disabled>Tab</glide-core-tab>
|
55
|
+
`);
|
56
|
+
expect(element.disabled).to.equal(true);
|
57
|
+
expect(element).to.have.attribute('aria-disabled', 'true');
|
58
|
+
});
|
59
|
+
it('renders the icon slot', async () => {
|
60
|
+
const element = await fixture(html `
|
61
|
+
<glide-core-tab>
|
62
|
+
<span slot="icon">Icon</span>
|
63
|
+
<span>Tab</span>
|
64
|
+
</glide-core-tab>
|
65
|
+
`);
|
66
|
+
const slotNodes = element
|
67
|
+
.shadowRoot.querySelector('slot[name="icon"]')
|
68
|
+
?.assignedNodes();
|
69
|
+
expect(slotNodes?.length).to.equal(1);
|
70
|
+
expect(slotNodes?.at(0)?.textContent?.trim()).to.equal('Icon');
|
71
|
+
});
|
package/dist/tag.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,l){var r,i=arguments.length,s=i<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,l);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(i<3?r(s):i>3?r(t,o,s):r(t,o))||s);return i>3&&s&&Object.defineProperty(t,o,s),s};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{owSlot}from"./library/ow.js";import{when}from"lit/directives/when.js";import styles from"./tag.styles.js";let GlideCoreTag=class GlideCoreTag extends LitElement{constructor(){super(...arguments),this.size="medium",this.removableLabel="",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#r=200,this.#i=()=>{new Promise((()=>setTimeout((()=>{this.remove()}),this.#r))),this.#t.value?.classList.toggle("activate"),this.#t.value?.classList.toggle("deactivate"),this.dispatchEvent(new Event("remove"))}}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}click(){this.#e.value?.click()}firstUpdated(){owSlot(this.#o.value)}render(){return html`<div class="${classMap({component:!0,activate:!0,[this.size]:!0})}" ${ref(this.#t)}><slot name="prefix" ${ref(this.#l)}></slot><slot @slotchange="${this.#s}" ${ref(this.#o)}></slot>${when(this.removableLabel,(()=>html`<button type="button" class="${classMap({[this.size]:!0})}" aria-label="Remove ${this.removableLabel}" data-test="button" ${ref(this.#e)} @click="${this.#i}"><svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></button>`))}</div>`}#e;#t;#o;#l;#r;#i;#s(){owSlot(this.#o.value)}};__decorate([property({reflect:!0})],GlideCoreTag.prototype,"size",void 0),__decorate([property({attribute:"removable-label"})],GlideCoreTag.prototype,"removableLabel",void 0),GlideCoreTag=__decorate([customElement("glide-core-tag")],GlideCoreTag);export default GlideCoreTag;
|
package/dist/tag.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
|
align-items: center;
|
4
4
|
background: var(--glide-core-surface-base);
|
@@ -127,7 +127,7 @@
|
|
127
127
|
}
|
128
128
|
|
129
129
|
&:focus-visible {
|
130
|
-
${
|
130
|
+
${focusOutline};
|
131
131
|
}
|
132
132
|
}
|
133
|
-
`];
|
133
|
+
`];
|
@@ -0,0 +1,118 @@
|
|
1
|
+
import { ArgumentError } from 'ow';
|
2
|
+
import { aTimeout, expect, fixture, html } from '@open-wc/testing';
|
3
|
+
import GlideCoreTag from './tag.js';
|
4
|
+
import sinon from 'sinon';
|
5
|
+
GlideCoreTag.shadowRootOptions.mode = 'open';
|
6
|
+
it('registers', async () => {
|
7
|
+
expect(window.customElements.get('glide-core-tag')).to.equal(GlideCoreTag);
|
8
|
+
});
|
9
|
+
it('is accessible', async () => {
|
10
|
+
const element = await fixture(html `<glide-core-tag>Tag</glide-core-tag>`);
|
11
|
+
// Wait for the animation to complete
|
12
|
+
await aTimeout(200);
|
13
|
+
await expect(element).to.be.accessible();
|
14
|
+
});
|
15
|
+
it('renders with default slot content', async () => {
|
16
|
+
const element = await fixture(html `<glide-core-tag><span data-content>Tag</span></glide-core-tag>`);
|
17
|
+
expect(element).to.be.not.null;
|
18
|
+
const container = element.shadowRoot?.querySelector('.component');
|
19
|
+
expect(container).to.be.not.null;
|
20
|
+
const contentRendered = element.querySelector('[data-content]');
|
21
|
+
expect(contentRendered).to.be.not.null;
|
22
|
+
expect(contentRendered?.textContent).to.be.equal('Tag');
|
23
|
+
});
|
24
|
+
it('does not render an icon button when "removable-label" attribute is not set', async () => {
|
25
|
+
const element = await fixture(html `<glide-core-tag><span data-content>Tag</span></glide-core-tag>`);
|
26
|
+
expect(element).to.not.have.attribute('removable-label');
|
27
|
+
const iconButton = element.shadowRoot?.querySelector('button');
|
28
|
+
expect(iconButton).to.be.null;
|
29
|
+
});
|
30
|
+
it('renders an icon button with aria-label when "removable-label" attribute is set', async () => {
|
31
|
+
const element = await fixture(html `<glide-core-tag removable-label="test-aria-label"
|
32
|
+
><span slot="prefix">Prefix</span
|
33
|
+
><span data-content>Tag</span></glide-core-tag
|
34
|
+
>`);
|
35
|
+
expect(element).to.be.not.null;
|
36
|
+
expect(element).to.have.attribute('removable-label', 'test-aria-label');
|
37
|
+
const iconButton = element.shadowRoot?.querySelector('button');
|
38
|
+
expect(iconButton).to.be.not.null;
|
39
|
+
expect(iconButton).to.have.attribute('aria-label', `Remove test-aria-label`);
|
40
|
+
expect(iconButton).to.have.attribute('type', 'button');
|
41
|
+
});
|
42
|
+
it('renders the "prefix" slot and its content', async () => {
|
43
|
+
const element = await fixture(html `<glide-core-tag
|
44
|
+
><span slot="prefix" data-prefix>test-prefix</span>Tag</glide-core-tag
|
45
|
+
>`);
|
46
|
+
const prefixSlot = element.shadowRoot?.querySelector('slot[name="prefix"]');
|
47
|
+
expect(prefixSlot?.assignedNodes()?.length).to.be.equal(1);
|
48
|
+
expect(document.querySelector('[data-prefix]')).to.be.not.null;
|
49
|
+
expect(document.querySelector('[data-prefix]')?.textContent).to.be.equal('test-prefix');
|
50
|
+
});
|
51
|
+
it('renders correctly when the "size" attribute is set to "small"', async () => {
|
52
|
+
const element = await fixture(html `<glide-core-tag removable-label="test-aria-label" size="small"
|
53
|
+
><span slot="prefix">Prefix</span
|
54
|
+
><span data-content>Tag</span></glide-core-tag
|
55
|
+
>`);
|
56
|
+
const container = element.shadowRoot?.querySelector('.component');
|
57
|
+
const iconButton = element.shadowRoot?.querySelector('button');
|
58
|
+
expect(container).to.have.class('small');
|
59
|
+
expect(iconButton).to.have.class('small');
|
60
|
+
});
|
61
|
+
it('renders correctly when the "size" attribute is set to "large"', async () => {
|
62
|
+
const element = await fixture(html `<glide-core-tag removable-label="test-aria-label" size="large"
|
63
|
+
><span slot="prefix">Prefix</span
|
64
|
+
><span data-content>Tag</span></glide-core-tag
|
65
|
+
>`);
|
66
|
+
const container = element.shadowRoot?.querySelector('.component');
|
67
|
+
const iconButton = element.shadowRoot?.querySelector('button');
|
68
|
+
expect(container).to.have.class('large');
|
69
|
+
expect(iconButton).to.have.class('large');
|
70
|
+
});
|
71
|
+
it('throws an error when the default slot is empty', async () => {
|
72
|
+
const spy = sinon.spy();
|
73
|
+
try {
|
74
|
+
await fixture(html `<glide-core-tag></glide-core-tag>`);
|
75
|
+
}
|
76
|
+
catch (error) {
|
77
|
+
if (error instanceof ArgumentError) {
|
78
|
+
spy();
|
79
|
+
}
|
80
|
+
}
|
81
|
+
expect(spy.called).to.be.true;
|
82
|
+
});
|
83
|
+
it('does not throw an error when the default slot is non-empty', async () => {
|
84
|
+
const spy = sinon.spy();
|
85
|
+
try {
|
86
|
+
await fixture(html `<glide-core-tag>Tag</glide-core-tag>`);
|
87
|
+
}
|
88
|
+
catch (error) {
|
89
|
+
if (error instanceof ArgumentError) {
|
90
|
+
spy();
|
91
|
+
}
|
92
|
+
}
|
93
|
+
expect(spy.notCalled).to.be.true;
|
94
|
+
});
|
95
|
+
it('toggles the "activate" and "deactivate" clases when the button is clicked', async () => {
|
96
|
+
const element = await fixture(html `<glide-core-tag removable-label="test-aria-label"
|
97
|
+
><span slot="prefix">Prefix</span>Tag</glide-core-tag
|
98
|
+
>`);
|
99
|
+
const container = element.shadowRoot?.querySelector('.component');
|
100
|
+
const iconButton = element.shadowRoot?.querySelector('button');
|
101
|
+
expect(container).to.have.class('activate');
|
102
|
+
iconButton?.click();
|
103
|
+
expect(container).to.have.class('deactivate');
|
104
|
+
});
|
105
|
+
it('removes the tag from the DOM when the button is clicked', async () => {
|
106
|
+
const element = await fixture(html `<glide-core-tag removable-label="test-aria-label"
|
107
|
+
><span slot="prefix">Prefix</span
|
108
|
+
><span data-content>Tag</span></glide-core-tag
|
109
|
+
>`);
|
110
|
+
expect(element.shadowRoot?.querySelector('.component')).to.be.not.null;
|
111
|
+
expect(document.querySelector('[data-content]')).to.be.not.null;
|
112
|
+
element?.click();
|
113
|
+
// Wait for the animation to complete
|
114
|
+
await aTimeout(300);
|
115
|
+
// the tag and its contents should be removed
|
116
|
+
expect(document.querySelector('glide-core-tag')).to.be.null;
|
117
|
+
expect(document.querySelector('[data-content]')).to.be.null;
|
118
|
+
});
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import './tag.js';
|
2
|
+
import { expect, fixture, html, oneEvent } from '@open-wc/testing';
|
3
|
+
import GlideCoreTag from './tag.js';
|
4
|
+
GlideCoreTag.shadowRootOptions.mode = 'open';
|
5
|
+
it('dispatches a "remove" event when the icon button is clicked', async () => {
|
6
|
+
const element = await fixture(html `<glide-core-tag removable-label="test-aria-label"
|
7
|
+
><span slot="prefix">Prefix</span
|
8
|
+
><span data-content>Tag</span></glide-core-tag
|
9
|
+
>`);
|
10
|
+
const iconButton = element.shadowRoot?.querySelector('button');
|
11
|
+
setTimeout(() => {
|
12
|
+
iconButton?.click();
|
13
|
+
});
|
14
|
+
const event = await oneEvent(element, 'remove');
|
15
|
+
expect(event?.type).to.be.equal('remove');
|
16
|
+
});
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
2
|
+
import GlideCoreTag from './tag.js';
|
3
|
+
GlideCoreTag.shadowRootOptions.mode = 'open';
|
4
|
+
it('calling `focus()` focuses the button', async () => {
|
5
|
+
const element = await fixture(html `<glide-core-tag removable-label="Removable Label"
|
6
|
+
>Tag</glide-core-tag
|
7
|
+
>`);
|
8
|
+
element.focus();
|
9
|
+
const button = element.shadowRoot?.querySelector('[data-test="button"]');
|
10
|
+
expect(element.shadowRoot?.activeElement).to.equal(button);
|
11
|
+
});
|
package/dist/textarea.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
</textarea></div><div class="meta" data-test-description-container id="meta" slot="description"><slot name="description"></slot>${
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,i,a){var r,o=arguments.length,l=o<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,i):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,i,a);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(l=(o<3?r(l):o>3?r(t,i,l):r(t,i))||l);return o>3&&l&&Object.defineProperty(t,i,l),l};import"./label.js";import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{when}from"lit/directives/when.js";import styles from"./textarea.styles.js";let GlideCoreTextarea=class GlideCoreTextarea extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}blur(){this.#e.value?.blur()}checkValidity(){return this.isCheckingValidity=!0,this.#t.checkValidity()}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i),this.removeEventListener("invalid",this.#a)}get form(){return this.#t.form}get validity(){return this.#t.validity}get willValidate(){return this.#t.willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){this.value=this.getAttribute("value")??""}render(){return html`<glide-core-label orientation="${this.orientation}" ?disabled="${this.disabled}" ?error="${this.#r||this.#o}" ?hide="${this.hideLabel}" ?required="${this.required}"><slot name="tooltip" slot="tooltip"></slot><label class="label" for="textarea">${this.label}</label><div class="textarea-container" slot="control"><textarea class="${classMap({error:this.#r||this.#o})}" id="textarea" name="${ifDefined(this.name)}" placeholder="${ifDefined(this.placeholder)}" rows="${this.rows}" autocapitalize="${ifDefined(this.autocapitalize)}" spellcheck="${this.spellcheck}" ?required="${this.required}" ?readonly="${this.readonly}" ?disabled="${this.disabled}" aria-describedby="meta" ${ref(this.#e)} @input="${this.#l}" @change="${this.#s}">
|
2
|
+
</textarea></div><div class="meta" data-test-description-container id="meta" slot="description"><slot name="description"></slot>${when(this.maxlength,(()=>html`<div class="${classMap({"character-count":!0,error:this.#o})}" data-test-maxlength>${this.value.length}/${this.maxlength}</div>`))}</div></glide-core-label>`}reportValidity(){return this.#t.reportValidity()}updated(){this.#e.value&&(this.#e.value.value=this.value),this.#d()}constructor(){super(),this.value="",this.label="",this.hideLabel=!1,this.orientation="horizontal",this.placeholder="",this.rows=2,this.required=!1,this.readonly=!1,this.disabled=!1,this.spellcheck=!1,this.autocapitalize="on",this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#e=createRef(),this.#i=({formData:e})=>{this.value.length>0&&this.name&&this.value&&!this.disabled&&e.append(this.name,this.value)},this.#t=this.attachInternals(),this.addEventListener("invalid",this.#a)}#t;#e;#i;get#r(){return!this.disabled&&!this.readonly&&!this.validity.valid&&this.isReportValidityOrSubmit}get#o(){return!(!this.maxlength||this.disabled)&&this.value.length>this.maxlength}#s(e){const t=this.#e.value.value;this.value=t,this.#d(),this.dispatchEvent(new Event(e.type,e))}#l(){const e=this.#e.value.value;this.value=e,this.#t.setFormValue(this.value),this.#d()}#a(e){e.preventDefault(),this.isCheckingValidity||(this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!0)}async#d(){const e=this.#e.value;this.#o?this.#t.setValidity({...e?.validity,tooLong:!0}," ",e):this.#t.setValidity(e?.validity,e?.validationMessage,e),await this.updateComplete}};__decorate([property()],GlideCoreTextarea.prototype,"value",void 0),__decorate([property()],GlideCoreTextarea.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreTextarea.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"orientation",void 0),__decorate([property()],GlideCoreTextarea.prototype,"placeholder",void 0),__decorate([property({reflect:!0,type:Number})],GlideCoreTextarea.prototype,"rows",void 0),__decorate([property({type:Boolean})],GlideCoreTextarea.prototype,"required",void 0),__decorate([property({type:Boolean})],GlideCoreTextarea.prototype,"readonly",void 0),__decorate([property({type:Boolean})],GlideCoreTextarea.prototype,"disabled",void 0),__decorate([property({type:Number,converter:e=>e&&Number.parseInt(e,10)})],GlideCoreTextarea.prototype,"maxlength",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"name",void 0),__decorate([property({type:Boolean})],GlideCoreTextarea.prototype,"spellcheck",void 0),__decorate([property()],GlideCoreTextarea.prototype,"autocapitalize",void 0),__decorate([state()],GlideCoreTextarea.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreTextarea.prototype,"isReportValidityOrSubmit",void 0),GlideCoreTextarea=__decorate([customElement("glide-core-textarea")],GlideCoreTextarea);export default GlideCoreTextarea;
|
package/dist/textarea.styles.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import{css}from"lit";export default css`
|
2
2
|
glide-core-label::part(tooltip-and-label-container) {
|
3
3
|
align-items: flex-start;
|
4
4
|
margin-block-start: var(--glide-core-spacing-sm);
|
@@ -48,7 +48,7 @@
|
|
48
48
|
}
|
49
49
|
|
50
50
|
&[disabled] {
|
51
|
-
background-color: var(--glide-core-surface-
|
51
|
+
background-color: var(--glide-core-surface-disabled);
|
52
52
|
border: 0.0625rem solid var(--glide-core-border-base-light);
|
53
53
|
color: var(--glide-core-text-tertiary-disabled);
|
54
54
|
}
|
@@ -66,4 +66,4 @@
|
|
66
66
|
font-weight: var(--glide-core-font-weight-bold);
|
67
67
|
}
|
68
68
|
}
|
69
|
-
`;
|
69
|
+
`;
|
@@ -0,0 +1,140 @@
|
|
1
|
+
import { expect, fixture } from '@open-wc/testing';
|
2
|
+
import { sendKeys } from '@web/test-runner-commands';
|
3
|
+
import GlideCoreTextarea from './textarea.js';
|
4
|
+
GlideCoreTextarea.shadowRootOptions.mode = 'open';
|
5
|
+
it('registers', async () => {
|
6
|
+
expect(window.customElements.get('glide-core-textarea')).to.equal(GlideCoreTextarea);
|
7
|
+
});
|
8
|
+
it('is accessible', async () => {
|
9
|
+
const template = `<glide-core-textarea value="value" label="label"></glide-core-textarea>`;
|
10
|
+
const element = await fixture(template);
|
11
|
+
await expect(element).to.be.accessible();
|
12
|
+
});
|
13
|
+
it('renders a textarea with two rows and value when attribute `value` is set ', async () => {
|
14
|
+
const template = `<glide-core-textarea value="value" label="label"></glide-core-textarea>`;
|
15
|
+
const element = await fixture(template);
|
16
|
+
const textarea = element.shadowRoot.querySelector('textarea');
|
17
|
+
expect(element);
|
18
|
+
expect(element).to.have.attribute('rows', '2');
|
19
|
+
expect(textarea).to.exist;
|
20
|
+
expect(textarea).to.have.attribute('rows', '2');
|
21
|
+
});
|
22
|
+
it('renders the `rows` attribute on the textarea when set', async () => {
|
23
|
+
const template = `<glide-core-textarea value="value" label="label" rows="5"></glide-core-textarea>`;
|
24
|
+
const element = await fixture(template);
|
25
|
+
const textarea = element.shadowRoot.querySelector('textarea');
|
26
|
+
expect(textarea).to.have.attribute('rows', '5');
|
27
|
+
});
|
28
|
+
it('renders a label when attribute `label` is set', async () => {
|
29
|
+
const template = `<glide-core-textarea value="value" label="label"></glide-core-textarea>`;
|
30
|
+
const element = await fixture(template);
|
31
|
+
const label = element.shadowRoot.querySelector('label');
|
32
|
+
expect(label).to.exist;
|
33
|
+
expect(label?.textContent?.trim()).to.be.equal('label');
|
34
|
+
});
|
35
|
+
it('renders the textarea as readonly when attribute `readonly` is set', async () => {
|
36
|
+
const template = `<glide-core-textarea value="value" label="label" readonly></glide-core-textarea>`;
|
37
|
+
const element = await fixture(template);
|
38
|
+
const textarea = element.shadowRoot.querySelector('textarea');
|
39
|
+
expect(textarea).to.have.attribute('readonly');
|
40
|
+
});
|
41
|
+
it('renders the textarea as disabled when attribute `disabled` is set', async () => {
|
42
|
+
const template = `<glide-core-textarea value="value" label="label" disabled></glide-core-textarea>`;
|
43
|
+
const element = await fixture(template);
|
44
|
+
const textarea = element.shadowRoot.querySelector('textarea');
|
45
|
+
expect(textarea).to.have.attribute('disabled');
|
46
|
+
});
|
47
|
+
it('renders the textarea with a placeholder when attribute `placeholder` is set', async () => {
|
48
|
+
const template = `<glide-core-textarea value="" label="label" placeholder="placeholder"></glide-core-textarea>`;
|
49
|
+
const element = await fixture(template);
|
50
|
+
const textarea = element.shadowRoot.querySelector('textarea');
|
51
|
+
expect(textarea).to.have.attribute('placeholder', 'placeholder');
|
52
|
+
});
|
53
|
+
it('renders `required` on textarea when set', async () => {
|
54
|
+
const template = `<glide-core-textarea value="value" label="label" required></glide-core-textarea>`;
|
55
|
+
const element = await fixture(template);
|
56
|
+
const textarea = element.shadowRoot.querySelector('textarea');
|
57
|
+
expect(textarea).to.have.attribute('required');
|
58
|
+
});
|
59
|
+
it('renders a `name` attribute on the textarea when set', async () => {
|
60
|
+
const template = `<glide-core-textarea value="value" label="label" name="test-name"></glide-core-textarea>`;
|
61
|
+
const element = await fixture(template);
|
62
|
+
const textarea = element.shadowRoot.querySelector('textarea');
|
63
|
+
expect(textarea).to.have.attribute('name', 'test-name');
|
64
|
+
});
|
65
|
+
it('supports a "tooltip" slot', async () => {
|
66
|
+
const template = `
|
67
|
+
<glide-core-textarea value="value" label="label" required>
|
68
|
+
<div slot="tooltip">Tooltip</div>
|
69
|
+
</glide-core-textarea>
|
70
|
+
`;
|
71
|
+
const element = await fixture(template);
|
72
|
+
const assignedElements = element.shadowRoot
|
73
|
+
?.querySelector('slot[name="tooltip"]')
|
74
|
+
?.assignedElements();
|
75
|
+
expect(assignedElements?.at(0)?.textContent).to.equal('Tooltip');
|
76
|
+
});
|
77
|
+
it('renders a slot with description', async () => {
|
78
|
+
const template = `<glide-core-textarea value="value" label="label"><span slot="description" data-test-content>Description</slot></glide-core-textarea>`;
|
79
|
+
const element = await fixture(template);
|
80
|
+
expect(element).to.exist;
|
81
|
+
const contentRendered = element.querySelector('[data-test-content]');
|
82
|
+
expect(contentRendered).to.exist;
|
83
|
+
expect(contentRendered?.textContent).to.be.equal('Description');
|
84
|
+
});
|
85
|
+
it('renders a character count when attribute `maxlength` is set greater than zero', async () => {
|
86
|
+
const template = `<glide-core-textarea value="value" label="label" maxlength="10"><span slot="description">Description</span></glide-core-textarea>`;
|
87
|
+
const element = await fixture(template);
|
88
|
+
const container = element.shadowRoot.querySelector('[data-test-maxlength]');
|
89
|
+
expect(container?.textContent?.trim()).to.be.equal('5/10');
|
90
|
+
});
|
91
|
+
it('does not render a character count when attribute `maxlength` is set less than than zero', async () => {
|
92
|
+
const template = `<glide-core-textarea value="value" label="label" maxlength="0"><span slot="description" data-test-content>Description</span></glide-core-textarea>`;
|
93
|
+
const element = await fixture(template);
|
94
|
+
const container = element.shadowRoot.querySelector('[data-test-description-container]');
|
95
|
+
expect(container?.textContent?.trim()).to.be.equal('');
|
96
|
+
});
|
97
|
+
it('focuses the textarea when the label is clicked', async () => {
|
98
|
+
const template = `<glide-core-textarea value="value" label="label"></glide-core-textarea>`;
|
99
|
+
const element = await fixture(template);
|
100
|
+
const label = element.shadowRoot.querySelector('label');
|
101
|
+
label?.click();
|
102
|
+
expect(element).to.have.focus;
|
103
|
+
await expect(element.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.be.equal('textarea');
|
104
|
+
});
|
105
|
+
it('has tabbable textarea', async () => {
|
106
|
+
const template = `<glide-core-textarea value="value" label="label"></glide-core-textarea>`;
|
107
|
+
const element = await fixture(template);
|
108
|
+
await sendKeys({ press: 'Tab' });
|
109
|
+
expect(element).to.have.focus;
|
110
|
+
await expect(element.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.be.equal('textarea');
|
111
|
+
});
|
112
|
+
it('renders text when typed into text area', async () => {
|
113
|
+
const template = `<glide-core-textarea value="" label="label"></glide-core-textarea>`;
|
114
|
+
const element = await fixture(template);
|
115
|
+
const textarea = element.shadowRoot.querySelector('textarea');
|
116
|
+
element.focus();
|
117
|
+
await sendKeys({ type: 'test text' });
|
118
|
+
expect(textarea?.value).to.equal('test text');
|
119
|
+
});
|
120
|
+
it('returns the content of the textarea when getting the `value` property', async () => {
|
121
|
+
const template = `<glide-core-textarea value="" label="label"></glide-core-textarea>`;
|
122
|
+
const element = await fixture(template);
|
123
|
+
element.focus();
|
124
|
+
await sendKeys({ type: 'test text' });
|
125
|
+
expect(element.value).to.equal('test text');
|
126
|
+
});
|
127
|
+
it('focuses the textarea when `focus` is called', async () => {
|
128
|
+
const template = `<glide-core-textarea value="" label="label"></glide-core-textarea>`;
|
129
|
+
const element = await fixture(template);
|
130
|
+
element.focus();
|
131
|
+
await expect(element.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.be.equal('textarea');
|
132
|
+
});
|
133
|
+
it('blurs the textarea when `blur` is called', async () => {
|
134
|
+
const template = `<glide-core-textarea value="" label="label"></glide-core-textarea>`;
|
135
|
+
const element = await fixture(template);
|
136
|
+
element.focus();
|
137
|
+
await expect(element.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.be.equal('textarea');
|
138
|
+
element.blur();
|
139
|
+
await expect(element.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.not.equal('textarea');
|
140
|
+
});
|