@crowdstrike/glide-core 0.8.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.
- package/dist/button-group.button.d.ts +14 -15
- package/dist/button-group.button.js +1 -1
- package/dist/button-group.button.styles.js +75 -52
- package/dist/button-group.button.test.basics.d.ts +1 -1
- package/dist/button-group.button.test.basics.js +83 -147
- package/dist/button-group.button.test.events.js +8 -67
- package/dist/button-group.button.test.focus.js +13 -0
- package/dist/button-group.button.test.interactions.d.ts +1 -0
- package/dist/button-group.button.test.interactions.js +42 -0
- package/dist/button-group.d.ts +7 -10
- package/dist/button-group.js +1 -1
- package/dist/button-group.stories.d.ts +1 -5
- package/dist/button-group.styles.js +18 -6
- package/dist/button-group.test.basics.js +113 -234
- package/dist/button-group.test.events.js +210 -263
- package/dist/button-group.test.focus.d.ts +1 -0
- package/dist/button-group.test.focus.js +39 -0
- package/dist/button-group.test.interactions.d.ts +1 -0
- package/dist/button-group.test.interactions.js +91 -0
- package/dist/button.test.basics.js +1 -1
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.styles.js +1 -1
- package/dist/checkbox-group.test.basics.js +1 -1
- package/dist/checkbox-group.test.events.js +4 -4
- package/dist/checkbox-group.test.focus.js +4 -3
- package/dist/checkbox.d.ts +7 -1
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.styles.js +10 -0
- package/dist/checkbox.test.events.js +4 -4
- package/dist/checkbox.test.focus.js +2 -2
- package/dist/{checkbox.test.states.js → checkbox.test.interactions.js} +24 -1
- package/dist/drawer.js +1 -1
- package/dist/dropdown.d.ts +6 -4
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.d.ts +6 -2
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.styles.js +13 -0
- package/dist/dropdown.option.test.basics.js +6 -3
- package/dist/dropdown.option.test.events.js +1 -1
- package/dist/dropdown.option.test.focus.js +1 -1
- package/dist/dropdown.option.test.interactions.multiple.js +1 -54
- package/dist/dropdown.option.test.interactions.single.js +51 -9
- package/dist/dropdown.styles.js +20 -19
- package/dist/dropdown.test.basics.js +143 -2
- package/dist/dropdown.test.basics.multiple.js +5 -2
- package/dist/dropdown.test.events.filterable.js +74 -0
- package/dist/dropdown.test.events.js +49 -160
- package/dist/dropdown.test.events.multiple.js +265 -8
- package/dist/dropdown.test.events.single.js +199 -2
- package/dist/dropdown.test.focus.filterable.js +9 -5
- package/dist/dropdown.test.focus.js +1 -1
- package/dist/dropdown.test.focus.multiple.js +1 -1
- package/dist/dropdown.test.focus.single.js +1 -1
- package/dist/dropdown.test.interactions.filterable.js +68 -11
- package/dist/dropdown.test.interactions.js +94 -5
- package/dist/dropdown.test.interactions.multiple.js +202 -5
- package/dist/dropdown.test.interactions.single.js +68 -6
- package/dist/form-controls-layout.test.basics.js +1 -1
- package/dist/icon-button.test.basics.js +1 -1
- package/dist/icons/checked.d.ts +1 -1
- package/dist/icons/checked.js +1 -1
- package/dist/icons/magnifying-glass.js +1 -1
- package/dist/input.d.ts +0 -6
- package/dist/input.js +1 -1
- package/dist/input.styles.js +7 -2
- package/dist/input.test.basics.js +19 -5
- package/dist/input.test.events.js +4 -4
- package/dist/input.test.focus.js +4 -4
- package/dist/input.test.translations.d.ts +1 -0
- package/dist/input.test.translations.js +38 -0
- package/dist/input.test.validity.js +133 -4
- package/dist/label.d.ts +1 -1
- package/dist/label.js +1 -1
- package/dist/label.styles.js +22 -13
- package/dist/label.test.basics.js +26 -24
- package/dist/library/expect-argument-error.js +1 -1
- package/dist/library/localize.d.ts +3 -1
- package/dist/menu.d.ts +3 -5
- package/dist/menu.js +1 -1
- package/dist/menu.options.test.basics.js +2 -2
- package/dist/menu.styles.js +1 -15
- package/dist/menu.test.basics.d.ts +1 -2
- package/dist/menu.test.basics.js +22 -6
- package/dist/menu.test.focus.d.ts +1 -0
- package/dist/menu.test.focus.js +13 -6
- package/dist/menu.test.interactions.js +212 -56
- package/dist/modal.icon-button.test.basics.js +1 -1
- package/dist/modal.js +1 -1
- package/dist/modal.styles.js +18 -13
- package/dist/modal.tertiary-icon.d.ts +0 -1
- package/dist/modal.tertiary-icon.js +1 -1
- package/dist/modal.tertiary-icon.test.basics.js +1 -1
- package/dist/modal.test.basics.js +1 -1
- package/dist/modal.test.events.js +10 -10
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.styles.js +1 -1
- package/dist/radio-group.test.focus.js +3 -3
- package/dist/radio.d.ts +1 -0
- package/dist/radio.js +1 -1
- package/dist/radio.styles.js +33 -0
- package/dist/split-container.test.basics.js +4 -0
- package/dist/split-link.test.interactions.js +1 -1
- package/dist/styles/variables.css +1 -1
- package/dist/tab.d.ts +1 -1
- package/dist/tab.group.js +1 -1
- package/dist/tab.group.test.basics.js +1 -1
- package/dist/tab.group.test.interactions.js +198 -2
- package/dist/tab.js +1 -1
- package/dist/tab.panel.d.ts +1 -0
- package/dist/tab.panel.js +1 -1
- package/dist/tab.panel.styles.js +11 -1
- package/dist/tag.test.basics.js +2 -2
- package/dist/textarea.d.ts +0 -1
- package/dist/textarea.js +2 -2
- package/dist/textarea.stories.d.ts +3 -4
- package/dist/textarea.styles.js +14 -3
- package/dist/textarea.test.basics.js +80 -44
- package/dist/textarea.test.events.js +56 -41
- package/dist/textarea.test.translations.d.ts +1 -0
- package/dist/textarea.test.translations.js +34 -0
- package/dist/textarea.test.validity.js +104 -20
- package/dist/toasts.js +1 -1
- package/dist/toasts.styles.js +8 -1
- package/dist/toasts.test.basics.js +20 -0
- package/dist/toggle.js +1 -1
- package/dist/toggle.test.focus.js +1 -1
- package/dist/toggle.test.interactions.d.ts +1 -0
- package/dist/tooltip.d.ts +7 -5
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +90 -25
- package/dist/tooltip.test.basics.js +38 -3
- package/dist/tooltip.test.interactions.js +136 -34
- package/dist/translations/en.js +1 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/ja.js +1 -1
- package/dist/tree.d.ts +0 -1
- package/dist/tree.item.d.ts +1 -2
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +0 -1
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.js +1 -1
- package/dist/tree.test.basics.js +1 -1
- package/package.json +2 -4
- package/dist/drawer.test.floating-components.d.ts +0 -1
- package/dist/drawer.test.floating-components.js +0 -52
- package/dist/library/set-containing-block.d.ts +0 -15
- package/dist/library/set-containing-block.js +0 -1
- package/dist/modal.test.floating-components.js +0 -63
- /package/dist/{checkbox.test.states.d.ts → button-group.button.test.focus.d.ts} +0 -0
- /package/dist/{modal.test.floating-components.d.ts → checkbox.test.interactions.d.ts} +0 -0
- /package/dist/{toggle.test.states.d.ts → dropdown.test.events.filterable.d.ts} +0 -0
- /package/dist/{toggle.test.states.js → toggle.test.interactions.js} +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
2
|
import { ArgumentError } from 'ow';
|
3
|
-
import { assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
|
3
|
+
import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
|
4
4
|
import { sendKeys } from '@web/test-runner-commands';
|
5
5
|
import GlideCoreDropdown from './dropdown.js';
|
6
6
|
import GlideCoreDropdownOption from './dropdown.option.js';
|
@@ -21,7 +21,11 @@ it('opens on click', async () => {
|
|
21
21
|
component.shadowRoot
|
22
22
|
?.querySelector('[data-test="button"]')
|
23
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"]');
|
24
27
|
expect(component.open).to.be.true;
|
28
|
+
expect(options?.checkVisibility()).to.be.true;
|
25
29
|
});
|
26
30
|
it('toggles open and closed when the button is clicked', async () => {
|
27
31
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
@@ -37,7 +41,10 @@ it('toggles open and closed when the button is clicked', async () => {
|
|
37
41
|
component.shadowRoot
|
38
42
|
?.querySelector('[data-test="button"]')
|
39
43
|
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
44
|
+
await elementUpdated(component);
|
45
|
+
const options = component.shadowRoot?.querySelector('[data-test="options"]');
|
40
46
|
expect(component.open).to.be.false;
|
47
|
+
expect(options?.checkVisibility()).to.be.false;
|
41
48
|
});
|
42
49
|
it('does not toggle open and closed when the button overflow text is clicked', async () => {
|
43
50
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
@@ -53,7 +60,11 @@ it('does not toggle open and closed when the button overflow text is clicked', a
|
|
53
60
|
component.shadowRoot
|
54
61
|
?.querySelector('[data-test="tag-overflow-text"]')
|
55
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"]');
|
56
66
|
expect(component.open).to.be.true;
|
67
|
+
expect(options?.checkVisibility()).to.be.true;
|
57
68
|
});
|
58
69
|
it('selects an option on click', async () => {
|
59
70
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
@@ -62,6 +73,8 @@ it('selects an option on click', async () => {
|
|
62
73
|
value="one"
|
63
74
|
></glide-core-dropdown-option>
|
64
75
|
</glide-core-dropdown>`);
|
76
|
+
// Wait for it to open.
|
77
|
+
await aTimeout(0);
|
65
78
|
const option = component.querySelector('glide-core-dropdown-option');
|
66
79
|
option?.click();
|
67
80
|
await elementUpdated(component);
|
@@ -77,11 +90,26 @@ it('selects an option on Space', async () => {
|
|
77
90
|
value="one"
|
78
91
|
></glide-core-dropdown-option>
|
79
92
|
</glide-core-dropdown>`);
|
93
|
+
// Wait for it to open.
|
94
|
+
await aTimeout(0);
|
80
95
|
const option = component.querySelector('glide-core-dropdown-option');
|
81
96
|
option?.focus();
|
82
97
|
await sendKeys({ press: ' ' });
|
83
98
|
expect(option?.selected).to.be.true;
|
84
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
|
+
});
|
85
113
|
it('selects an option on Enter', async () => {
|
86
114
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
87
115
|
<glide-core-dropdown-option
|
@@ -89,6 +117,8 @@ it('selects an option on Enter', async () => {
|
|
89
117
|
value="one"
|
90
118
|
></glide-core-dropdown-option>
|
91
119
|
</glide-core-dropdown>`);
|
120
|
+
// Wait for it to open.
|
121
|
+
await aTimeout(0);
|
92
122
|
const option = component.querySelector('glide-core-dropdown-option');
|
93
123
|
option?.focus();
|
94
124
|
await sendKeys({ press: 'Enter' });
|
@@ -122,6 +152,17 @@ it('closes when an option is selected via click', async () => {
|
|
122
152
|
component.querySelector('glide-core-dropdown-option')?.click();
|
123
153
|
expect(component.open).to.be.false;
|
124
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
|
+
});
|
125
166
|
it('closes when an option is selected via Enter', async () => {
|
126
167
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
127
168
|
<glide-core-dropdown-option
|
@@ -129,6 +170,19 @@ it('closes when an option is selected via Enter', async () => {
|
|
129
170
|
value="value"
|
130
171
|
></glide-core-dropdown-option>
|
131
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);
|
132
186
|
component.querySelector('glide-core-dropdown-option')?.focus();
|
133
187
|
await sendKeys({ press: 'Enter' });
|
134
188
|
expect(component.open).to.be.false;
|
@@ -140,6 +194,8 @@ it('closes when an option is selected via Space', async () => {
|
|
140
194
|
value="value"
|
141
195
|
></glide-core-dropdown-option>
|
142
196
|
</glide-core-dropdown>`);
|
197
|
+
// Wait for it to open.
|
198
|
+
await aTimeout(0);
|
143
199
|
const option = component.querySelector('glide-core-dropdown-option');
|
144
200
|
option?.focus();
|
145
201
|
await sendKeys({ press: ' ' });
|
@@ -211,7 +267,7 @@ it('throws when `value` is changed programmatically to include more than one val
|
|
211
267
|
spy();
|
212
268
|
}
|
213
269
|
}
|
214
|
-
expect(spy.
|
270
|
+
expect(spy.callCount).to.equal(1);
|
215
271
|
});
|
216
272
|
it('updates `value` when an option `value` is changed programmatically', async () => {
|
217
273
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
@@ -274,6 +330,8 @@ it('updates `value` when an option is selected via Enter', async () => {
|
|
274
330
|
|
275
331
|
<glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
|
276
332
|
</glide-core-dropdown>`);
|
333
|
+
// Wait for it to open.
|
334
|
+
await aTimeout(0);
|
277
335
|
const options = component.querySelectorAll('glide-core-dropdown-option');
|
278
336
|
options[0].focus();
|
279
337
|
await sendKeys({ press: 'Enter' });
|
@@ -283,7 +341,7 @@ it('updates `value` when an option is selected via Enter', async () => {
|
|
283
341
|
?.querySelector('[data-test="button"]')
|
284
342
|
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
285
343
|
// Wait for it to open.
|
286
|
-
await
|
344
|
+
await aTimeout(0);
|
287
345
|
options[1].focus();
|
288
346
|
await sendKeys({ press: 'Enter' });
|
289
347
|
expect(component.value).to.deep.equal(['two']);
|
@@ -292,7 +350,7 @@ it('updates `value` when an option is selected via Enter', async () => {
|
|
292
350
|
?.querySelector('[data-test="button"]')
|
293
351
|
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
294
352
|
// Wait for it to open.
|
295
|
-
await
|
353
|
+
await aTimeout(0);
|
296
354
|
options[2].focus();
|
297
355
|
await sendKeys({ press: 'Enter' });
|
298
356
|
expect(component.value).to.deep.equal([]);
|
@@ -311,6 +369,8 @@ it('updates `value` when an option is selected via Space', async () => {
|
|
311
369
|
|
312
370
|
<glide-core-dropdown-option label="Three"></glide-core-dropdown-option>
|
313
371
|
</glide-core-dropdown>`);
|
372
|
+
// Wait for it to open.
|
373
|
+
await aTimeout(0);
|
314
374
|
const options = component.querySelectorAll('glide-core-dropdown-option');
|
315
375
|
options[0].focus();
|
316
376
|
await sendKeys({ press: ' ' });
|
@@ -320,7 +380,7 @@ it('updates `value` when an option is selected via Space', async () => {
|
|
320
380
|
?.querySelector('[data-test="button"]')
|
321
381
|
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
322
382
|
// Wait for it to open.
|
323
|
-
await
|
383
|
+
await aTimeout(0);
|
324
384
|
options[1].focus();
|
325
385
|
await sendKeys({ press: ' ' });
|
326
386
|
expect(component.value).to.deep.equal(['two']);
|
@@ -329,7 +389,7 @@ it('updates `value` when an option is selected via Space', async () => {
|
|
329
389
|
?.querySelector('[data-test="button"]')
|
330
390
|
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
331
391
|
// Wait for it to open.
|
332
|
-
await
|
392
|
+
await aTimeout(0);
|
333
393
|
options[2].focus();
|
334
394
|
await sendKeys({ press: ' ' });
|
335
395
|
expect(component.value).to.deep.equal([]);
|
@@ -442,6 +502,8 @@ it('does not select an option on Enter when the option is not focused', async ()
|
|
442
502
|
value="two"
|
443
503
|
></glide-core-dropdown-option>
|
444
504
|
</glide-core-dropdown>`);
|
505
|
+
// Wait for it to open.
|
506
|
+
await aTimeout(0);
|
445
507
|
const option = component.querySelector('glide-core-dropdown-option');
|
446
508
|
option?.focus();
|
447
509
|
await sendKeys({ down: 'Tab' });
|
@@ -49,7 +49,7 @@ it('throws if it does not have a default slot', async () => {
|
|
49
49
|
spy();
|
50
50
|
}
|
51
51
|
}
|
52
|
-
expect(spy.
|
52
|
+
expect(spy.callCount).to.equal(1);
|
53
53
|
});
|
54
54
|
it('throws if its default slot is the incorrect type', async () => {
|
55
55
|
await expectArgumentError(() => {
|
package/dist/icons/checked.d.ts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
declare const _default: import("lit").TemplateResult
|
1
|
+
declare const _default: import("lit").TemplateResult<1>;
|
2
2
|
export default _default;
|
package/dist/icons/checked.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
import{
|
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,
|
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;
|
package/dist/input.styles.js
CHANGED
@@ -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-
|
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
|
@@ -54,7 +54,7 @@ it('changes to type text when password is revealed', async () => {
|
|
54
54
|
const inputElement = element.shadowRoot?.querySelector('input');
|
55
55
|
expect(inputElement).to.exist;
|
56
56
|
expect(inputElement?.getAttribute('type')).to.equal('password');
|
57
|
-
const passwordToggle = element.shadowRoot?.querySelector('
|
57
|
+
const passwordToggle = element.shadowRoot?.querySelector('[data-test="password-toggle"]');
|
58
58
|
passwordToggle?.click();
|
59
59
|
await element.updateComplete;
|
60
60
|
expect(inputElement?.getAttribute('type')).to.equal('text');
|
@@ -66,7 +66,7 @@ it('shows search icon with type search', async () => {
|
|
66
66
|
const inputElement = element.shadowRoot?.querySelector('input');
|
67
67
|
expect(inputElement).to.exist;
|
68
68
|
expect(inputElement?.getAttribute('type')).to.equal('search');
|
69
|
-
const searchIcon = element.shadowRoot?.querySelector('
|
69
|
+
const searchIcon = element.shadowRoot?.querySelector('[data-test="search-icon"]');
|
70
70
|
expect(searchIcon).to.exist;
|
71
71
|
});
|
72
72
|
it('when using "focus() on input", the native input is focused', async () => {
|
@@ -100,7 +100,7 @@ it('clearable attribute allows for a button which can clear input', async () =>
|
|
100
100
|
const element = await fixture(html `
|
101
101
|
<glide-core-input label="Test" clearable></glide-core-input>
|
102
102
|
`);
|
103
|
-
const clearButton = element.shadowRoot?.querySelector('
|
103
|
+
const clearButton = element.shadowRoot?.querySelector('[data-test="clear-button"]');
|
104
104
|
element.focus();
|
105
105
|
await sendKeys({ type: 'testing' });
|
106
106
|
expect(element.value).to.be.equal('testing');
|
@@ -119,8 +119,22 @@ it('displays a max character and current character count if maxlength is provide
|
|
119
119
|
const element = await fixture(html `
|
120
120
|
<glide-core-input label="Test label" maxlength="5"></glide-core-input>
|
121
121
|
`);
|
122
|
-
const
|
123
|
-
expect(
|
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;
|
124
138
|
});
|
125
139
|
it('supports a "tooltip" slot', async () => {
|
126
140
|
const component = await fixture(html `<glide-core-input label="test">
|
@@ -65,7 +65,7 @@ it('does not dispatch an "invalid" event after `checkValidity` is called when no
|
|
65
65
|
input.addEventListener('invalid', spy);
|
66
66
|
input.checkValidity();
|
67
67
|
await aTimeout(0);
|
68
|
-
expect(spy.
|
68
|
+
expect(spy.callCount).to.equal(0);
|
69
69
|
});
|
70
70
|
it('does not dispatch an "invalid" event after `checkValidity` is called when required and no value but disabled', async () => {
|
71
71
|
const form = document.createElement('form');
|
@@ -74,7 +74,7 @@ it('does not dispatch an "invalid" event after `checkValidity` is called when re
|
|
74
74
|
input.addEventListener('invalid', spy);
|
75
75
|
input.checkValidity();
|
76
76
|
await aTimeout(0);
|
77
|
-
expect(spy.
|
77
|
+
expect(spy.callCount).to.equal(0);
|
78
78
|
});
|
79
79
|
it('does not dispatch an "invalid" event when `reportValidity` is called when not required,', async () => {
|
80
80
|
const form = document.createElement('form');
|
@@ -85,7 +85,7 @@ it('does not dispatch an "invalid" event when `reportValidity` is called when no
|
|
85
85
|
input.addEventListener('invalid', spy);
|
86
86
|
input.reportValidity();
|
87
87
|
await aTimeout(0);
|
88
|
-
expect(spy.
|
88
|
+
expect(spy.callCount).to.equal(0);
|
89
89
|
});
|
90
90
|
it('does not dispatch an "invalid" event when `reportValidity` is called when required and no value but disabled', async () => {
|
91
91
|
const form = document.createElement('form');
|
@@ -94,5 +94,5 @@ it('does not dispatch an "invalid" event when `reportValidity` is called when re
|
|
94
94
|
input.addEventListener('invalid', spy);
|
95
95
|
input.reportValidity();
|
96
96
|
await aTimeout(0);
|
97
|
-
expect(spy.
|
97
|
+
expect(spy.callCount).to.equal(0);
|
98
98
|
});
|
package/dist/input.test.focus.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
2
|
import './input.js';
|
3
3
|
import { expect, fixture, html } from '@open-wc/testing';
|
4
|
-
import
|
5
|
-
|
6
|
-
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 () => {
|
7
7
|
const input = await fixture(html `<glide-core-input required></glide-core-input>`);
|
8
8
|
input.focus();
|
9
9
|
const inputElement = input.shadowRoot?.querySelector('input');
|
@@ -27,7 +27,7 @@ it('blurs the input and reports validity if `blur` is called', async () => {
|
|
27
27
|
await input.updateComplete;
|
28
28
|
expect(input.shadowRoot?.activeElement).to.equal(null);
|
29
29
|
expect(input.validity.valid).to.equal(false);
|
30
|
-
expect(input.shadowRoot?.querySelector('glide-core-label')?.error).to.equal(true);
|
30
|
+
expect(input.shadowRoot?.querySelector('glide-core-private-label')?.error).to.equal(true);
|
31
31
|
});
|
32
32
|
it('focuses the input after `reportValidity` is called when required and no value', async () => {
|
33
33
|
const form = document.createElement('form');
|
@@ -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
|
+
});
|