@crowdstrike/glide-core 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/README.md +44 -5
  2. package/dist/accordion.test.basics.js +1 -0
  3. package/dist/accordion.test.events.js +1 -0
  4. package/dist/button-group.button.d.ts +14 -15
  5. package/dist/button-group.button.js +1 -1
  6. package/dist/button-group.button.styles.js +75 -52
  7. package/dist/button-group.button.test.basics.d.ts +1 -1
  8. package/dist/button-group.button.test.basics.js +84 -147
  9. package/dist/button-group.button.test.events.js +9 -67
  10. package/dist/button-group.button.test.focus.js +13 -0
  11. package/dist/button-group.button.test.interactions.d.ts +1 -0
  12. package/dist/button-group.button.test.interactions.js +42 -0
  13. package/dist/button-group.d.ts +7 -10
  14. package/dist/button-group.js +1 -1
  15. package/dist/button-group.stories.d.ts +1 -5
  16. package/dist/button-group.styles.js +18 -6
  17. package/dist/button-group.test.basics.js +114 -234
  18. package/dist/button-group.test.events.js +211 -263
  19. package/dist/button-group.test.focus.d.ts +1 -0
  20. package/dist/button-group.test.focus.js +39 -0
  21. package/dist/button-group.test.interactions.d.ts +1 -0
  22. package/dist/button-group.test.interactions.js +91 -0
  23. package/dist/button.test.basics.js +2 -1
  24. package/dist/button.test.events.js +1 -0
  25. package/dist/button.test.form.js +1 -0
  26. package/dist/checkbox-group.js +1 -1
  27. package/dist/checkbox-group.styles.js +1 -1
  28. package/dist/checkbox-group.test.basics.js +2 -1
  29. package/dist/checkbox-group.test.events.js +5 -4
  30. package/dist/checkbox-group.test.focus.js +5 -3
  31. package/dist/checkbox-group.test.form.js +1 -0
  32. package/dist/checkbox-group.test.validity.js +1 -0
  33. package/dist/checkbox.d.ts +7 -1
  34. package/dist/checkbox.js +1 -1
  35. package/dist/checkbox.styles.js +11 -3
  36. package/dist/checkbox.test.basics.js +1 -0
  37. package/dist/checkbox.test.events.js +5 -4
  38. package/dist/checkbox.test.focus.js +2 -2
  39. package/dist/checkbox.test.form.js +1 -0
  40. package/dist/{checkbox.test.states.js → checkbox.test.interactions.js} +25 -1
  41. package/dist/checkbox.test.validity.js +1 -0
  42. package/dist/drawer.js +1 -1
  43. package/dist/drawer.test.basics.js +1 -0
  44. package/dist/drawer.test.closing.js +1 -0
  45. package/dist/drawer.test.events.js +1 -0
  46. package/dist/drawer.test.methods.js +1 -0
  47. package/dist/dropdown.d.ts +6 -4
  48. package/dist/dropdown.js +1 -1
  49. package/dist/dropdown.option.d.ts +7 -2
  50. package/dist/dropdown.option.js +1 -1
  51. package/dist/dropdown.option.styles.js +13 -0
  52. package/dist/dropdown.option.test.basics.js +7 -3
  53. package/dist/dropdown.option.test.basics.multiple.js +1 -0
  54. package/dist/dropdown.option.test.basics.single.js +1 -0
  55. package/dist/dropdown.option.test.events.js +2 -1
  56. package/dist/dropdown.option.test.focus.js +1 -1
  57. package/dist/dropdown.option.test.interactions.multiple.js +2 -54
  58. package/dist/dropdown.option.test.interactions.single.js +52 -9
  59. package/dist/dropdown.styles.js +20 -19
  60. package/dist/dropdown.test.basics.filterable.js +1 -0
  61. package/dist/dropdown.test.basics.js +144 -2
  62. package/dist/dropdown.test.basics.multiple.js +6 -3
  63. package/dist/dropdown.test.basics.single.js +1 -1
  64. package/dist/dropdown.test.events.filterable.js +74 -0
  65. package/dist/dropdown.test.events.js +50 -160
  66. package/dist/dropdown.test.events.multiple.js +268 -10
  67. package/dist/dropdown.test.events.single.js +202 -4
  68. package/dist/dropdown.test.focus.filterable.js +9 -5
  69. package/dist/dropdown.test.focus.js +2 -1
  70. package/dist/dropdown.test.focus.multiple.js +1 -2
  71. package/dist/dropdown.test.focus.single.js +1 -1
  72. package/dist/dropdown.test.form.js +1 -0
  73. package/dist/dropdown.test.form.multiple.js +1 -0
  74. package/dist/dropdown.test.form.single.js +1 -0
  75. package/dist/dropdown.test.interactions.filterable.js +69 -11
  76. package/dist/dropdown.test.interactions.js +95 -5
  77. package/dist/dropdown.test.interactions.multiple.js +203 -6
  78. package/dist/dropdown.test.interactions.single.js +69 -6
  79. package/dist/dropdown.test.validity.js +1 -0
  80. package/dist/form-controls-layout.test.basics.js +2 -1
  81. package/dist/icon-button.test.basics.js +2 -1
  82. package/dist/icons/checked.d.ts +1 -1
  83. package/dist/icons/checked.js +1 -1
  84. package/dist/icons/magnifying-glass.js +1 -1
  85. package/dist/input.d.ts +0 -6
  86. package/dist/input.js +1 -1
  87. package/dist/input.styles.js +7 -2
  88. package/dist/input.test.basics.js +20 -5
  89. package/dist/input.test.events.js +5 -4
  90. package/dist/input.test.focus.js +5 -4
  91. package/dist/input.test.form.js +1 -0
  92. package/dist/input.test.translations.d.ts +1 -0
  93. package/dist/input.test.translations.js +38 -0
  94. package/dist/input.test.validity.js +134 -4
  95. package/dist/label.d.ts +1 -1
  96. package/dist/label.js +1 -1
  97. package/dist/label.styles.js +29 -20
  98. package/dist/label.test.basics.js +27 -24
  99. package/dist/library/expect-argument-error.js +1 -1
  100. package/dist/library/localize.d.ts +5 -1
  101. package/dist/library/ow.test.d.ts +2 -1
  102. package/dist/library/ow.test.js +8 -3
  103. package/dist/menu.button.test.basics.js +1 -0
  104. package/dist/menu.d.ts +3 -5
  105. package/dist/menu.js +1 -1
  106. package/dist/menu.link.test.basics.js +1 -0
  107. package/dist/menu.options.test.basics.js +3 -2
  108. package/dist/menu.styles.js +1 -15
  109. package/dist/menu.test.basics.d.ts +1 -2
  110. package/dist/menu.test.basics.js +23 -6
  111. package/dist/menu.test.events.d.ts +1 -0
  112. package/dist/menu.test.events.js +2 -1
  113. package/dist/menu.test.focus.d.ts +1 -0
  114. package/dist/menu.test.focus.js +14 -6
  115. package/dist/menu.test.interactions.js +213 -56
  116. package/dist/modal.icon-button.test.basics.js +2 -1
  117. package/dist/modal.js +1 -1
  118. package/dist/modal.styles.js +18 -13
  119. package/dist/modal.tertiary-icon.d.ts +0 -1
  120. package/dist/modal.tertiary-icon.js +1 -1
  121. package/dist/modal.tertiary-icon.test.basics.js +2 -1
  122. package/dist/modal.test.accessibility.js +1 -0
  123. package/dist/modal.test.basics.js +2 -1
  124. package/dist/modal.test.close.js +1 -0
  125. package/dist/modal.test.events.js +11 -10
  126. package/dist/modal.test.lock-scroll.js +1 -0
  127. package/dist/modal.test.methods.js +1 -0
  128. package/dist/modal.test.scrollbars.js +1 -0
  129. package/dist/radio-group.js +1 -1
  130. package/dist/radio-group.styles.js +1 -1
  131. package/dist/radio-group.test.basics.js +1 -0
  132. package/dist/radio-group.test.events.js +1 -0
  133. package/dist/radio-group.test.focus.js +4 -3
  134. package/dist/radio-group.test.form.js +1 -0
  135. package/dist/radio-group.test.validity.js +1 -0
  136. package/dist/radio.d.ts +1 -0
  137. package/dist/radio.js +1 -1
  138. package/dist/radio.styles.js +33 -0
  139. package/dist/split-button.test.basics.js +1 -0
  140. package/dist/split-container.test.basics.js +5 -0
  141. package/dist/split-link.test.basics.js +1 -0
  142. package/dist/split-link.test.interactions.js +2 -1
  143. package/dist/styles/variables.css +1 -1
  144. package/dist/tab.d.ts +1 -3
  145. package/dist/tab.group.d.ts +3 -5
  146. package/dist/tab.group.js +1 -1
  147. package/dist/tab.group.styles.js +27 -13
  148. package/dist/tab.group.test.basics.js +8 -57
  149. package/dist/tab.group.test.interactions.d.ts +3 -0
  150. package/dist/tab.group.test.interactions.js +454 -0
  151. package/dist/tab.js +1 -1
  152. package/dist/tab.panel.d.ts +1 -0
  153. package/dist/tab.panel.js +1 -1
  154. package/dist/tab.panel.styles.js +11 -1
  155. package/dist/tab.styles.js +7 -68
  156. package/dist/tab.test.basics.js +0 -20
  157. package/dist/tabs.stories.d.ts +1 -2
  158. package/dist/tag.test.basics.js +3 -2
  159. package/dist/textarea.d.ts +0 -1
  160. package/dist/textarea.js +2 -2
  161. package/dist/textarea.stories.d.ts +3 -4
  162. package/dist/textarea.styles.js +14 -3
  163. package/dist/textarea.test.basics.js +81 -44
  164. package/dist/textarea.test.events.js +57 -41
  165. package/dist/textarea.test.form.js +1 -0
  166. package/dist/textarea.test.translations.d.ts +1 -0
  167. package/dist/textarea.test.translations.js +34 -0
  168. package/dist/textarea.test.validity.js +105 -20
  169. package/dist/toasts.js +1 -1
  170. package/dist/toasts.styles.js +8 -1
  171. package/dist/toasts.test.basics.js +20 -0
  172. package/dist/toggle.js +1 -1
  173. package/dist/toggle.test.basics.js +1 -0
  174. package/dist/toggle.test.events.js +1 -0
  175. package/dist/toggle.test.focus.js +1 -1
  176. package/dist/toggle.test.interactions.d.ts +1 -0
  177. package/dist/{toggle.test.states.js → toggle.test.interactions.js} +1 -0
  178. package/dist/tooltip.d.ts +7 -5
  179. package/dist/tooltip.js +1 -1
  180. package/dist/tooltip.styles.js +90 -25
  181. package/dist/tooltip.test.basics.js +39 -3
  182. package/dist/tooltip.test.interactions.js +137 -34
  183. package/dist/translations/en.js +1 -1
  184. package/dist/translations/fr.js +1 -1
  185. package/dist/translations/ja.js +1 -1
  186. package/dist/tree.d.ts +0 -1
  187. package/dist/tree.item.d.ts +2 -3
  188. package/dist/tree.item.js +1 -1
  189. package/dist/tree.item.menu.d.ts +0 -1
  190. package/dist/tree.item.menu.js +1 -1
  191. package/dist/tree.item.test.basics.js +1 -0
  192. package/dist/tree.js +1 -1
  193. package/dist/tree.test.basics.js +2 -1
  194. package/dist/tree.test.events.js +1 -1
  195. package/package.json +40 -29
  196. package/dist/drawer.test.floating-components.d.ts +0 -1
  197. package/dist/drawer.test.floating-components.js +0 -51
  198. package/dist/library/set-containing-block.d.ts +0 -15
  199. package/dist/library/set-containing-block.js +0 -1
  200. package/dist/modal.test.floating-components.js +0 -62
  201. /package/dist/{checkbox.test.states.d.ts → button-group.button.test.focus.d.ts} +0 -0
  202. /package/dist/{modal.test.floating-components.d.ts → checkbox.test.interactions.d.ts} +0 -0
  203. /package/dist/{toggle.test.states.d.ts → dropdown.test.events.filterable.d.ts} +0 -0
@@ -1,5 +1,6 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import { ArgumentError } from 'ow';
2
- import { assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
3
+ import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
3
4
  import { sendKeys } from '@web/test-runner-commands';
4
5
  import GlideCoreDropdown from './dropdown.js';
5
6
  import GlideCoreDropdownOption from './dropdown.option.js';
@@ -20,7 +21,11 @@ it('opens on click', async () => {
20
21
  component.shadowRoot
21
22
  ?.querySelector('[data-test="button"]')
22
23
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
24
+ // Wait for it to open.
25
+ await aTimeout(0);
26
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
23
27
  expect(component.open).to.be.true;
28
+ expect(options?.checkVisibility()).to.be.true;
24
29
  });
25
30
  it('toggles open and closed when the button is clicked', async () => {
26
31
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
@@ -36,7 +41,10 @@ it('toggles open and closed when the button is clicked', async () => {
36
41
  component.shadowRoot
37
42
  ?.querySelector('[data-test="button"]')
38
43
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
44
+ await elementUpdated(component);
45
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
39
46
  expect(component.open).to.be.false;
47
+ expect(options?.checkVisibility()).to.be.false;
40
48
  });
41
49
  it('does not toggle open and closed when the button overflow text is clicked', async () => {
42
50
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
@@ -52,7 +60,11 @@ it('does not toggle open and closed when the button overflow text is clicked', a
52
60
  component.shadowRoot
53
61
  ?.querySelector('[data-test="tag-overflow-text"]')
54
62
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
63
+ // Wait for it to open.
64
+ await aTimeout(0);
65
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
55
66
  expect(component.open).to.be.true;
67
+ expect(options?.checkVisibility()).to.be.true;
56
68
  });
57
69
  it('selects an option on click', async () => {
58
70
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
@@ -61,6 +73,8 @@ it('selects an option on click', async () => {
61
73
  value="one"
62
74
  ></glide-core-dropdown-option>
63
75
  </glide-core-dropdown>`);
76
+ // Wait for it to open.
77
+ await aTimeout(0);
64
78
  const option = component.querySelector('glide-core-dropdown-option');
65
79
  option?.click();
66
80
  await elementUpdated(component);
@@ -76,11 +90,26 @@ it('selects an option on Space', async () => {
76
90
  value="one"
77
91
  ></glide-core-dropdown-option>
78
92
  </glide-core-dropdown>`);
93
+ // Wait for it to open.
94
+ await aTimeout(0);
79
95
  const option = component.querySelector('glide-core-dropdown-option');
80
96
  option?.focus();
81
97
  await sendKeys({ press: ' ' });
82
98
  expect(option?.selected).to.be.true;
83
99
  });
100
+ it('does not deselect options on Space', async () => {
101
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
102
+ <glide-core-dropdown-option
103
+ label="One"
104
+ value="one"
105
+ selected
106
+ ></glide-core-dropdown-option>
107
+ </glide-core-dropdown>`);
108
+ component?.focus();
109
+ await sendKeys({ press: ' ' });
110
+ const option = component.querySelector('glide-core-dropdown-option');
111
+ expect(option?.selected).to.be.true;
112
+ });
84
113
  it('selects an option on Enter', async () => {
85
114
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
86
115
  <glide-core-dropdown-option
@@ -88,6 +117,8 @@ it('selects an option on Enter', async () => {
88
117
  value="one"
89
118
  ></glide-core-dropdown-option>
90
119
  </glide-core-dropdown>`);
120
+ // Wait for it to open.
121
+ await aTimeout(0);
91
122
  const option = component.querySelector('glide-core-dropdown-option');
92
123
  option?.focus();
93
124
  await sendKeys({ press: 'Enter' });
@@ -121,6 +152,17 @@ it('closes when an option is selected via click', async () => {
121
152
  component.querySelector('glide-core-dropdown-option')?.click();
122
153
  expect(component.open).to.be.false;
123
154
  });
155
+ it('closes when an option is selected via Space', async () => {
156
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
157
+ <glide-core-dropdown-option
158
+ label="Label"
159
+ value="value"
160
+ ></glide-core-dropdown-option>
161
+ </glide-core-dropdown>`);
162
+ component.focus();
163
+ await sendKeys({ press: ' ' });
164
+ expect(component.open).to.be.false;
165
+ });
124
166
  it('closes when an option is selected via Enter', async () => {
125
167
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
126
168
  <glide-core-dropdown-option
@@ -128,6 +170,19 @@ it('closes when an option is selected via Enter', async () => {
128
170
  value="value"
129
171
  ></glide-core-dropdown-option>
130
172
  </glide-core-dropdown>`);
173
+ component.focus();
174
+ await sendKeys({ press: 'Enter' });
175
+ expect(component.open).to.be.false;
176
+ });
177
+ it('closes when an option is selected via Enter', async () => {
178
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
179
+ <glide-core-dropdown-option
180
+ label="Label"
181
+ value="value"
182
+ ></glide-core-dropdown-option>
183
+ </glide-core-dropdown>`);
184
+ // Wait for it to open.
185
+ await aTimeout(0);
131
186
  component.querySelector('glide-core-dropdown-option')?.focus();
132
187
  await sendKeys({ press: 'Enter' });
133
188
  expect(component.open).to.be.false;
@@ -139,6 +194,8 @@ it('closes when an option is selected via Space', async () => {
139
194
  value="value"
140
195
  ></glide-core-dropdown-option>
141
196
  </glide-core-dropdown>`);
197
+ // Wait for it to open.
198
+ await aTimeout(0);
142
199
  const option = component.querySelector('glide-core-dropdown-option');
143
200
  option?.focus();
144
201
  await sendKeys({ press: ' ' });
@@ -210,7 +267,7 @@ it('throws when `value` is changed programmatically to include more than one val
210
267
  spy();
211
268
  }
212
269
  }
213
- expect(spy.called).to.be.true;
270
+ expect(spy.callCount).to.equal(1);
214
271
  });
215
272
  it('updates `value` when an option `value` is changed programmatically', async () => {
216
273
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
@@ -273,6 +330,8 @@ it('updates `value` when an option is selected via Enter', async () => {
273
330
 
274
331
  <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
275
332
  </glide-core-dropdown>`);
333
+ // Wait for it to open.
334
+ await aTimeout(0);
276
335
  const options = component.querySelectorAll('glide-core-dropdown-option');
277
336
  options[0].focus();
278
337
  await sendKeys({ press: 'Enter' });
@@ -282,7 +341,7 @@ it('updates `value` when an option is selected via Enter', async () => {
282
341
  ?.querySelector('[data-test="button"]')
283
342
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
284
343
  // Wait for it to open.
285
- await elementUpdated(component);
344
+ await aTimeout(0);
286
345
  options[1].focus();
287
346
  await sendKeys({ press: 'Enter' });
288
347
  expect(component.value).to.deep.equal(['two']);
@@ -291,7 +350,7 @@ it('updates `value` when an option is selected via Enter', async () => {
291
350
  ?.querySelector('[data-test="button"]')
292
351
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
293
352
  // Wait for it to open.
294
- await elementUpdated(component);
353
+ await aTimeout(0);
295
354
  options[2].focus();
296
355
  await sendKeys({ press: 'Enter' });
297
356
  expect(component.value).to.deep.equal([]);
@@ -310,6 +369,8 @@ it('updates `value` when an option is selected via Space', async () => {
310
369
 
311
370
  <glide-core-dropdown-option label="Three"></glide-core-dropdown-option>
312
371
  </glide-core-dropdown>`);
372
+ // Wait for it to open.
373
+ await aTimeout(0);
313
374
  const options = component.querySelectorAll('glide-core-dropdown-option');
314
375
  options[0].focus();
315
376
  await sendKeys({ press: ' ' });
@@ -319,7 +380,7 @@ it('updates `value` when an option is selected via Space', async () => {
319
380
  ?.querySelector('[data-test="button"]')
320
381
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
321
382
  // Wait for it to open.
322
- await elementUpdated(component);
383
+ await aTimeout(0);
323
384
  options[1].focus();
324
385
  await sendKeys({ press: ' ' });
325
386
  expect(component.value).to.deep.equal(['two']);
@@ -328,7 +389,7 @@ it('updates `value` when an option is selected via Space', async () => {
328
389
  ?.querySelector('[data-test="button"]')
329
390
  ?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
330
391
  // Wait for it to open.
331
- await elementUpdated(component);
392
+ await aTimeout(0);
332
393
  options[2].focus();
333
394
  await sendKeys({ press: ' ' });
334
395
  expect(component.value).to.deep.equal([]);
@@ -441,6 +502,8 @@ it('does not select an option on Enter when the option is not focused', async ()
441
502
  value="two"
442
503
  ></glide-core-dropdown-option>
443
504
  </glide-core-dropdown>`);
505
+ // Wait for it to open.
506
+ await aTimeout(0);
444
507
  const option = component.querySelector('glide-core-dropdown-option');
445
508
  option?.focus();
446
509
  await sendKeys({ down: 'Tab' });
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './dropdown.option.js';
2
3
  import { expect, fixture, html } from '@open-wc/testing';
3
4
  import GlideCoreDropdown from './dropdown.js';
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './checkbox.js';
2
3
  import './input.js';
3
4
  import { ArgumentError } from 'ow';
@@ -48,7 +49,7 @@ it('throws if it does not have a default slot', async () => {
48
49
  spy();
49
50
  }
50
51
  }
51
- expect(spy.called).to.be.true;
52
+ expect(spy.callCount).to.equal(1);
52
53
  });
53
54
  it('throws if its default slot is the incorrect type', async () => {
54
55
  await expectArgumentError(() => {
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './icon-button.js';
2
3
  import { ArgumentError } from 'ow';
3
4
  import { assert, expect, fixture, html } from '@open-wc/testing';
@@ -106,5 +107,5 @@ it('throws if it does not have a default slot', async () => {
106
107
  spy();
107
108
  }
108
109
  }
109
- expect(spy.called).to.be.true;
110
+ expect(spy.callCount).to.equal(1);
110
111
  });
@@ -1,2 +1,2 @@
1
- declare const _default: import("lit").TemplateResult;
1
+ declare const _default: import("lit").TemplateResult<1>;
2
2
  export default _default;
@@ -1 +1 @@
1
- import{svg}from"lit/static-html.js";export default svg`<svg fill="none" viewBox="0 0 24 24" style="height: var(--size, 0.875rem); width: var(--size, 0.875rem);"><path d="M20 6L9 17L4 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
1
+ import{html}from"lit";export default html`<svg fill="none" viewBox="0 0 24 24" style="height: var(--size, 0.875rem); width: var(--size, 0.875rem);"><path d="M20 6L9 17L4 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
@@ -1 +1 @@
1
- import{svg}from"lit/static-html.js";export default svg`<svg class="search-icon" fill="none" width="16" height="16" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"/></svg>`;
1
+ import{svg}from"lit/static-html.js";export default svg`<svg class="search-icon" data-test="search-icon" fill="none" width="16" height="16" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"/></svg>`;
package/dist/input.d.ts CHANGED
@@ -41,24 +41,18 @@ export default class GlideCoreInput extends LitElement {
41
41
  disabled: boolean;
42
42
  privateSplit?: 'left' | 'middle';
43
43
  maxlength?: number;
44
- descriptionNodes: NodeListOf<HTMLElement>;
45
- prefixIconNodes: NodeListOf<HTMLElement>;
46
- suffixIconNodes: NodeListOf<HTMLElement>;
47
44
  get form(): HTMLFormElement | null;
48
45
  get validity(): ValidityState;
49
46
  get willValidate(): boolean;
50
47
  blur(): void;
51
48
  checkValidity(): boolean;
52
49
  disconnectedCallback(): void;
53
- firstUpdated(): void;
54
50
  formAssociatedCallback(): void;
55
51
  formResetCallback(): void;
56
- get isTypeSearch(): boolean;
57
52
  get hasClearIcon(): boolean;
58
53
  get isClearIconVisible(): boolean;
59
54
  render(): import("lit").TemplateResult<1>;
60
55
  reportValidity(): boolean;
61
- get valueCharacterCount(): number;
62
56
  constructor();
63
57
  private hasFocus;
64
58
  private isBlurring;
package/dist/input.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(t,e,i,o){var r,s=arguments.length,a=s<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,i,o);else for(var l=t.length-1;l>=0;l--)(r=t[l])&&(a=(s<3?r(a):s>3?r(e,i,a):r(e,i))||a);return s>3&&a&&Object.defineProperty(e,i,a),a};import"./icon-button.js";import"./label.js";import{LitElement,html,nothing}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,queryAssignedNodes,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import magnifyingGlassIcon from"./icons/magnifying-glass.js";import ow from"./library/ow.js";import styles from"./input.styles.js";export const SUPPORTED_TYPES=["email","number","password","search","tel","text","url"];let GlideCoreInput=class GlideCoreInput extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}get form(){return this.#t.form}get validity(){return this.#t.validity}get willValidate(){return this.#t.willValidate}blur(){this.#e?.blur()}checkValidity(){this.isCheckingValidity=!0;const t=this.#t.checkValidity();return this.isCheckingValidity=!1,t}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i)}firstUpdated(){this.#o()}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){this.value=this.getAttribute("value")??""}get isTypeSearch(){return"search"===this.type}get hasClearIcon(){return this.clearable&&!this.disabled&&!this.readonly}get isClearIconVisible(){return this.hasClearIcon&&this.value.length>0}render(){return html`<glide-core-label class="${classMap({left:"left"===this.privateSplit,middle:"middle"===this.privateSplit})}" orientation="${this.orientation}" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?error="${this.#r||this.#s}" ?hide="${this.hideLabel}" ?required="${this.required}"><slot name="tooltip" slot="tooltip"></slot><label for="input">${this.label}</label><div class="${classMap({"input-box":!0,focused:this.hasFocus,empty:""===this.value,disabled:this.disabled,readonly:this.readonly&&!this.disabled,error:this.#r||this.#s})}" slot="control"><slot name="prefix"></slot><input aria-describedby="meta" id="input" type="${"password"===this.type&&this.passwordVisible?"text":this.type}" .value="${this.value}" placeholder="${ifDefined(this.placeholder)}" autocapitalize="${ifDefined(this.autocapitalize)}" spellcheck="${this.spellcheck}" ?required="${this.required}" ?readonly="${this.readonly}" ?disabled="${this.disabled}" @focus="${this.#a}" @blur="${this.#l}" @change="${this.#n}" @input="${this.#d}" ${ref(this.#p)}> ${this.hasClearIcon?html`<glide-core-icon-button variant="tertiary" class="${classMap({"clear-icon-button":!0,"clear-icon-button--visible":this.isClearIconVisible})}" aria-label="${this.#h.term("clearEntry")}" @click="${this.#c}" tabindex="-1"><slot name="clear-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M6 6L18 18" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></slot></glide-core-icon-button>`:""} ${"password"===this.type&&this.passwordToggle&&!this.disabled?html`<glide-core-icon-button variant="tertiary" class="password-toggle" aria-label="${this.passwordVisible?"Hide password":"Show password"}" aria-controls="input" aria-expanded="${this.passwordVisible?"true":"false"}" @click="${this.#u}" tabindex="-1">${this.passwordVisible?html`<svg width="16" height="16" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"/></svg>`:html`<svg width="16" height="16" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"/><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/></svg>`}</glide-core-icon-button>`:""}<div class="suffix">${this.isTypeSearch?magnifyingGlassIcon:html`<slot name="suffix"></slot>`}</div></div><div class="meta" id="meta" slot="description"><slot class="description" name="description"></slot>${this.maxlength?html`<div class="${classMap({"character-count":!0,error:this.#s})}">${this.valueCharacterCount}/${this.maxlength}</div>`:nothing}</div></glide-core-label>`}reportValidity(){this.isReportValidityOrSubmit=!0;const t=this.#t.reportValidity();return this.requestUpdate(),t}get valueCharacterCount(){return this.value.length}constructor(){super(),this.type="text",this.value="",this.hideLabel=!1,this.orientation="horizontal",this.clearable=!1,this.spellcheck=!1,this.autocapitalize="on",this.passwordToggle=!1,this.required=!1,this.readonly=!1,this.disabled=!1,this.hasFocus=!1,this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.passwordVisible=!1,this.#p=createRef(),this.#h=new LocalizeController(this),this.#i=({formData:t})=>{this.name&&this.value&&!this.disabled&&t.append(this.name,this.value)},this.#t=this.attachInternals(),this.addEventListener("invalid",(t=>{if(t?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}))}#p;#t;#h;#i;get#s(){return Boolean(this.maxlength&&this.valueCharacterCount>this.maxlength)}get#r(){return!this.disabled&&!this.validity?.valid&&this.isReportValidityOrSubmit}get#e(){return this.#p.value}#l(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1,this.hasFocus=!1}#n(t){ow(this.#e,ow.object.instanceOf(HTMLInputElement)),this.value=this.#e.value,this.#o(),this.dispatchEvent(new Event(t.type,t))}#c(t){this.value="",this.dispatchEvent(new Event("clear",{bubbles:!0})),this.#e?.focus(),this.#o(),t.stopPropagation()}#a(){this.hasFocus=!0}#d(){ow(this.#e,ow.object.instanceOf(HTMLInputElement)),this.value=this.#e.value,this.#o()}#u(){this.passwordVisible=!this.passwordVisible}async#o(){await this.updateComplete,this.#t.setValidity(this.#e?.validity,this.#e?.validationMessage,this.#e),this.isReportValidityOrSubmit&&this.reportValidity()}};__decorate([property()],GlideCoreInput.prototype,"type",void 0),__decorate([property({reflect:!0})],GlideCoreInput.prototype,"name",void 0),__decorate([property()],GlideCoreInput.prototype,"value",void 0),__decorate([property()],GlideCoreInput.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreInput.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreInput.prototype,"orientation",void 0),__decorate([property()],GlideCoreInput.prototype,"placeholder",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"clearable",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"spellcheck",void 0),__decorate([property()],GlideCoreInput.prototype,"autocapitalize",void 0),__decorate([property({attribute:"password-toggle",type:Boolean})],GlideCoreInput.prototype,"passwordToggle",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreInput.prototype,"required",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"readonly",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"disabled",void 0),__decorate([property()],GlideCoreInput.prototype,"privateSplit",void 0),__decorate([property({type:Number,converter:t=>t&&Number.parseInt(t,10)})],GlideCoreInput.prototype,"maxlength",void 0),__decorate([queryAssignedNodes({slot:"description"})],GlideCoreInput.prototype,"descriptionNodes",void 0),__decorate([queryAssignedNodes({slot:"prefix"})],GlideCoreInput.prototype,"prefixIconNodes",void 0),__decorate([queryAssignedNodes({slot:"suffix"})],GlideCoreInput.prototype,"suffixIconNodes",void 0),__decorate([state()],GlideCoreInput.prototype,"hasFocus",void 0),__decorate([state()],GlideCoreInput.prototype,"isBlurring",void 0),__decorate([state()],GlideCoreInput.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreInput.prototype,"isReportValidityOrSubmit",void 0),__decorate([state()],GlideCoreInput.prototype,"passwordVisible",void 0),GlideCoreInput=__decorate([customElement("glide-core-input")],GlideCoreInput);export default GlideCoreInput;
1
+ var __decorate=this&&this.__decorate||function(e,t,i,o){var r,s=arguments.length,a=s<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,o);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(a=(s<3?r(a):s>3?r(t,i,a):r(t,i))||a);return s>3&&a&&Object.defineProperty(t,i,a),a};import"./icon-button.js";import"./label.js";import{LitElement,html,nothing}from"lit";import{LocalizeController}from"./library/localize.js";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 magnifyingGlassIcon from"./icons/magnifying-glass.js";import ow from"./library/ow.js";import styles from"./input.styles.js";export const SUPPORTED_TYPES=["email","number","password","search","tel","text","url"];let GlideCoreInput=class GlideCoreInput extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}get form(){return this.#e.form}get validity(){return!this.required||this.value||this.disabled?this.#t?this.#e.setValidity({tooLong:!0}," ",this.#i.value):this.#e.setValidity({}):this.#e.setValidity({valueMissing:!0}," ",this.#i.value),this.#e.validity}get willValidate(){return this.#e.willValidate}blur(){this.#i.value?.blur()}checkValidity(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#o)}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#o)}formResetCallback(){this.value=this.getAttribute("value")??""}get hasClearIcon(){return this.clearable&&!this.disabled&&!this.readonly}get isClearIconVisible(){return this.hasClearIcon&&this.value.length>0}render(){return html`<glide-core-private-label class="${classMap({left:"left"===this.privateSplit,middle:"middle"===this.privateSplit})}" orientation="${this.orientation}" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?error="${this.#r||this.#t}" ?hide="${this.hideLabel}" ?required="${this.required}"><slot name="tooltip" slot="tooltip"></slot><label for="input">${this.label}</label><div class="${classMap({"input-container":!0,focused:this.hasFocus,empty:""===this.value,disabled:this.disabled,readonly:this.readonly&&!this.disabled,error:this.#r||this.#t})}" slot="control"><slot name="prefix"></slot><input aria-describedby="meta" aria-invalid="${this.#r||this.#t}" id="input" type="${"password"===this.type&&this.passwordVisible?"text":this.type}" .value="${this.value}" placeholder="${ifDefined(this.placeholder)}" autocapitalize="${ifDefined(this.autocapitalize)}" spellcheck="${this.spellcheck}" ?required="${this.required}" ?readonly="${this.readonly}" ?disabled="${this.disabled}" @focus="${this.#s}" @blur="${this.#a}" @change="${this.#l}" @input="${this.#n}" ${ref(this.#i)}> ${this.hasClearIcon?html`<glide-core-icon-button variant="tertiary" class="${classMap({"clear-icon-button":!0,"clear-icon-button--visible":this.isClearIconVisible})}" data-test="clear-button" label="${this.#d.term("clearEntry",this.label)}" @click="${this.#h}"><svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M6 6L18 18" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-icon-button>`:nothing} ${"password"===this.type&&this.passwordToggle&&!this.disabled?html`<glide-core-icon-button variant="tertiary" class="password-toggle" data-test="password-toggle" label="${this.passwordVisible?"Hide password":"Show password"}" aria-controls="input" aria-expanded="${this.passwordVisible?"true":"false"}" @click="${this.#p}">${this.passwordVisible?html`<svg aria-hidden="true" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"/></svg>`:html`<svg aria-hidden="true" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"/><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/></svg>`}</glide-core-icon-button>`:nothing}<div class="suffix">${"search"===this.type?magnifyingGlassIcon:html`<slot name="suffix"></slot>`}</div></div><div class="meta" id="meta" slot="description"><slot class="description" name="description"></slot>${this.maxlength?html`<div class="${classMap({"character-count":!0,error:this.#t})}" data-test="character-count-container"><span aria-hidden="true" data-test="character-count-text">${this.#d.term("displayedCharacterCount",this.#c,this.maxlength)} </span><span class="hidden" data-test="character-count-announcement">${this.#d.term("announcedCharacterCount",this.#c,this.maxlength)}</span></div>`:nothing}</div></glide-core-private-label>`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#e.reportValidity();return this.requestUpdate(),e}constructor(){super(),this.type="text",this.value="",this.hideLabel=!1,this.orientation="horizontal",this.clearable=!1,this.spellcheck=!1,this.autocapitalize="on",this.passwordToggle=!1,this.required=!1,this.readonly=!1,this.disabled=!1,this.hasFocus=!1,this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.passwordVisible=!1,this.#i=createRef(),this.#d=new LocalizeController(this),this.#o=({formData:e})=>{this.name&&this.value&&!this.disabled&&e.append(this.name,this.value)},this.#e=this.attachInternals(),this.addEventListener("invalid",(e=>{if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}))}#i;#e;#d;get#c(){return this.value.length}#o;get#t(){return Boolean(!this.disabled&&!this.readonly&&this.maxlength&&this.#c>this.maxlength)}get#r(){return!this.disabled&&!this.validity?.valid&&this.isReportValidityOrSubmit}#a(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1,this.hasFocus=!1}#l(e){ow(this.#i.value,ow.object.instanceOf(HTMLInputElement)),this.value=this.#i.value?.value,this.dispatchEvent(new Event(e.type,e))}#h(e){this.value="",this.dispatchEvent(new Event("clear",{bubbles:!0})),this.#i.value?.focus(),e.stopPropagation()}#s(){this.hasFocus=!0}#n(){ow(this.#i.value,ow.object.instanceOf(HTMLInputElement)),this.value=this.#i.value.value}#p(){this.passwordVisible=!this.passwordVisible}};__decorate([property()],GlideCoreInput.prototype,"type",void 0),__decorate([property({reflect:!0})],GlideCoreInput.prototype,"name",void 0),__decorate([property()],GlideCoreInput.prototype,"value",void 0),__decorate([property()],GlideCoreInput.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreInput.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreInput.prototype,"orientation",void 0),__decorate([property()],GlideCoreInput.prototype,"placeholder",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"clearable",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"spellcheck",void 0),__decorate([property()],GlideCoreInput.prototype,"autocapitalize",void 0),__decorate([property({attribute:"password-toggle",type:Boolean})],GlideCoreInput.prototype,"passwordToggle",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreInput.prototype,"required",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"readonly",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"disabled",void 0),__decorate([property()],GlideCoreInput.prototype,"privateSplit",void 0),__decorate([property({type:Number,converter:e=>e&&Number.parseInt(e,10)})],GlideCoreInput.prototype,"maxlength",void 0),__decorate([state()],GlideCoreInput.prototype,"hasFocus",void 0),__decorate([state()],GlideCoreInput.prototype,"isBlurring",void 0),__decorate([state()],GlideCoreInput.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreInput.prototype,"isReportValidityOrSubmit",void 0),__decorate([state()],GlideCoreInput.prototype,"passwordVisible",void 0),GlideCoreInput=__decorate([customElement("glide-core-input")],GlideCoreInput);export default GlideCoreInput;
@@ -1,4 +1,4 @@
1
- import{css}from"lit";export default css`
1
+ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";export default css`
2
2
  .meta {
3
3
  column-gap: var(--glide-core-spacing-xs);
4
4
  display: flex;
@@ -15,6 +15,10 @@ import{css}from"lit";export default css`
15
15
  &.error {
16
16
  font-weight: var(--glide-core-font-weight-bold);
17
17
  }
18
+
19
+ .hidden {
20
+ ${visuallyHidden};
21
+ }
18
22
  }
19
23
 
20
24
  .search-icon {
@@ -22,7 +26,7 @@ import{css}from"lit";export default css`
22
26
  display: flex;
23
27
  }
24
28
 
25
- .input-box {
29
+ .input-container {
26
30
  align-items: center;
27
31
  background-color: var(--glide-core-surface-base-lighter);
28
32
  block-size: 2.125rem;
@@ -41,6 +45,7 @@ import{css}from"lit";export default css`
41
45
 
42
46
  &.focused:not(.error) {
43
47
  border-color: var(--glide-core-border-focus);
48
+ transition: border-color 200ms ease-in-out;
44
49
  }
45
50
 
46
51
  /* We had to resort to a class selector because there may be a bug in Chrome and Safari
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import { expect, fixture, html } from '@open-wc/testing';
2
3
  import { sendKeys } from '@web/test-runner-commands';
3
4
  import GlideCoreInput from './input.js';
@@ -53,7 +54,7 @@ it('changes to type text when password is revealed', async () => {
53
54
  const inputElement = element.shadowRoot?.querySelector('input');
54
55
  expect(inputElement).to.exist;
55
56
  expect(inputElement?.getAttribute('type')).to.equal('password');
56
- const passwordToggle = element.shadowRoot?.querySelector('.password-toggle');
57
+ const passwordToggle = element.shadowRoot?.querySelector('[data-test="password-toggle"]');
57
58
  passwordToggle?.click();
58
59
  await element.updateComplete;
59
60
  expect(inputElement?.getAttribute('type')).to.equal('text');
@@ -65,7 +66,7 @@ it('shows search icon with type search', async () => {
65
66
  const inputElement = element.shadowRoot?.querySelector('input');
66
67
  expect(inputElement).to.exist;
67
68
  expect(inputElement?.getAttribute('type')).to.equal('search');
68
- const searchIcon = element.shadowRoot?.querySelector('.search-icon');
69
+ const searchIcon = element.shadowRoot?.querySelector('[data-test="search-icon"]');
69
70
  expect(searchIcon).to.exist;
70
71
  });
71
72
  it('when using "focus() on input", the native input is focused', async () => {
@@ -99,7 +100,7 @@ it('clearable attribute allows for a button which can clear input', async () =>
99
100
  const element = await fixture(html `
100
101
  <glide-core-input label="Test" clearable></glide-core-input>
101
102
  `);
102
- const clearButton = element.shadowRoot?.querySelector('.clear-icon-button');
103
+ const clearButton = element.shadowRoot?.querySelector('[data-test="clear-button"]');
103
104
  element.focus();
104
105
  await sendKeys({ type: 'testing' });
105
106
  expect(element.value).to.be.equal('testing');
@@ -118,8 +119,22 @@ it('displays a max character and current character count if maxlength is provide
118
119
  const element = await fixture(html `
119
120
  <glide-core-input label="Test label" maxlength="5"></glide-core-input>
120
121
  `);
121
- const maxCharacterCountContainer = element.shadowRoot?.querySelector('.character-count');
122
- expect(maxCharacterCountContainer?.textContent?.trim()).to.be.equal('0/5');
122
+ const maxCharacterCountText = element.shadowRoot?.querySelector('[data-test="character-count-text"]');
123
+ expect(maxCharacterCountText?.textContent?.trim()).to.equal('0/5');
124
+ });
125
+ it('displays visually hidden character count text for screenreaders', async () => {
126
+ const element = await fixture(html `
127
+ <glide-core-input label="Test label" maxlength="5"></glide-core-input>
128
+ `);
129
+ const maxCharacterCountAnnouncement = element.shadowRoot?.querySelector('[data-test="character-count-announcement"]');
130
+ expect(maxCharacterCountAnnouncement?.textContent?.trim()).to.equal('Character count 0 of 5');
131
+ });
132
+ it('does not render a character count when attribute `maxlength` is set less than than zero', async () => {
133
+ const element = await fixture(html `
134
+ <glide-core-input label="Test label" maxlength="0"></glide-core-input>
135
+ `);
136
+ const container = element.shadowRoot?.querySelector('[data-test="character-count-container"]');
137
+ expect(container).to.be.null;
123
138
  });
124
139
  it('supports a "tooltip" slot', async () => {
125
140
  const component = await fixture(html `<glide-core-input label="test">
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './input.js';
2
3
  import * as sinon from 'sinon';
3
4
  import { aTimeout, expect, fixture, html, oneEvent } from '@open-wc/testing';
@@ -64,7 +65,7 @@ it('does not dispatch an "invalid" event after `checkValidity` is called when no
64
65
  input.addEventListener('invalid', spy);
65
66
  input.checkValidity();
66
67
  await aTimeout(0);
67
- expect(spy.notCalled).to.be.true;
68
+ expect(spy.callCount).to.equal(0);
68
69
  });
69
70
  it('does not dispatch an "invalid" event after `checkValidity` is called when required and no value but disabled', async () => {
70
71
  const form = document.createElement('form');
@@ -73,7 +74,7 @@ it('does not dispatch an "invalid" event after `checkValidity` is called when re
73
74
  input.addEventListener('invalid', spy);
74
75
  input.checkValidity();
75
76
  await aTimeout(0);
76
- expect(spy.notCalled).to.be.true;
77
+ expect(spy.callCount).to.equal(0);
77
78
  });
78
79
  it('does not dispatch an "invalid" event when `reportValidity` is called when not required,', async () => {
79
80
  const form = document.createElement('form');
@@ -84,7 +85,7 @@ it('does not dispatch an "invalid" event when `reportValidity` is called when no
84
85
  input.addEventListener('invalid', spy);
85
86
  input.reportValidity();
86
87
  await aTimeout(0);
87
- expect(spy.notCalled).to.be.true;
88
+ expect(spy.callCount).to.equal(0);
88
89
  });
89
90
  it('does not dispatch an "invalid" event when `reportValidity` is called when required and no value but disabled', async () => {
90
91
  const form = document.createElement('form');
@@ -93,5 +94,5 @@ it('does not dispatch an "invalid" event when `reportValidity` is called when re
93
94
  input.addEventListener('invalid', spy);
94
95
  input.reportValidity();
95
96
  await aTimeout(0);
96
- expect(spy.notCalled).to.be.true;
97
+ expect(spy.callCount).to.equal(0);
97
98
  });
@@ -1,8 +1,9 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './input.js';
2
3
  import { expect, fixture, html } from '@open-wc/testing';
3
- import Input from './input.js';
4
- Input.shadowRootOptions.mode = 'open';
5
- it('focuses the input when `focus` is called', async () => {
4
+ import GlideCoreInput from './input.js';
5
+ GlideCoreInput.shadowRootOptions.mode = 'open';
6
+ it('focuses the input when `focus()` is called', async () => {
6
7
  const input = await fixture(html `<glide-core-input required></glide-core-input>`);
7
8
  input.focus();
8
9
  const inputElement = input.shadowRoot?.querySelector('input');
@@ -26,7 +27,7 @@ it('blurs the input and reports validity if `blur` is called', async () => {
26
27
  await input.updateComplete;
27
28
  expect(input.shadowRoot?.activeElement).to.equal(null);
28
29
  expect(input.validity.valid).to.equal(false);
29
- expect(input.shadowRoot?.querySelector('glide-core-label')?.error).to.equal(true);
30
+ expect(input.shadowRoot?.querySelector('glide-core-private-label')?.error).to.equal(true);
30
31
  });
31
32
  it('focuses the input after `reportValidity` is called when required and no value', async () => {
32
33
  const form = document.createElement('form');
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './input.js';
2
3
  import { expect, fixture, html } from '@open-wc/testing';
3
4
  it('can be reset to initial value', async () => {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,38 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
3
+ import GlideCoreInput from './input.js';
4
+ GlideCoreInput.shadowRootOptions.mode = 'open';
5
+ it('renders dynamic strings in Japanese', async () => {
6
+ const element = await fixture(html `
7
+ <glide-core-input
8
+ label="Test"
9
+ value="lorem"
10
+ maxlength="40"
11
+ clearable
12
+ ></glide-core-input>
13
+ `);
14
+ document.documentElement.setAttribute('lang', 'ja');
15
+ await elementUpdated(element);
16
+ const maxCharacterCountText = element.shadowRoot?.querySelector('[data-test="character-count-text"]');
17
+ expect(maxCharacterCountText?.textContent?.trim()).to.equal('5/40');
18
+ const maxCharacterCountAnnouncement = element.shadowRoot?.querySelector('[data-test="character-count-announcement"]');
19
+ expect(maxCharacterCountAnnouncement?.textContent?.trim()).to.equal('Character count 5 of 40');
20
+ expect(element.shadowRoot?.querySelector('[data-test="clear-button"]')?.label).to.equal('Clear Test entry');
21
+ });
22
+ it('renders dynamic strings in French', async () => {
23
+ const element = await fixture(html `
24
+ <glide-core-input
25
+ label="Test"
26
+ value="lorem"
27
+ maxlength="40"
28
+ clearable
29
+ ></glide-core-input>
30
+ `);
31
+ document.documentElement.setAttribute('lang', 'fr');
32
+ await elementUpdated(element);
33
+ const maxCharacterCountText = element.shadowRoot?.querySelector('[data-test="character-count-text"]');
34
+ expect(maxCharacterCountText?.textContent?.trim()).to.equal('5/40');
35
+ const maxCharacterCountAnnouncement = element.shadowRoot?.querySelector('[data-test="character-count-announcement"]');
36
+ expect(maxCharacterCountAnnouncement?.textContent?.trim()).to.equal('Character count 5 of 40');
37
+ expect(element.shadowRoot?.querySelector('[data-test="clear-button"]')?.label).to.equal('Clear Test entry');
38
+ });