@crowdstrike/glide-core 0.12.1 → 0.12.3

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 (61) hide show
  1. package/dist/checkbox-group.styles.js +1 -1
  2. package/dist/dropdown.d.ts +5 -1
  3. package/dist/dropdown.js +126 -58
  4. package/dist/dropdown.option.d.ts +3 -0
  5. package/dist/dropdown.option.js +1 -1
  6. package/dist/dropdown.option.styles.js +81 -16
  7. package/dist/dropdown.option.test.basics.js +4 -33
  8. package/dist/dropdown.option.test.basics.multiple.js +9 -0
  9. package/dist/dropdown.option.test.basics.single.js +8 -0
  10. package/dist/dropdown.option.test.interactions.multiple.js +12 -0
  11. package/dist/dropdown.option.test.interactions.single.js +11 -0
  12. package/dist/dropdown.styles.js +127 -29
  13. package/dist/dropdown.test.basics.filterable.js +11 -54
  14. package/dist/dropdown.test.basics.js +24 -244
  15. package/dist/dropdown.test.basics.multiple.js +13 -60
  16. package/dist/dropdown.test.basics.single.js +2 -8
  17. package/dist/dropdown.test.events.filterable.js +12 -54
  18. package/dist/dropdown.test.events.js +139 -46
  19. package/dist/dropdown.test.events.multiple.js +17 -87
  20. package/dist/dropdown.test.events.single.js +99 -60
  21. package/dist/dropdown.test.focus.filterable.js +13 -60
  22. package/dist/dropdown.test.focus.js +64 -11
  23. package/dist/dropdown.test.focus.multiple.js +36 -46
  24. package/dist/dropdown.test.focus.single.js +28 -23
  25. package/dist/dropdown.test.form.js +22 -0
  26. package/dist/dropdown.test.interactions.filterable.js +86 -72
  27. package/dist/dropdown.test.interactions.js +361 -207
  28. package/dist/dropdown.test.interactions.multiple.js +152 -279
  29. package/dist/dropdown.test.interactions.single.js +62 -98
  30. package/dist/dropdown.test.validity.js +12 -49
  31. package/dist/icons/pencil.d.ts +2 -0
  32. package/dist/icons/pencil.js +1 -0
  33. package/dist/label.js +1 -1
  34. package/dist/label.styles.js +7 -3
  35. package/dist/library/localize.d.ts +2 -0
  36. package/dist/menu.js +1 -1
  37. package/dist/menu.options.js +1 -1
  38. package/dist/menu.options.test.events.d.ts +1 -0
  39. package/dist/menu.options.test.events.js +19 -0
  40. package/dist/menu.test.interactions.d.ts +1 -0
  41. package/dist/menu.test.interactions.js +38 -0
  42. package/dist/radio-group.styles.js +1 -1
  43. package/dist/tab.group.d.ts +8 -1
  44. package/dist/tab.group.js +1 -1
  45. package/dist/tab.group.styles.js +4 -0
  46. package/dist/tab.group.test.basics.js +77 -1
  47. package/dist/tab.panel.js +1 -1
  48. package/dist/tab.panel.styles.js +15 -0
  49. package/dist/tag.d.ts +2 -0
  50. package/dist/tag.js +1 -1
  51. package/dist/tag.styles.js +46 -5
  52. package/dist/tag.test.basics.js +1 -1
  53. package/dist/tag.test.events.js +76 -3
  54. package/dist/tag.test.focus.js +1 -1
  55. package/dist/textarea.styles.js +1 -1
  56. package/dist/translations/en.js +1 -1
  57. package/dist/translations/fr.d.ts +1 -1
  58. package/dist/translations/fr.js +1 -1
  59. package/dist/translations/ja.d.ts +1 -1
  60. package/dist/translations/ja.js +1 -1
  61. package/package.json +1 -1
@@ -24,40 +24,11 @@ it('has defaults', async () => {
24
24
  expect(component.privateActive).to.be.false;
25
25
  expect(component.privateIndeterminate).to.be.false;
26
26
  });
27
- it('can have a label', async () => {
27
+ it('is selectable', async () => {
28
28
  const component = await fixture(html `<glide-core-dropdown-option
29
29
  label="Label"
30
- value="value"
30
+ selected
31
31
  ></glide-core-dropdown-option>`);
32
- const label = component.shadowRoot?.querySelector('[data-test="label"]');
33
- expect(label?.textContent?.trim()).to.equal('Label');
34
- });
35
- it('can have an icon', async () => {
36
- const component = await fixture(html `<glide-core-dropdown-option label="Label" value="value">
37
- <svg slot="icon" width="16" height="16" viewBox="0 0 24 24" fill="none">
38
- <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" />
39
-
40
- <path
41
- d="M12 16L12 12"
42
- stroke="currentColor"
43
- stroke-width="2"
44
- stroke-linecap="round"
45
- />
46
-
47
- <circle cx="12" cy="8" r="1" fill="currentColor" />
48
- </svg>
49
- </glide-core-dropdown-option>`);
50
- const icon = component?.shadowRoot
51
- ?.querySelector('slot[name="icon"]')
52
- ?.assignedElements()
53
- .at(0);
54
- expect(icon instanceof SVGElement).to.be.true;
55
- });
56
- it('can have a value', async () => {
57
- const component = await fixture(html `<glide-core-dropdown-option
58
- label="Label"
59
- value="value"
60
- ></glide-core-dropdown-option>`);
61
- expect(component.getAttribute('value')).to.equal('value');
62
- expect(component.value).to.equal('value');
32
+ const checkedIconContainer = component.shadowRoot?.querySelector('[data-test="checked-icon-container"]');
33
+ expect(checkedIconContainer instanceof Element).to.be.true;
63
34
  });
@@ -25,3 +25,12 @@ it('is deselected when initially deselected', async () => {
25
25
  expect(component.ariaSelected).to.equal('false');
26
26
  expect(checkbox?.checked).to.be.false;
27
27
  });
28
+ it('is editable', async () => {
29
+ const component = await fixture(html `<glide-core-dropdown-option
30
+ label="Label"
31
+ editable
32
+ private-multiple
33
+ ></glide-core-dropdown-option>`);
34
+ const button = component.shadowRoot?.querySelector('[data-test="edit-button"]');
35
+ expect(button?.checkVisibility()).to.be.true;
36
+ });
@@ -19,3 +19,11 @@ it('is deselected when initially deselected', async () => {
19
19
  expect(component.selected).to.be.false;
20
20
  expect(component.ariaSelected).to.equal('false');
21
21
  });
22
+ it('is editable', async () => {
23
+ const component = await fixture(html `<glide-core-dropdown-option
24
+ label="Label"
25
+ editable
26
+ ></glide-core-dropdown-option>`);
27
+ const button = component.shadowRoot?.querySelector('[data-test="edit-button"]');
28
+ expect(button?.checkVisibility()).to.be.true;
29
+ });
@@ -28,3 +28,15 @@ it('is deselected when programmatically deselected', async () => {
28
28
  expect(component.ariaSelected).to.equal('false');
29
29
  expect(checkbox?.checked).to.be.false;
30
30
  });
31
+ it('sets `privateIsEditActive`', async () => {
32
+ const component = await fixture(html `<glide-core-dropdown-option
33
+ label="Label"
34
+ editable
35
+ private-multiple
36
+ ></glide-core-dropdown-option>`);
37
+ const button = component.shadowRoot?.querySelector('[data-test="edit-button"]');
38
+ button?.dispatchEvent(new MouseEvent('mouseover'));
39
+ expect(component.privateIsEditActive).to.be.true;
40
+ button?.dispatchEvent(new MouseEvent('mouseout'));
41
+ expect(component.privateIsEditActive).to.be.false;
42
+ });
@@ -63,3 +63,14 @@ it('has no tooltip when active and with a short label set programmatically', asy
63
63
  const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
64
64
  expect(tooltip?.checkVisibility()).to.be.false;
65
65
  });
66
+ it('sets `privateIsEditActive`', async () => {
67
+ const component = await fixture(html `<glide-core-dropdown-option
68
+ label="Label"
69
+ editable
70
+ ></glide-core-dropdown-option>`);
71
+ const button = component.shadowRoot?.querySelector('[data-test="edit-button"]');
72
+ button?.dispatchEvent(new MouseEvent('mouseover'));
73
+ expect(component.privateIsEditActive).to.be.true;
74
+ button?.dispatchEvent(new MouseEvent('mouseout'));
75
+ expect(component.privateIsEditActive).to.be.false;
76
+ });
@@ -1,5 +1,6 @@
1
- import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-scale-animation.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
2
- ${opacityAndScaleAnimation(".options:popover-open")}
1
+ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import opacityAndScaleAnimation from"./styles/opacity-and-scale-animation.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
2
+ ${focusOutline(".add-button:focus-visible")}
3
+ ${opacityAndScaleAnimation(".options-and-footer:popover-open")}
3
4
  ${visuallyHidden(".selected-option-labels")}
4
5
  `,css`
5
6
  .component {
@@ -13,6 +14,19 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
13
14
  position: relative;
14
15
  }
15
16
 
17
+ glide-core-private-label {
18
+ &::part(private-control-and-summary) {
19
+ /*
20
+ The Label component's grid column styling combined with the fact that
21
+ ".dropdown-and-options" isn't a direct descendant of that grid means that
22
+ Dropdown's label won't shrink when space constrained without a minimum
23
+ width on Label's ".control-and-summary". It's not clear to me why Grid
24
+ behaves this way.
25
+ */
26
+ min-inline-size: var(--min-inline-size);
27
+ }
28
+ }
29
+
16
30
  .dropdown {
17
31
  --button-and-input-height: 1.25rem;
18
32
 
@@ -37,7 +51,6 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
37
51
  background-color 200ms ease-in-out,
38
52
  border-color 200ms ease-in-out;
39
53
  user-select: none;
40
- white-space: nowrap;
41
54
 
42
55
  &.quiet:not(.multiple) {
43
56
  background-color: transparent;
@@ -67,57 +80,58 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
67
80
  }
68
81
 
69
82
  &.quiet {
70
- &:is(:hover, :has(.button:focus-visible, .input:focus-visible)):not(
71
- &.error,
72
- &.disabled,
73
- &.multiple,
74
- &.readonly
75
- ) {
83
+ &:is(
84
+ :hover,
85
+ :has(.primary-button:focus-visible, .input:focus-visible)
86
+ ):not(&.error, &.disabled, &.multiple, &.readonly) {
76
87
  background-color: var(--glide-core-surface-hover);
77
88
  color: var(--glide-core-text-body-1);
78
89
  }
79
90
  }
80
91
 
81
- &:is(:hover, :has(.button:focus-visible, .input:focus-visible)):not(
82
- &.disabled,
83
- &.error,
84
- &.quiet,
85
- &.readonly
86
- ) {
92
+ &:is(
93
+ :hover,
94
+ :has(.primary-button:focus-visible, .input:focus-visible)
95
+ ):not(&.disabled, &.error, &.quiet, &.readonly) {
87
96
  border-color: var(--glide-core-border-focus);
88
97
  }
89
98
 
90
- &:has(.button:focus-visible, .input:focus-visible) {
99
+ &:has(.primary-button:focus-visible, .input:focus-visible) {
91
100
  &.quiet {
92
101
  border-color: var(--glide-core-border-focus);
93
102
  }
94
103
  }
95
104
  }
96
105
 
97
- .options {
106
+ .options-and-footer {
98
107
  --border-width: 1px;
99
- --padding: var(--glide-core-spacing-xxxs);
100
108
 
101
109
  background-color: var(--glide-core-surface-modal);
102
- border: var(--border-width) solid var(--glide-core-surface-modal);
110
+ border: var(--border-width) solid var(--glide-core-border-base-lighter);
103
111
  border-radius: var(--glide-core-spacing-xs);
104
112
  box-shadow: var(--glide-core-shadow-lg);
105
- box-sizing: border-box;
106
113
  inset: unset;
114
+ min-inline-size: var(--min-inline-size);
115
+ padding: 0;
116
+ position: absolute;
117
+
118
+ &.hidden {
119
+ display: none;
120
+ }
121
+ }
122
+
123
+ .options {
124
+ --padding: var(--glide-core-spacing-xxxs);
125
+
126
+ box-sizing: border-box;
107
127
  max-block-size: calc(
108
128
  var(--private-option-height) * 9 + var(--padding) * 2 +
109
129
  var(--border-width) * 2
110
130
  );
111
- min-inline-size: var(--min-inline-size);
112
131
  overflow: auto;
113
132
  padding: var(--padding);
114
- position: absolute;
115
133
  scroll-behavior: smooth;
116
134
 
117
- &.hidden {
118
- display: none;
119
- }
120
-
121
135
  &.large {
122
136
  --private-option-height: 1.75rem;
123
137
  }
@@ -127,6 +141,71 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
127
141
  }
128
142
  }
129
143
 
144
+ .footer {
145
+ background-color: var(--glide-core-surface-page);
146
+ border-block-start: 1px solid var(--glide-core-border-base);
147
+ box-shadow: 0 -8px 8px -8px
148
+ var(--glide-core-surface-base-gray, rgb(0 0 0 / 40%));
149
+ display: none;
150
+ inline-size: calc(100% - var(--glide-core-spacing-xxxs) * 2);
151
+ inset-block-end: 0;
152
+ padding: var(--glide-core-spacing-xxxs);
153
+
154
+ /*
155
+ "sticky" is a little hack so that footer is absolutely positioned but
156
+ its space in layout is preserved, so it doesn't overlap the last option.
157
+ */
158
+ position: sticky;
159
+
160
+ &.visible {
161
+ display: block;
162
+ }
163
+ }
164
+
165
+ .add-button {
166
+ align-items: center;
167
+ background-color: transparent;
168
+ border: none;
169
+ border-radius: 0.75rem;
170
+ display: flex;
171
+ font-family: var(--glide-core-body-sm-font-family);
172
+ font-weight: var(--glide-core-body-sm-font-weight);
173
+ inline-size: 100%;
174
+ line-height: 100%;
175
+ text-align: start;
176
+
177
+ &.large {
178
+ --size: 1rem;
179
+
180
+ column-gap: 0.625rem;
181
+ font-size: var(--glide-core-body-sm-font-size);
182
+ padding-block: 0.375rem;
183
+ padding-inline: var(--glide-core-spacing-sm);
184
+ }
185
+
186
+ &.small {
187
+ --size: 0.875rem;
188
+
189
+ column-gap: var(--glide-core-spacing-xs);
190
+ font-size: var(--glide-core-body-xs-font-size);
191
+ padding-block: var(--glide-core-spacing-xxxs);
192
+ padding-inline: var(--glide-core-spacing-xs);
193
+ }
194
+
195
+ &:focus {
196
+ outline: none;
197
+ }
198
+
199
+ &:focus-visible {
200
+ outline-offset: -2px;
201
+ }
202
+
203
+ &:focus,
204
+ &:hover {
205
+ background-color: var(--glide-core-surface-hover);
206
+ }
207
+ }
208
+
130
209
  .select-all {
131
210
  border-block-end: 1px solid var(--glide-core-border-base-light);
132
211
  margin-block-end: var(--glide-core-spacing-xxxs);
@@ -172,8 +251,8 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
172
251
  }
173
252
  }
174
253
 
175
- .tag-overflow-text-and-button {
176
- column-gap: var(--glide-core-spacing-md);
254
+ .tag-overflow-and-buttons {
255
+ align-items: center;
177
256
  display: flex;
178
257
  margin-inline-start: auto;
179
258
  }
@@ -181,6 +260,7 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
181
260
  .tag-overflow-text {
182
261
  align-content: center;
183
262
  color: var(--glide-core-text-link);
263
+ margin-inline-end: var(--glide-core-spacing-md);
184
264
  }
185
265
 
186
266
  .single-select-icon-slot {
@@ -197,15 +277,28 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
197
277
  }
198
278
  }
199
279
 
280
+ .internal-label-tooltip {
281
+ display: none;
282
+ overflow: hidden;
283
+
284
+ &.visible {
285
+ display: block;
286
+ }
287
+ }
288
+
200
289
  .internal-label {
290
+ overflow: hidden;
291
+
201
292
  /*
202
293
  2px so the label is vertically aligned. "vertical-align: middle" has no
203
294
  effect on flex children.
204
295
  */
205
296
  padding-block-start: 0.125rem;
297
+ text-overflow: ellipsis;
298
+ white-space: nowrap;
206
299
  }
207
300
 
208
- .button {
301
+ .primary-button {
209
302
  align-items: center;
210
303
  background: none;
211
304
  block-size: var(--button-and-input-height);
@@ -219,6 +312,11 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
219
312
  }
220
313
  }
221
314
 
315
+ .edit-button {
316
+ display: flex;
317
+ margin-inline-end: var(--glide-core-spacing-xxs);
318
+ }
319
+
222
320
  .input {
223
321
  background-color: transparent;
224
322
  block-size: var(--button-and-input-height);
@@ -4,60 +4,17 @@ import { expect, fixture, html } from '@open-wc/testing';
4
4
  import GlideCoreDropdown from './dropdown.js';
5
5
  GlideCoreDropdown.shadowRootOptions.mode = 'open';
6
6
  const defaultSlot = html `
7
- <glide-core-dropdown-option
8
- label="One"
9
- value="one"
10
- ></glide-core-dropdown-option>
11
-
12
- <glide-core-dropdown-option
13
- label="Two"
14
- value="two"
15
- ></glide-core-dropdown-option>
16
-
17
- <glide-core-dropdown-option
18
- label="Three"
19
- value="three"
20
- ></glide-core-dropdown-option>
21
-
22
- <glide-core-dropdown-option
23
- label="Four"
24
- value="four"
25
- ></glide-core-dropdown-option>
26
-
27
- <glide-core-dropdown-option
28
- label="Five"
29
- value="five"
30
- ></glide-core-dropdown-option>
31
-
32
- <glide-core-dropdown-option
33
- label="Six"
34
- value="six"
35
- ></glide-core-dropdown-option>
36
-
37
- <glide-core-dropdown-option
38
- label="Seven"
39
- value="seven"
40
- ></glide-core-dropdown-option>
41
-
42
- <glide-core-dropdown-option
43
- label="Eight"
44
- value="eight"
45
- ></glide-core-dropdown-option>
46
-
47
- <glide-core-dropdown-option
48
- label="Nine"
49
- value="nine"
50
- ></glide-core-dropdown-option>
51
-
52
- <glide-core-dropdown-option
53
- label="Ten"
54
- value="ten"
55
- ></glide-core-dropdown-option>
56
-
57
- <glide-core-dropdown-option
58
- label="Eleven"
59
- value="eleven"
60
- ></glide-core-dropdown-option>
7
+ <glide-core-dropdown-option label="One"></glide-core-dropdown-option>
8
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
9
+ <glide-core-dropdown-option label="Three"></glide-core-dropdown-option>
10
+ <glide-core-dropdown-option label="Four"></glide-core-dropdown-option>
11
+ <glide-core-dropdown-option label="Five"></glide-core-dropdown-option>
12
+ <glide-core-dropdown-option label="Six"></glide-core-dropdown-option>
13
+ <glide-core-dropdown-option label="Seven"></glide-core-dropdown-option>
14
+ <glide-core-dropdown-option label="Eight"></glide-core-dropdown-option>
15
+ <glide-core-dropdown-option label="Nine"></glide-core-dropdown-option>
16
+ <glide-core-dropdown-option label="Ten"></glide-core-dropdown-option>
17
+ <glide-core-dropdown-option label="Eleven"></glide-core-dropdown-option>
61
18
  `;
62
19
  it('is accessible', async () => {
63
20
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>