@crowdstrike/glide-core 0.12.2 → 0.13.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 (63) hide show
  1. package/dist/accordion.d.ts +1 -1
  2. package/dist/accordion.styles.js +2 -1
  3. package/dist/button-group.js +1 -1
  4. package/dist/button-group.stories.d.ts +0 -1
  5. package/dist/button-group.test.events.js +2 -0
  6. package/dist/checkbox-group.styles.js +1 -1
  7. package/dist/checkbox.styles.js +6 -3
  8. package/dist/drawer.js +1 -1
  9. package/dist/dropdown.d.ts +8 -1
  10. package/dist/dropdown.js +140 -74
  11. package/dist/dropdown.option.js +1 -1
  12. package/dist/dropdown.option.styles.js +39 -7
  13. package/dist/dropdown.option.test.interactions.multiple.js +2 -2
  14. package/dist/dropdown.option.test.interactions.single.js +2 -2
  15. package/dist/dropdown.styles.js +121 -16
  16. package/dist/dropdown.test.basics.filterable.js +19 -57
  17. package/dist/dropdown.test.basics.js +24 -244
  18. package/dist/dropdown.test.basics.multiple.js +13 -60
  19. package/dist/dropdown.test.basics.single.js +2 -8
  20. package/dist/dropdown.test.events.filterable.js +12 -66
  21. package/dist/dropdown.test.events.js +75 -49
  22. package/dist/dropdown.test.events.multiple.js +17 -87
  23. package/dist/dropdown.test.events.single.js +12 -60
  24. package/dist/dropdown.test.focus.filterable.js +11 -58
  25. package/dist/dropdown.test.focus.js +62 -9
  26. package/dist/dropdown.test.focus.multiple.js +22 -38
  27. package/dist/dropdown.test.focus.single.js +5 -16
  28. package/dist/dropdown.test.interactions.filterable.js +167 -69
  29. package/dist/dropdown.test.interactions.js +226 -244
  30. package/dist/dropdown.test.interactions.multiple.js +78 -274
  31. package/dist/dropdown.test.interactions.single.js +20 -85
  32. package/dist/dropdown.test.validity.js +12 -49
  33. package/dist/input.d.ts +1 -1
  34. package/dist/input.js +2 -1
  35. package/dist/input.styles.js +44 -30
  36. package/dist/label.js +1 -1
  37. package/dist/label.styles.js +7 -3
  38. package/dist/library/localize.d.ts +2 -0
  39. package/dist/menu.js +1 -1
  40. package/dist/menu.stories.d.ts +1 -0
  41. package/dist/menu.styles.js +1 -1
  42. package/dist/menu.test.interactions.js +1 -1
  43. package/dist/modal.d.ts +1 -1
  44. package/dist/modal.js +1 -1
  45. package/dist/radio-group.stories.d.ts +0 -1
  46. package/dist/radio-group.styles.js +1 -1
  47. package/dist/styles/variables.css +1 -1
  48. package/dist/tab.group.d.ts +0 -1
  49. package/dist/tab.group.js +1 -1
  50. package/dist/tab.group.styles.js +5 -13
  51. package/dist/tab.panel.styles.js +0 -3
  52. package/dist/tabs.stories.d.ts +0 -1
  53. package/dist/tag.js +1 -1
  54. package/dist/tag.styles.js +5 -3
  55. package/dist/tag.test.interactions.js +8 -8
  56. package/dist/textarea.styles.js +1 -1
  57. package/dist/translations/en.js +1 -1
  58. package/dist/translations/fr.d.ts +1 -1
  59. package/dist/translations/fr.js +1 -1
  60. package/dist/translations/ja.d.ts +1 -1
  61. package/dist/translations/ja.js +1 -1
  62. package/dist/tree.stories.d.ts +0 -1
  63. package/package.json +18 -18
@@ -6,60 +6,17 @@ import GlideCoreDropdownOption from './dropdown.option.js';
6
6
  GlideCoreDropdown.shadowRootOptions.mode = 'open';
7
7
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
8
8
  const defaultSlot = html `
9
- <glide-core-dropdown-option
10
- label="One"
11
- value="one"
12
- ></glide-core-dropdown-option>
13
-
14
- <glide-core-dropdown-option
15
- label="Two"
16
- value="two"
17
- ></glide-core-dropdown-option>
18
-
19
- <glide-core-dropdown-option
20
- label="Three"
21
- value="three"
22
- ></glide-core-dropdown-option>
23
-
24
- <glide-core-dropdown-option
25
- label="Four"
26
- value="four"
27
- ></glide-core-dropdown-option>
28
-
29
- <glide-core-dropdown-option
30
- label="Five"
31
- value="five"
32
- ></glide-core-dropdown-option>
33
-
34
- <glide-core-dropdown-option
35
- label="Six"
36
- value="six"
37
- ></glide-core-dropdown-option>
38
-
39
- <glide-core-dropdown-option
40
- label="Seven"
41
- value="seven"
42
- ></glide-core-dropdown-option>
43
-
44
- <glide-core-dropdown-option
45
- label="Eight"
46
- value="eight"
47
- ></glide-core-dropdown-option>
48
-
49
- <glide-core-dropdown-option
50
- label="Nine"
51
- value="nine"
52
- ></glide-core-dropdown-option>
53
-
54
- <glide-core-dropdown-option
55
- label="Ten"
56
- value="ten"
57
- ></glide-core-dropdown-option>
58
-
59
- <glide-core-dropdown-option
60
- label="Eleven"
61
- value="eleven"
62
- ></glide-core-dropdown-option>
9
+ <glide-core-dropdown-option label="One"></glide-core-dropdown-option>
10
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
11
+ <glide-core-dropdown-option label="Three"></glide-core-dropdown-option>
12
+ <glide-core-dropdown-option label="Four"></glide-core-dropdown-option>
13
+ <glide-core-dropdown-option label="Five"></glide-core-dropdown-option>
14
+ <glide-core-dropdown-option label="Six"></glide-core-dropdown-option>
15
+ <glide-core-dropdown-option label="Seven"></glide-core-dropdown-option>
16
+ <glide-core-dropdown-option label="Eight"></glide-core-dropdown-option>
17
+ <glide-core-dropdown-option label="Nine"></glide-core-dropdown-option>
18
+ <glide-core-dropdown-option label="Ten"></glide-core-dropdown-option>
19
+ <glide-core-dropdown-option label="Eleven"></glide-core-dropdown-option>
63
20
  `;
64
21
  it('opens on click', async () => {
65
22
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
@@ -218,6 +175,56 @@ it('hides its magnifying glass icon when multiselect and not filtering', async (
218
175
  const icon = component?.shadowRoot?.querySelector('[data-test="magnifying-glass-icon"]');
219
176
  expect(icon?.checkVisibility()).to.be.not.ok;
220
177
  });
178
+ it('does not clear its filter when a tag is removed via Backspace', async () => {
179
+ const component = await fixture(html `<glide-core-dropdown
180
+ label="Label"
181
+ placeholder="Placeholder"
182
+ filterable
183
+ multiple
184
+ >
185
+ <glide-core-dropdown-option
186
+ label="One"
187
+ selected
188
+ ></glide-core-dropdown-option>
189
+
190
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
191
+ </glide-core-dropdown>`);
192
+ // Wait for it to open.
193
+ await aTimeout(0);
194
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
195
+ input?.select();
196
+ input?.focus();
197
+ await sendKeys({ type: 'o' });
198
+ await sendKeys({ press: 'ArrowLeft' });
199
+ await sendKeys({ press: 'Backspace' });
200
+ expect(input?.value).to.equal('o');
201
+ });
202
+ it('does not clear its filter when every tag is removed via Meta + Backspace', async () => {
203
+ const component = await fixture(html `<glide-core-dropdown
204
+ label="Label"
205
+ placeholder="Placeholder"
206
+ filterable
207
+ multiple
208
+ >
209
+ <glide-core-dropdown-option
210
+ label="One"
211
+ selected
212
+ ></glide-core-dropdown-option>
213
+
214
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
215
+ </glide-core-dropdown>`);
216
+ // Wait for it to open.
217
+ await aTimeout(0);
218
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
219
+ input?.select();
220
+ input?.focus();
221
+ await sendKeys({ type: 'o' });
222
+ await sendKeys({ press: 'ArrowLeft' });
223
+ await sendKeys({ down: 'Meta' });
224
+ await sendKeys({ press: 'Backspace' });
225
+ await sendKeys({ up: 'Meta' });
226
+ expect(input?.value).to.equal('o');
227
+ });
221
228
  it('does not filter on only whitespace', async () => {
222
229
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
223
230
  ${defaultSlot}
@@ -257,6 +264,34 @@ it('hides Select All when filtering', async () => {
257
264
  const selectAll = component.shadowRoot?.querySelector('[data-test="select-all"]');
258
265
  expect(selectAll?.checkVisibility()).to.not.be.ok;
259
266
  });
267
+ it('unhides every option after filtering when one is selected and Dropdown is reopened', async () => {
268
+ const component = await fixture(html `<glide-core-dropdown
269
+ label="Label"
270
+ placeholder="Placeholder"
271
+ open
272
+ filterable
273
+ >
274
+ <glide-core-dropdown-option
275
+ label="One"
276
+ selected
277
+ ></glide-core-dropdown-option>
278
+
279
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
280
+ </glide-core-dropdown>`);
281
+ // Wait for it to open.
282
+ await aTimeout(0);
283
+ component.focus();
284
+ await sendKeys({ type: 'two' });
285
+ component.blur();
286
+ await elementUpdated(component);
287
+ component.open = true;
288
+ // Wait for it to open.
289
+ await aTimeout(0);
290
+ const options = [
291
+ ...component.querySelectorAll('glide-core-dropdown-option'),
292
+ ].filter(({ hidden }) => !hidden);
293
+ expect(options.length).to.equal(2);
294
+ });
260
295
  it('sets the first unfiltered option as active when the previously active option is filtered out', async () => {
261
296
  const component = await fixture(html `<glide-core-dropdown
262
297
  label="Label"
@@ -308,14 +343,10 @@ it('sets the `value` of its `<input>` when made filterable', async () => {
308
343
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
309
344
  <glide-core-dropdown-option
310
345
  label="One"
311
- value="one"
312
346
  selected
313
347
  ></glide-core-dropdown-option>
314
348
 
315
- <glide-core-dropdown-option
316
- label="Two"
317
- value="two"
318
- ></glide-core-dropdown-option>
349
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
319
350
  </glide-core-dropdown>`);
320
351
  component.filterable = true;
321
352
  await elementUpdated(component);
@@ -350,7 +381,6 @@ it('deselects the last selected option on Backspace', async () => {
350
381
  component.shadowRoot
351
382
  ?.querySelector('[data-test="input"]')
352
383
  ?.setSelectionRange(0, 0);
353
- await aTimeout(0);
354
384
  await sendKeys({ press: 'Backspace' });
355
385
  expect(options[1].selected).to.be.false;
356
386
  expect(options[0].selected).to.be.true;
@@ -395,6 +425,22 @@ it('clears the `value` of its `<input>` when multiselect and an option is select
395
425
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
396
426
  expect(input?.value).to.be.empty.string;
397
427
  });
428
+ it('does not clear its filter when a tag is removed', async () => {
429
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
430
+ ${defaultSlot}
431
+ </glide-core-dropdown>`);
432
+ const option = component.querySelector('glide-core-dropdown-option');
433
+ assert(option);
434
+ option.selected = true;
435
+ component.focus();
436
+ await sendKeys({ type: 'one' });
437
+ component.shadowRoot
438
+ ?.querySelector('[data-test="tag"]')
439
+ ?.click();
440
+ await elementUpdated(component);
441
+ const input = component.shadowRoot?.querySelector('[data-test="input"]');
442
+ expect(input?.value).to.equal('one');
443
+ });
398
444
  it('uses `placeholder` as a placeholder when multiselect and no option is selected', async () => {
399
445
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
400
446
  ${defaultSlot}
@@ -601,7 +647,7 @@ it('sets `aria-activedescendant` when closed via click', async () => {
601
647
  ?.click();
602
648
  await elementUpdated(component);
603
649
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
604
- expect(input?.getAttribute('aria-activedescendant')).to.equal('');
650
+ expect(input?.getAttribute('aria-activedescendant')).to.be.empty.string;
605
651
  });
606
652
  it('sets `aria-activedescendant` when closed because it lost focus', async () => {
607
653
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
@@ -610,7 +656,7 @@ it('sets `aria-activedescendant` when closed because it lost focus', async () =>
610
656
  component.focus();
611
657
  await sendKeys({ press: 'Tab' });
612
658
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
613
- expect(input?.getAttribute('aria-activedescendant')).to.equal('');
659
+ expect(input?.getAttribute('aria-activedescendant')).to.be.empty.string;
614
660
  });
615
661
  it('sets `aria-activedescendant` when closed because something outside of it was clicked', async () => {
616
662
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
@@ -619,7 +665,7 @@ it('sets `aria-activedescendant` when closed because something outside of it was
619
665
  document.body.click();
620
666
  await elementUpdated(component);
621
667
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
622
- expect(input?.getAttribute('aria-activedescendant')).to.equal('');
668
+ expect(input?.getAttribute('aria-activedescendant')).to.be.empty.string;
623
669
  });
624
670
  it('sets `aria-activedescendant` when closed via Escape', async () => {
625
671
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
@@ -628,7 +674,7 @@ it('sets `aria-activedescendant` when closed via Escape', async () => {
628
674
  component.focus();
629
675
  await sendKeys({ press: 'Escape' });
630
676
  const input = component.shadowRoot?.querySelector('[data-test="input"]');
631
- expect(input?.getAttribute('aria-activedescendant')).to.equal('');
677
+ expect(input?.getAttribute('aria-activedescendant')).to.be.empty.string;
632
678
  });
633
679
  it('cannot be tabbed to when `disabled`', async () => {
634
680
  await fixture(html `<glide-core-dropdown
@@ -691,17 +737,69 @@ it('has no icon when filtering and an option is selected', async () => {
691
737
 
692
738
  <glide-core-dropdown-option
693
739
  label="One"
694
- value="one"
695
740
  selected
696
741
  ></glide-core-dropdown-option>
697
742
 
698
- <glide-core-dropdown-option
699
- label="Two"
700
- value="two"
701
- ></glide-core-dropdown-option>
743
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
702
744
  </glide-core-dropdown>`);
703
745
  component.focus();
704
746
  await sendKeys({ type: 'one' });
705
747
  const iconSlot = component.shadowRoot?.querySelector('[data-test="single-select-icon-slot"]');
706
748
  expect(iconSlot).to.be.null;
707
749
  });
750
+ it('supports custom filtering', async () => {
751
+ const component = await fixture(html `<glide-core-dropdown
752
+ label="Label"
753
+ placeholder="Placeholder"
754
+ filterable
755
+ >
756
+ <glide-core-dropdown-option label="One"></glide-core-dropdown-option>
757
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
758
+ </glide-core-dropdown>`);
759
+ component.filter = async (filter) => {
760
+ const options = [
761
+ ...component.querySelectorAll('glide-core-dropdown-option'),
762
+ ];
763
+ return options.filter(({ label }) => label.includes(filter));
764
+ };
765
+ component.focus();
766
+ await sendKeys({ type: 'O' });
767
+ const options = [
768
+ ...component.querySelectorAll('glide-core-dropdown-option'),
769
+ ].filter(({ hidden }) => !hidden);
770
+ expect(options.length).to.equal(1);
771
+ expect(options[0].label).to.equal('One');
772
+ });
773
+ it('does nothing when filtering fails', async () => {
774
+ const component = await fixture(html `<glide-core-dropdown
775
+ label="Label"
776
+ placeholder="Placeholder"
777
+ filterable
778
+ >
779
+ <glide-core-dropdown-option label="One"></glide-core-dropdown-option>
780
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
781
+ </glide-core-dropdown>`);
782
+ component.filter = () => {
783
+ return Promise.reject();
784
+ };
785
+ component.focus();
786
+ await sendKeys({ type: 'O' });
787
+ const options = [
788
+ ...component.querySelectorAll('glide-core-dropdown-option'),
789
+ ].filter(({ hidden }) => !hidden);
790
+ expect(options.length).to.equal(2);
791
+ });
792
+ it('updates its item count after filtering', async () => {
793
+ const component = await fixture(html `<glide-core-dropdown
794
+ label="Label"
795
+ placeholder="Placeholder"
796
+ filterable
797
+ >
798
+ <glide-core-dropdown-option label="One"></glide-core-dropdown-option>
799
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
800
+ </glide-core-dropdown>`);
801
+ component.focus();
802
+ await sendKeys({ type: 'one' });
803
+ const itemCount = component.shadowRoot?.querySelector('[data-test="item-count"]');
804
+ expect(itemCount?.ariaLabel).to.equal('1 items');
805
+ });