@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.
Files changed (208) hide show
  1. package/dist/accordion.js +1 -1
  2. package/dist/accordion.styles.js +4 -4
  3. package/dist/accordion.test.basics.js +109 -0
  4. package/dist/accordion.test.events.js +39 -0
  5. package/dist/button-group.button.js +1 -1
  6. package/dist/button-group.button.styles.js +4 -4
  7. package/dist/button-group.button.test.basics.js +169 -0
  8. package/dist/button-group.button.test.events.js +73 -0
  9. package/dist/button-group.js +1 -1
  10. package/dist/button-group.styles.js +3 -3
  11. package/dist/button-group.test.basics.js +268 -0
  12. package/dist/button-group.test.events.js +291 -0
  13. package/dist/button.js +1 -1
  14. package/dist/button.styles.js +4 -4
  15. package/dist/button.test.basics.js +196 -0
  16. package/dist/button.test.events.js +25 -0
  17. package/dist/button.test.form.js +49 -0
  18. package/dist/checkbox-group.js +1 -1
  19. package/dist/checkbox-group.styles.js +2 -2
  20. package/dist/checkbox-group.test.basics.js +119 -0
  21. package/dist/checkbox-group.test.events.js +110 -0
  22. package/dist/checkbox-group.test.focus.js +45 -0
  23. package/dist/checkbox-group.test.form.js +130 -0
  24. package/dist/checkbox-group.test.validity.js +75 -0
  25. package/dist/checkbox.js +1 -1
  26. package/dist/checkbox.styles.js +3 -3
  27. package/dist/checkbox.test.basics.js +89 -0
  28. package/dist/checkbox.test.events.js +87 -0
  29. package/dist/checkbox.test.focus.js +38 -0
  30. package/dist/checkbox.test.form.js +115 -0
  31. package/dist/checkbox.test.states.js +62 -0
  32. package/dist/checkbox.test.validity.js +51 -0
  33. package/dist/drawer.d.ts +2 -2
  34. package/dist/drawer.js +1 -15
  35. package/dist/drawer.styles.js +18 -3
  36. package/dist/drawer.test.accessibility.js +22 -0
  37. package/dist/drawer.test.basics.js +43 -0
  38. package/dist/drawer.test.closing.js +37 -0
  39. package/dist/drawer.test.events.js +52 -0
  40. package/dist/drawer.test.methods.js +34 -0
  41. package/dist/dropdown.d.ts +4 -2
  42. package/dist/dropdown.js +1 -1
  43. package/dist/dropdown.option.d.ts +1 -3
  44. package/dist/dropdown.option.js +1 -1
  45. package/dist/dropdown.option.styles.js +2 -2
  46. package/dist/dropdown.option.test.basics.js +59 -0
  47. package/dist/dropdown.option.test.basics.multiple.js +26 -0
  48. package/dist/dropdown.option.test.basics.single.js +20 -0
  49. package/dist/dropdown.option.test.events.js +27 -0
  50. package/dist/dropdown.option.test.focus.js +11 -0
  51. package/dist/dropdown.option.test.interactions.multiple.js +87 -0
  52. package/dist/dropdown.option.test.interactions.single.js +22 -0
  53. package/dist/dropdown.styles.js +28 -9
  54. package/dist/dropdown.test.basics.filterable.js +84 -0
  55. package/dist/dropdown.test.basics.js +233 -0
  56. package/dist/dropdown.test.basics.multiple.js +270 -0
  57. package/dist/dropdown.test.basics.single.js +79 -0
  58. package/dist/dropdown.test.events.js +268 -0
  59. package/dist/dropdown.test.events.multiple.js +130 -0
  60. package/dist/dropdown.test.focus.d.ts +1 -0
  61. package/dist/dropdown.test.focus.filterable.js +154 -0
  62. package/dist/dropdown.test.focus.js +18 -0
  63. package/dist/dropdown.test.focus.multiple.js +181 -0
  64. package/dist/dropdown.test.focus.single.js +53 -0
  65. package/dist/dropdown.test.form.js +140 -0
  66. package/dist/dropdown.test.form.multiple.js +149 -0
  67. package/dist/dropdown.test.form.single.js +128 -0
  68. package/dist/dropdown.test.interactions.filterable.js +385 -0
  69. package/dist/dropdown.test.interactions.js +446 -0
  70. package/dist/dropdown.test.interactions.multiple.js +908 -0
  71. package/dist/dropdown.test.interactions.single.js +466 -0
  72. package/dist/dropdown.test.validity.js +46 -0
  73. package/dist/icon-button.js +1 -1
  74. package/dist/icon-button.styles.js +3 -3
  75. package/dist/icon-button.test.basics.js +103 -0
  76. package/dist/icons/checked.js +1 -1
  77. package/dist/icons/magnifying-glass.js +1 -1
  78. package/dist/input.js +1 -1
  79. package/dist/input.styles.js +3 -3
  80. package/dist/input.test.basics.js +169 -0
  81. package/dist/input.test.events.js +97 -0
  82. package/dist/input.test.focus.js +54 -0
  83. package/dist/input.test.form.js +56 -0
  84. package/dist/input.test.validity.js +50 -0
  85. package/dist/label.js +1 -1
  86. package/dist/label.styles.js +3 -3
  87. package/dist/label.test.basics.js +129 -0
  88. package/dist/library/expect-argument-error.js +1 -1
  89. package/dist/library/ow.js +1 -1
  90. package/dist/library/ow.test.js +55 -0
  91. package/dist/menu.button.d.ts +1 -2
  92. package/dist/menu.button.js +1 -1
  93. package/dist/menu.button.styles.js +3 -3
  94. package/dist/menu.button.test.basics.js +42 -0
  95. package/dist/menu.d.ts +4 -0
  96. package/dist/menu.js +1 -1
  97. package/dist/menu.link.d.ts +1 -2
  98. package/dist/menu.link.js +1 -1
  99. package/dist/menu.link.styles.js +3 -3
  100. package/dist/menu.link.test.basics.js +46 -0
  101. package/dist/menu.styles.js +13 -6
  102. package/dist/menu.test.basics.js +161 -0
  103. package/dist/menu.test.focus.d.ts +0 -1
  104. package/dist/menu.test.focus.js +66 -0
  105. package/dist/menu.test.interactions.d.ts +0 -1
  106. package/dist/menu.test.interactions.js +522 -0
  107. package/dist/modal.icon-button.js +1 -1
  108. package/dist/modal.icon-button.styles.js +2 -2
  109. package/dist/modal.icon-button.test.basics.js +45 -0
  110. package/dist/modal.js +1 -15
  111. package/dist/modal.styles.js +4 -4
  112. package/dist/modal.tertiary-icon.js +1 -1
  113. package/dist/modal.tertiary-icon.test.basics.js +59 -0
  114. package/dist/modal.test.accessibility.js +48 -0
  115. package/dist/modal.test.basics.js +203 -0
  116. package/dist/modal.test.close.js +38 -0
  117. package/dist/modal.test.events.js +110 -0
  118. package/dist/modal.test.lock-scroll.js +76 -0
  119. package/dist/modal.test.methods.js +23 -0
  120. package/dist/modal.test.scrollbars.js +19 -0
  121. package/dist/radio-group.js +1 -1
  122. package/dist/radio-group.styles.js +2 -2
  123. package/dist/radio-group.test.basics.js +323 -0
  124. package/dist/radio-group.test.events.js +277 -0
  125. package/dist/radio-group.test.focus.js +75 -0
  126. package/dist/radio-group.test.form.js +104 -0
  127. package/dist/radio-group.test.validity.js +228 -0
  128. package/dist/radio.js +1 -1
  129. package/dist/radio.styles.js +4 -4
  130. package/dist/split-button.d.ts +24 -0
  131. package/dist/split-button.js +1 -0
  132. package/dist/split-button.stories.d.ts +17 -0
  133. package/dist/split-button.styles.d.ts +2 -0
  134. package/dist/split-button.styles.js +103 -0
  135. package/dist/split-button.test.basics.d.ts +1 -0
  136. package/dist/split-button.test.basics.js +84 -0
  137. package/dist/split-container.d.ts +30 -0
  138. package/dist/split-container.js +1 -0
  139. package/dist/split-container.styles.d.ts +2 -0
  140. package/dist/split-container.styles.js +132 -0
  141. package/dist/split-container.test.basics.d.ts +3 -0
  142. package/dist/split-container.test.basics.js +445 -0
  143. package/dist/split-container.test.interactions.d.ts +1 -0
  144. package/dist/split-container.test.interactions.js +20 -0
  145. package/dist/split-link.d.ts +25 -0
  146. package/dist/split-link.js +1 -0
  147. package/dist/split-link.test.basics.d.ts +1 -0
  148. package/dist/split-link.test.basics.js +92 -0
  149. package/dist/split-link.test.interactions.d.ts +1 -0
  150. package/dist/split-link.test.interactions.js +19 -0
  151. package/dist/status-indicator.js +1 -1
  152. package/dist/status-indicator.styles.js +2 -2
  153. package/dist/status-indicator.test.basics.js +102 -0
  154. package/dist/styles/focus-outline.js +1 -4
  155. package/dist/styles/visually-hidden.js +1 -11
  156. package/dist/tab.group.js +1 -1
  157. package/dist/tab.group.styles.js +2 -2
  158. package/dist/tab.group.test.basics.js +185 -0
  159. package/dist/tab.js +1 -1
  160. package/dist/tab.panel.js +1 -1
  161. package/dist/tab.panel.styles.js +3 -3
  162. package/dist/tab.styles.js +2 -2
  163. package/dist/tab.test.basics.js +71 -0
  164. package/dist/tag.js +1 -1
  165. package/dist/tag.styles.js +3 -3
  166. package/dist/tag.test.basics.js +118 -0
  167. package/dist/tag.test.events.js +16 -0
  168. package/dist/tag.test.focus.js +11 -0
  169. package/dist/textarea.js +2 -2
  170. package/dist/textarea.styles.js +3 -3
  171. package/dist/textarea.test.basics.js +140 -0
  172. package/dist/textarea.test.events.js +204 -0
  173. package/dist/textarea.test.form.js +70 -0
  174. package/dist/textarea.test.validity.js +83 -0
  175. package/dist/toasts.js +1 -1
  176. package/dist/toasts.styles.js +2 -2
  177. package/dist/toasts.test.basics.js +94 -0
  178. package/dist/toasts.toast.js +1 -1
  179. package/dist/toasts.toast.styles.js +5 -2
  180. package/dist/toasts.toast.test.basics.js +139 -0
  181. package/dist/toggle.js +1 -1
  182. package/dist/toggle.styles.js +3 -3
  183. package/dist/toggle.test.basics.js +64 -0
  184. package/dist/toggle.test.events.js +29 -0
  185. package/dist/toggle.test.focus.js +9 -0
  186. package/dist/toggle.test.states.js +35 -0
  187. package/dist/tooltip.js +1 -1
  188. package/dist/tooltip.styles.js +3 -3
  189. package/dist/tooltip.test.basics.js +64 -0
  190. package/dist/tooltip.test.interactions.js +78 -0
  191. package/dist/tree.item.icon-button.js +1 -1
  192. package/dist/tree.item.icon-button.styles.js +2 -2
  193. package/dist/tree.item.icon-button.test.basics.js +13 -0
  194. package/dist/tree.item.js +1 -1
  195. package/dist/tree.item.menu.js +1 -1
  196. package/dist/tree.item.menu.styles.js +2 -2
  197. package/dist/tree.item.menu.test.basics.js +34 -0
  198. package/dist/tree.item.styles.js +2 -2
  199. package/dist/tree.item.test.basics.js +102 -0
  200. package/dist/tree.js +1 -1
  201. package/dist/tree.styles.js +2 -2
  202. package/dist/tree.test.aria.js +86 -0
  203. package/dist/tree.test.basics.js +123 -0
  204. package/dist/tree.test.events.js +19 -0
  205. package/dist/tree.test.focus.js +261 -0
  206. package/package.json +20 -18
  207. /package/dist/{dropdown.option.test.focus.multiple.d.ts → dropdown.option.test.focus.d.ts} +0 -0
  208. /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
- "use strict";var y=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var h=(t,e,o,c)=>{for(var s=c>1?void 0:c?H(e,o):e,E=t.length-1,L;E>=0;E--)(L=t[E])&&(s=(c?L(e,o,s):L(s))||s);return c&&s&&y(e,o,s),s};var k=(t,e,o)=>{if(!e.has(t))throw TypeError("Cannot "+o)};var i=(t,e,o)=>(k(t,e,"read from private field"),o?o.call(t):e.get(t)),r=(t,e,o)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,o)};var g=(t,e,o)=>(k(t,e,"access private method"),o);var m,a,n,v,p,f,b,x;import{LitElement as w,html as $}from"lit";import{classMap as M}from"lit/directives/class-map.js";import{createRef as u,ref as d}from"lit/directives/ref.js";import{customElement as z,property as R}from"lit/decorators.js";import{owSlot as S}from"./library/ow.js";import{when as D}from"lit/directives/when.js";import j from"./tag.styles.js";let l=class extends w{constructor(){super(...arguments);r(this,b);this.size="medium";this.removableLabel="";r(this,m,u());r(this,a,u());r(this,n,u());r(this,v,u());r(this,p,200);r(this,f,()=>{new Promise(()=>setTimeout(()=>{this.remove()},i(this,p))),i(this,a).value?.classList.toggle("activate"),i(this,a).value?.classList.toggle("deactivate"),this.dispatchEvent(new Event("remove"))})}click(){i(this,m).value?.click()}firstUpdated(){S(i(this,n).value)}render(){return $`<div class="${M({component:!0,activate:!0,[this.size]:!0})}" ${d(i(this,a))}><slot name="prefix" ${d(i(this,v))}></slot><slot @slotchange="${g(this,b,x)}" ${d(i(this,n))}></slot>${D(this.removableLabel,()=>$`<button type="button" class="${M({[this.size]:!0})}" aria-label="Remove ${this.removableLabel}" data-test="button" ${d(i(this,m))} @click="${i(this,f)}"><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>`}};m=new WeakMap,a=new WeakMap,n=new WeakMap,v=new WeakMap,p=new WeakMap,f=new WeakMap,b=new WeakSet,x=function(){S(i(this,n).value)},l.shadowRootOptions={...w.shadowRootOptions,delegatesFocus:!0,mode:"closed"},l.styles=j,h([R({reflect:!0})],l.prototype,"size",2),h([R({attribute:"removable-label"})],l.prototype,"removableLabel",2),l=h([z("glide-core-tag")],l);export{l as default};
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;
@@ -1,4 +1,4 @@
1
- "use strict";import{css as e}from"lit";import i from"./styles/focus-outline.js";export default[e`
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
- ${i};
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
- "use strict";var O=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var l=(a,s,t,d)=>{for(var u=d>1?void 0:d?N(s,t):s,E=a.length-1,k;E>=0;E--)(k=a[E])&&(u=(d?k(s,t,u):k(u))||u);return d&&u&&O(s,t,u),u};var w=(a,s,t)=>{if(!s.has(a))throw TypeError("Cannot "+t)};var e=(a,s,t)=>(w(a,s,"read from private field"),t?t.call(a):s.get(a)),o=(a,s,t)=>{if(s.has(a))throw TypeError("Cannot add the same private member more than once");s instanceof WeakSet?s.add(a):s.set(a,t)},S=(a,s,t,d)=>(w(a,s,"write to private field"),d?d.call(a,t):s.set(a,t),t);var c=(a,s,t)=>(w(a,s,"access private method"),t);var n,h,f,b,R,m,p,$,F,V,M,y,I,v,g;import"./label.js";import{LitElement as A,html as q}from"lit";import{classMap as z}from"lit/directives/class-map.js";import{createRef as D,ref as H}from"lit/directives/ref.js";import{customElement as U,property as r,state as B}from"lit/decorators.js";import{ifDefined as L}from"lit/directives/if-defined.js";import{when as j}from"lit/directives/when.js";import x from"./textarea.styles.js";let i=class extends A{constructor(){super();o(this,b);o(this,m);o(this,$);o(this,V);o(this,y);o(this,v);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;o(this,n,void 0);o(this,h,D());o(this,f,({formData:t})=>{this.value.length>0&&this.name&&this.value&&!this.disabled&&t.append(this.name,this.value)});S(this,n,this.attachInternals()),this.addEventListener("invalid",c(this,y,I))}blur(){e(this,h).value?.blur()}checkValidity(){return this.isCheckingValidity=!0,e(this,n).checkValidity()}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",e(this,f)),this.removeEventListener("invalid",c(this,y,I))}get form(){return e(this,n).form}get validity(){return e(this,n).validity}get willValidate(){return e(this,n).willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",e(this,f))}formResetCallback(){this.value=this.getAttribute("value")??""}render(){return q`<glide-core-label orientation="${this.orientation}" ?disabled="${this.disabled}" ?error="${e(this,b,R)||e(this,m,p)}" ?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="${z({error:e(this,b,R)||e(this,m,p)})}" id="textarea" name="${L(this.name)}" placeholder="${L(this.placeholder)}" rows="${this.rows}" autocapitalize="${L(this.autocapitalize)}" spellcheck="${this.spellcheck}" ?required="${this.required}" ?readonly="${this.readonly}" ?disabled="${this.disabled}" aria-describedby="meta" ${H(e(this,h))} @input="${c(this,V,M)}" @change="${c(this,$,F)}">
2
- </textarea></div><div class="meta" data-test-description-container id="meta" slot="description"><slot name="description"></slot>${j(this.maxlength,()=>q`<div class="${z({"character-count":!0,error:e(this,m,p)})}" data-test-maxlength>${this.value.length}/${this.maxlength}</div>`)}</div></glide-core-label>`}reportValidity(){return e(this,n).reportValidity()}updated(){e(this,h).value&&(e(this,h).value.value=this.value),c(this,v,g).call(this)}};n=new WeakMap,h=new WeakMap,f=new WeakMap,b=new WeakSet,R=function(){return!this.disabled&&!this.readonly&&!this.validity.valid&&this.isReportValidityOrSubmit},m=new WeakSet,p=function(){return!this.maxlength||this.disabled?!1:this.value.length>this.maxlength},$=new WeakSet,F=function(t){const d=e(this,h).value.value;this.value=d,c(this,v,g).call(this),this.dispatchEvent(new Event(t.type,t))},V=new WeakSet,M=function(){const t=e(this,h).value.value;this.value=t,e(this,n).setFormValue(this.value),c(this,v,g).call(this)},y=new WeakSet,I=function(t){t.preventDefault(),this.isCheckingValidity||(this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!0)},v=new WeakSet,g=async function(){const t=e(this,h).value;e(this,m,p)?e(this,n).setValidity({...t?.validity,tooLong:!0}," ",t):e(this,n).setValidity(t?.validity,t?.validationMessage,t),await this.updateComplete},i.formAssociated=!0,i.shadowRootOptions={...A.shadowRootOptions,mode:"closed",delegatesFocus:!0},i.styles=x,l([r()],i.prototype,"value",2),l([r()],i.prototype,"label",2),l([r({attribute:"hide-label",type:Boolean})],i.prototype,"hideLabel",2),l([r({reflect:!0})],i.prototype,"orientation",2),l([r()],i.prototype,"placeholder",2),l([r({reflect:!0,type:Number})],i.prototype,"rows",2),l([r({type:Boolean})],i.prototype,"required",2),l([r({type:Boolean})],i.prototype,"readonly",2),l([r({type:Boolean})],i.prototype,"disabled",2),l([r({type:Number,converter(t){return t&&Number.parseInt(t,10)}})],i.prototype,"maxlength",2),l([r({reflect:!0})],i.prototype,"name",2),l([r({type:Boolean})],i.prototype,"spellcheck",2),l([r()],i.prototype,"autocapitalize",2),l([B()],i.prototype,"isCheckingValidity",2),l([B()],i.prototype,"isReportValidityOrSubmit",2),i=l([U("glide-core-textarea")],i);export{i as default};
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;
@@ -1,4 +1,4 @@
1
- "use strict";import{css as e}from"lit";export default e`
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-base-gray-light);
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
+ });