@crowdstrike/glide-core 0.9.6 → 0.11.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/README.md +17 -53
- package/dist/accordion.d.ts +10 -10
- package/dist/accordion.js +1 -1
- package/dist/accordion.stories.d.ts +0 -1
- package/dist/accordion.styles.js +36 -38
- package/dist/accordion.test.basics.js +13 -95
- package/dist/accordion.test.events.js +21 -33
- package/dist/accordion.test.focus.d.ts +1 -0
- package/dist/accordion.test.focus.js +11 -0
- package/dist/accordion.test.interactions.d.ts +1 -0
- package/dist/accordion.test.interactions.js +75 -0
- package/dist/button-group.button.d.ts +2 -4
- package/dist/button-group.button.js +1 -1
- package/dist/button-group.button.styles.js +6 -14
- package/dist/button-group.button.test.basics.js +8 -17
- package/dist/button-group.button.test.interactions.js +4 -4
- package/dist/button-group.d.ts +0 -2
- package/dist/button-group.test.basics.js +10 -10
- package/dist/button-group.test.events.js +2 -2
- package/dist/button-group.test.interactions.js +1 -1
- package/dist/button.d.ts +7 -10
- package/dist/button.js +1 -1
- package/dist/button.styles.js +4 -7
- package/dist/button.test.basics.js +10 -26
- package/dist/button.test.events.js +9 -9
- package/dist/checkbox-group.d.ts +3 -4
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.styles.js +13 -1
- package/dist/checkbox-group.test.basics.js +8 -12
- package/dist/checkbox-group.test.focus.js +7 -7
- package/dist/checkbox-group.test.interactions.d.ts +1 -0
- package/dist/checkbox-group.test.interactions.js +82 -0
- package/dist/checkbox.d.ts +5 -4
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.styles.js +35 -15
- package/dist/checkbox.test.basics.js +6 -15
- package/dist/checkbox.test.events.js +9 -0
- package/dist/checkbox.test.focus.js +4 -2
- package/dist/checkbox.test.interactions.js +11 -11
- package/dist/drawer.d.ts +2 -5
- package/dist/drawer.js +1 -1
- package/dist/drawer.test.accessibility.js +8 -8
- package/dist/drawer.test.basics.js +16 -16
- package/dist/drawer.test.closing.js +18 -16
- package/dist/drawer.test.events.js +13 -24
- package/dist/drawer.test.methods.js +22 -22
- package/dist/dropdown.d.ts +7 -5
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.d.ts +2 -3
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.styles.js +31 -19
- package/dist/dropdown.option.test.basics.js +4 -4
- package/dist/dropdown.option.test.events.js +9 -1
- package/dist/dropdown.option.test.interactions.single.js +2 -2
- package/dist/dropdown.styles.js +39 -3
- package/dist/dropdown.test.basics.d.ts +1 -1
- package/dist/dropdown.test.basics.js +27 -14
- package/dist/dropdown.test.basics.multiple.js +65 -32
- package/dist/dropdown.test.basics.single.js +49 -0
- package/dist/dropdown.test.events.filterable.js +13 -2
- package/dist/dropdown.test.focus.filterable.js +12 -3
- package/dist/dropdown.test.focus.js +18 -2
- package/dist/dropdown.test.form.multiple.js +3 -2
- package/dist/dropdown.test.interactions.filterable.js +141 -45
- package/dist/dropdown.test.interactions.js +24 -0
- package/dist/dropdown.test.interactions.multiple.js +87 -30
- package/dist/dropdown.test.interactions.single.js +40 -4
- package/dist/form-controls-layout.d.ts +0 -2
- package/dist/icon-button.d.ts +2 -4
- package/dist/icon-button.js +1 -1
- package/dist/icon-button.test.basics.js +14 -82
- package/dist/icon-button.test.focus.d.ts +1 -0
- package/dist/icon-button.test.focus.js +13 -0
- package/dist/input.d.ts +4 -5
- package/dist/input.js +1 -1
- package/dist/input.styles.js +4 -4
- package/dist/input.test.basics.js +0 -52
- package/dist/input.test.events.js +27 -27
- package/dist/input.test.focus.js +27 -26
- package/dist/input.test.form.js +6 -6
- package/dist/input.test.validity.js +130 -130
- package/dist/label.d.ts +1 -3
- package/dist/label.js +1 -1
- package/dist/label.styles.js +5 -6
- package/dist/label.test.basics.js +4 -4
- package/dist/library/ow.js +1 -1
- package/dist/menu.button.d.ts +0 -2
- package/dist/menu.button.test.basics.js +3 -3
- package/dist/menu.d.ts +1 -4
- package/dist/menu.js +1 -1
- package/dist/menu.link.d.ts +1 -2
- package/dist/menu.link.js +1 -1
- package/dist/menu.options.d.ts +0 -2
- package/dist/menu.test.events.js +6 -6
- package/dist/menu.test.focus.js +5 -18
- package/dist/menu.test.interactions.js +48 -24
- package/dist/modal.d.ts +6 -17
- package/dist/modal.icon-button.d.ts +0 -2
- package/dist/modal.icon-button.test.basics.js +3 -3
- package/dist/modal.js +1 -1
- package/dist/modal.styles.js +13 -19
- package/dist/modal.tertiary-icon.d.ts +0 -3
- package/dist/modal.tertiary-icon.test.basics.js +3 -3
- package/dist/modal.test.basics.js +9 -5
- package/dist/modal.test.close.js +2 -2
- package/dist/modal.test.events.js +2 -2
- package/dist/radio-group.d.ts +0 -3
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.test.basics.js +61 -61
- package/dist/radio-group.test.events.js +13 -13
- package/dist/radio-group.test.focus.js +1 -1
- package/dist/radio-group.test.form.js +2 -2
- package/dist/radio-group.test.validity.js +12 -12
- package/dist/radio.d.ts +0 -3
- package/dist/radio.styles.js +4 -12
- package/dist/split-button.d.ts +8 -11
- package/dist/split-button.js +1 -1
- package/dist/split-button.primary-button.d.ts +21 -0
- package/dist/split-button.primary-button.js +1 -0
- package/dist/split-button.primary-button.styles.js +96 -0
- package/dist/split-button.primary-button.test.basics.d.ts +1 -0
- package/dist/split-button.primary-button.test.basics.js +31 -0
- package/dist/split-button.primary-button.test.focus.d.ts +1 -0
- package/dist/split-button.primary-button.test.focus.js +14 -0
- package/dist/split-button.primary-link.d.ts +19 -0
- package/dist/split-button.primary-link.js +1 -0
- package/dist/split-button.primary-link.test.basics.d.ts +1 -0
- package/dist/split-button.primary-link.test.basics.js +30 -0
- package/dist/split-button.primary-link.test.focus.d.ts +1 -0
- package/dist/split-button.primary-link.test.focus.js +15 -0
- package/dist/split-button.secondary-button.d.ts +25 -0
- package/dist/split-button.secondary-button.js +1 -0
- package/dist/split-button.secondary-button.styles.js +103 -0
- package/dist/split-button.secondary-button.test.basics.d.ts +1 -0
- package/dist/split-button.secondary-button.test.basics.js +58 -0
- package/dist/split-button.secondary-button.test.focus.d.ts +1 -0
- package/dist/split-button.secondary-button.test.focus.js +14 -0
- package/dist/split-button.secondary-button.test.interactions.d.ts +2 -0
- package/dist/split-button.secondary-button.test.interactions.js +30 -0
- package/dist/split-button.stories.d.ts +4 -3
- package/dist/split-button.styles.js +1 -94
- package/dist/split-button.test.basics.d.ts +2 -1
- package/dist/split-button.test.basics.js +67 -80
- package/dist/split-button.test.interactions.d.ts +4 -0
- package/dist/split-button.test.interactions.js +51 -0
- package/dist/styles/opacity-and-scale-animation.js +2 -6
- package/dist/styles/variables.css +1 -1
- package/dist/tab.d.ts +2 -11
- package/dist/tab.group.d.ts +3 -5
- package/dist/tab.group.js +1 -1
- package/dist/tab.group.styles.js +18 -15
- package/dist/tab.group.test.basics.js +49 -34
- package/dist/tab.group.test.interactions.js +17 -14
- package/dist/tab.panel.d.ts +0 -3
- package/dist/tab.test.basics.js +6 -5
- package/dist/tag.d.ts +5 -4
- package/dist/tag.js +1 -1
- package/dist/tag.styles.js +47 -38
- package/dist/tag.test.basics.js +18 -110
- package/dist/tag.test.events.js +12 -8
- package/dist/tag.test.focus.js +2 -3
- package/dist/tag.test.interactions.d.ts +1 -0
- package/dist/tag.test.interactions.js +36 -0
- package/dist/textarea.d.ts +2 -3
- package/dist/textarea.js +2 -2
- package/dist/textarea.test.basics.js +8 -8
- package/dist/textarea.test.events.js +55 -55
- package/dist/textarea.test.form.js +9 -9
- package/dist/textarea.test.validity.js +167 -135
- package/dist/toasts.d.ts +1 -5
- package/dist/toasts.test.basics.js +2 -1
- package/dist/toasts.toast.d.ts +1 -4
- package/dist/toasts.toast.js +1 -1
- package/dist/toasts.toast.styles.js +12 -0
- package/dist/toggle.d.ts +0 -2
- package/dist/toggle.styles.js +1 -5
- package/dist/toggle.test.basics.js +2 -2
- package/dist/toggle.test.interactions.js +7 -7
- package/dist/tooltip.d.ts +2 -1
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +37 -13
- package/dist/tooltip.test.basics.d.ts +1 -1
- package/dist/tooltip.test.basics.js +19 -19
- package/dist/tree.d.ts +0 -2
- package/dist/tree.item.d.ts +5 -7
- package/dist/tree.item.icon-button.d.ts +1 -4
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +1 -2
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.menu.test.basics.js +31 -10
- package/dist/tree.item.styles.js +7 -9
- package/dist/tree.item.test.basics.js +43 -31
- package/dist/tree.test.basics.js +29 -29
- package/dist/tree.test.focus.js +77 -74
- package/package.json +12 -14
- package/dist/split-container.d.ts +0 -31
- package/dist/split-container.js +0 -1
- package/dist/split-container.styles.js +0 -132
- package/dist/split-container.test.basics.d.ts +0 -3
- package/dist/split-container.test.basics.js +0 -445
- package/dist/split-container.test.interactions.d.ts +0 -1
- package/dist/split-container.test.interactions.js +0 -20
- package/dist/split-link.d.ts +0 -25
- package/dist/split-link.js +0 -1
- package/dist/split-link.test.basics.d.ts +0 -1
- package/dist/split-link.test.basics.js +0 -93
- package/dist/split-link.test.interactions.d.ts +0 -1
- package/dist/split-link.test.interactions.js +0 -20
- package/dist/status-indicator.d.ts +0 -30
- package/dist/status-indicator.js +0 -1
- package/dist/status-indicator.stories.d.ts +0 -5
- package/dist/status-indicator.styles.js +0 -58
- package/dist/status-indicator.test.basics.d.ts +0 -1
- package/dist/status-indicator.test.basics.js +0 -102
- /package/dist/{split-container.styles.d.ts → split-button.primary-button.styles.d.ts} +0 -0
- /package/dist/{status-indicator.styles.d.ts → split-button.secondary-button.styles.d.ts} +0 -0
@@ -534,3 +534,27 @@ it('remains open when something other than the button is clicked', async () => {
|
|
534
534
|
});
|
535
535
|
expect(component.open).to.be.true;
|
536
536
|
});
|
537
|
+
it('hides the tooltip of the active option when opened via click', async () => {
|
538
|
+
// The period is arbitrary. 500 of them ensures we exceed the maximum
|
539
|
+
// width even if it's increased.
|
540
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
541
|
+
<glide-core-dropdown-option
|
542
|
+
label=${'.'.repeat(500)}
|
543
|
+
></glide-core-dropdown-option>
|
544
|
+
|
545
|
+
<glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
|
546
|
+
</glide-core-dropdown>`);
|
547
|
+
// Calling `click()` would be sweet. The problem is it sets `event.detail` to `0`,
|
548
|
+
// which puts us in a guard in the event handler. `Event` has no `detail` property
|
549
|
+
// and would work. `CustomEvent` is used for completeness and to get us as close as
|
550
|
+
// possible to a real click. See the comment in the handler for more information.
|
551
|
+
component.shadowRoot
|
552
|
+
?.querySelector('[data-test="button"]')
|
553
|
+
?.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: 1 }));
|
554
|
+
// Wait for it to open.
|
555
|
+
await aTimeout(0);
|
556
|
+
const tooltip = component
|
557
|
+
.querySelector('glide-core-dropdown-option')
|
558
|
+
?.shadowRoot?.querySelector('[data-test="tooltip"]');
|
559
|
+
expect(tooltip?.checkVisibility()).to.be.false;
|
560
|
+
});
|
@@ -1,11 +1,45 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
7
|
+
};
|
8
|
+
import { LitElement } from 'lit';
|
2
9
|
import { aTimeout, assert, elementUpdated, expect, fixture, html, oneEvent, } from '@open-wc/testing';
|
10
|
+
import { customElement } from 'lit/decorators.js';
|
3
11
|
import { sendKeys } from '@web/test-runner-commands';
|
4
12
|
import { sendMouse } from '@web/test-runner-commands';
|
5
13
|
import GlideCoreDropdown from './dropdown.js';
|
6
14
|
import GlideCoreDropdownOption from './dropdown.option.js';
|
15
|
+
let GlideCoreDropdownInAnotherComponent = class GlideCoreDropdownInAnotherComponent extends LitElement {
|
16
|
+
static { this.shadowRootOptions = {
|
17
|
+
...LitElement.shadowRootOptions,
|
18
|
+
mode: 'closed',
|
19
|
+
}; }
|
20
|
+
render() {
|
21
|
+
return html `<glide-core-dropdown
|
22
|
+
label="Label"
|
23
|
+
placeholder="Placeholder"
|
24
|
+
multiple
|
25
|
+
open
|
26
|
+
>
|
27
|
+
<glide-core-dropdown-option
|
28
|
+
label="One"
|
29
|
+
value="one"
|
30
|
+
></glide-core-dropdown-option>
|
31
|
+
|
32
|
+
<glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
|
33
|
+
<glide-core-dropdown-option label="Three"></glide-core-dropdown-option>
|
34
|
+
</glide-core-dropdown>`;
|
35
|
+
}
|
36
|
+
};
|
37
|
+
GlideCoreDropdownInAnotherComponent = __decorate([
|
38
|
+
customElement('glide-core-dropdown-in-another-component')
|
39
|
+
], GlideCoreDropdownInAnotherComponent);
|
7
40
|
GlideCoreDropdown.shadowRootOptions.mode = 'open';
|
8
41
|
GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
|
42
|
+
GlideCoreDropdownInAnotherComponent.shadowRootOptions.mode = 'open';
|
9
43
|
it('opens on click', async () => {
|
10
44
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
|
11
45
|
<glide-core-dropdown-option
|
@@ -221,25 +255,20 @@ it('deactivates all other options on "mouseover"', async () => {
|
|
221
255
|
expect(options[2]?.privateActive).to.be.false;
|
222
256
|
});
|
223
257
|
it('remains open when an option is selected via click', async () => {
|
224
|
-
const component = await fixture(html `<glide-core-dropdown
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
value="two"
|
239
|
-
></glide-core-dropdown-option>
|
240
|
-
</glide-core-dropdown>`);
|
241
|
-
component.querySelector('glide-core-dropdown-option')?.click();
|
242
|
-
expect(component.open).to.be.true;
|
258
|
+
const component = await fixture(html `<glide-core-dropdown-in-another-component></glide-core-dropdown-in-another-component>`);
|
259
|
+
// Wait for it to open.
|
260
|
+
await aTimeout(0);
|
261
|
+
const option = component.shadowRoot?.querySelector('glide-core-dropdown-option');
|
262
|
+
assert(option);
|
263
|
+
const { x, y } = option.getBoundingClientRect();
|
264
|
+
// Calling `click()` won't do because Dropdown relies on a "mouseup" event to
|
265
|
+
// decide if it should close.
|
266
|
+
await sendMouse({
|
267
|
+
type: 'click',
|
268
|
+
position: [Math.ceil(x), Math.ceil(y)],
|
269
|
+
});
|
270
|
+
const dropdown = component.shadowRoot?.querySelector('glide-core-dropdown');
|
271
|
+
expect(dropdown?.open).to.be.true;
|
243
272
|
});
|
244
273
|
it('remains open when an option is selected via Enter', async () => {
|
245
274
|
const component = await fixture(html `<glide-core-dropdown
|
@@ -330,6 +359,22 @@ it('does not activate the next option on ArrowDown when a tag is focused', async
|
|
330
359
|
await sendKeys({ press: 'ArrowDown' });
|
331
360
|
expect(options[0]?.privateActive).to.be.true;
|
332
361
|
});
|
362
|
+
it('updates its tag when the `label` of a selected option is changed programmatically', async () => {
|
363
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
|
364
|
+
<glide-core-dropdown-option
|
365
|
+
label="One"
|
366
|
+
selected
|
367
|
+
></glide-core-dropdown-option>
|
368
|
+
|
369
|
+
<glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
|
370
|
+
</glide-core-dropdown>`);
|
371
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
372
|
+
assert(option);
|
373
|
+
option.label = 'Three';
|
374
|
+
await elementUpdated(component);
|
375
|
+
const tag = component.shadowRoot?.querySelector('[data-test="tag"]');
|
376
|
+
expect(tag?.label).to.equal('Three');
|
377
|
+
});
|
333
378
|
it('selects and deselects options when `value` is changed programmatically', async () => {
|
334
379
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
|
335
380
|
<glide-core-dropdown-option
|
@@ -454,7 +499,7 @@ it('updates `value` when an option is selected or deselected via Space', async (
|
|
454
499
|
await sendKeys({ press: ' ' });
|
455
500
|
expect(component.value).to.deep.equal(['one']);
|
456
501
|
});
|
457
|
-
it('updates `value` when
|
502
|
+
it('updates `value` when multiselect is changed to `true` programmatically', async () => {
|
458
503
|
const component = await fixture(html `<glide-core-dropdown open>
|
459
504
|
<glide-core-dropdown-option
|
460
505
|
label="One"
|
@@ -493,9 +538,9 @@ it('updates `value` when the `value` of a selected option is changed programmati
|
|
493
538
|
const option = component.querySelector('glide-core-dropdown-option');
|
494
539
|
assert(option);
|
495
540
|
option.value = 'three';
|
496
|
-
expect(component.value).to.deep.equal(['
|
541
|
+
expect(component.value).to.deep.equal(['three', 'two']);
|
497
542
|
});
|
498
|
-
it('updates `value` when the `value` of a selected option is
|
543
|
+
it('updates `value` when the `value` of a selected option is emptied programmatically', async () => {
|
499
544
|
const component = await fixture(html `<glide-core-dropdown open multiple>
|
500
545
|
<glide-core-dropdown-option
|
501
546
|
label="One"
|
@@ -538,8 +583,13 @@ it('has no internal label when an option is newly selected', async () => {
|
|
538
583
|
const label = component.shadowRoot?.querySelector('[data-test="internal-label"]');
|
539
584
|
expect(label).to.not.exist;
|
540
585
|
});
|
541
|
-
it('
|
542
|
-
const component = await fixture(html `<glide-core-dropdown
|
586
|
+
it('hides tags to prevent overflow', async () => {
|
587
|
+
const component = await fixture(html `<glide-core-dropdown
|
588
|
+
label="Label"
|
589
|
+
placeholder="Placeholder"
|
590
|
+
multiple
|
591
|
+
style="display: block; max-width: 20rem;"
|
592
|
+
>
|
543
593
|
<glide-core-dropdown-option
|
544
594
|
label="One"
|
545
595
|
value="one"
|
@@ -565,14 +615,20 @@ it('only has so many tags when many options are selected', async () => {
|
|
565
615
|
options[1].selected = true;
|
566
616
|
options[2].selected = true;
|
567
617
|
options[3].selected = true;
|
568
|
-
|
618
|
+
// Wait for the Resize Observer to do its thing.
|
619
|
+
await aTimeout(0);
|
569
620
|
const tagContainers = [
|
570
621
|
...(component.shadowRoot?.querySelectorAll('[data-test="tag-container"]') ?? []),
|
571
622
|
].filter((element) => element.checkVisibility());
|
572
|
-
expect(tagContainers?.length).to.equal(
|
623
|
+
expect(tagContainers?.length).to.equal(2);
|
573
624
|
});
|
574
|
-
it('has overflow text when
|
575
|
-
const component = await fixture(html `<glide-core-dropdown
|
625
|
+
it('has overflow text when its tags are overflowing', async () => {
|
626
|
+
const component = await fixture(html `<glide-core-dropdown
|
627
|
+
label="Label"
|
628
|
+
placeholder="Placeholder"
|
629
|
+
multiple
|
630
|
+
style="display: block; max-width: 20rem;"
|
631
|
+
>
|
576
632
|
<glide-core-dropdown-option
|
577
633
|
label="One"
|
578
634
|
value="one"
|
@@ -598,9 +654,10 @@ it('has overflow text when many options are selected', async () => {
|
|
598
654
|
options[1].selected = true;
|
599
655
|
options[2].selected = true;
|
600
656
|
options[3].selected = true;
|
601
|
-
|
657
|
+
// Wait for the Resize Observer to do its thing.
|
658
|
+
await aTimeout(0);
|
602
659
|
const tagOverflow = component.shadowRoot?.querySelector('[data-test="tag-overflow-count"]');
|
603
|
-
expect(tagOverflow?.textContent?.trim()).to.equal('
|
660
|
+
expect(tagOverflow?.textContent?.trim()).to.equal('2');
|
604
661
|
});
|
605
662
|
it('deselects the option when its tag is removed', async () => {
|
606
663
|
const component = await fixture(html `<glide-core-dropdown
|
@@ -119,10 +119,8 @@ it('selects an option when its icon is clicked', async () => {
|
|
119
119
|
// Wait for it to open.
|
120
120
|
await aTimeout(0);
|
121
121
|
const option = component.querySelector('glide-core-dropdown-option');
|
122
|
-
option
|
123
|
-
?.querySelector('[
|
124
|
-
?.assignedElements()
|
125
|
-
?.at(0)
|
122
|
+
option
|
123
|
+
?.querySelector('[slot="icon"]')
|
126
124
|
?.dispatchEvent(new Event('click', { bubbles: true }));
|
127
125
|
expect(option?.selected).to.be.true;
|
128
126
|
});
|
@@ -257,6 +255,20 @@ it('deselects all other options when one is newly selected', async () => {
|
|
257
255
|
expect(options[1].selected).to.be.true;
|
258
256
|
expect(options[2].selected).to.be.false;
|
259
257
|
});
|
258
|
+
it('updates its internal label when the `label` of a selected option is changed programmatically', async () => {
|
259
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
260
|
+
<glide-core-dropdown-option
|
261
|
+
label="One"
|
262
|
+
selected
|
263
|
+
></glide-core-dropdown-option>
|
264
|
+
</glide-core-dropdown>`);
|
265
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
266
|
+
assert(option);
|
267
|
+
option.label = 'Two';
|
268
|
+
await elementUpdated(component);
|
269
|
+
const label = component.shadowRoot?.querySelector('[data-test="internal-label"]');
|
270
|
+
expect(label?.textContent?.trim()).to.equal(option?.label);
|
271
|
+
});
|
260
272
|
it('selects and deselects options when `value` is changed programmatically', async () => {
|
261
273
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
262
274
|
<glide-core-dropdown-option
|
@@ -549,3 +561,27 @@ it('clicks the button when `click()` is called', async () => {
|
|
549
561
|
const event = await oneEvent(button, 'click');
|
550
562
|
expect(event instanceof PointerEvent).to.be.true;
|
551
563
|
});
|
564
|
+
it('unhides its options when made unfilterable', async () => {
|
565
|
+
const component = await fixture(html `<glide-core-dropdown
|
566
|
+
label="Label"
|
567
|
+
placeholder="Placeholder"
|
568
|
+
filterable
|
569
|
+
>
|
570
|
+
<glide-core-dropdown-option
|
571
|
+
label="One"
|
572
|
+
value="one"
|
573
|
+
></glide-core-dropdown-option>
|
574
|
+
|
575
|
+
<glide-core-dropdown-option
|
576
|
+
label="Two"
|
577
|
+
value="two"
|
578
|
+
></glide-core-dropdown-option>
|
579
|
+
</glide-core-dropdown>`);
|
580
|
+
component.focus();
|
581
|
+
await sendKeys({ type: 'one' });
|
582
|
+
component.filterable = false;
|
583
|
+
const options = [
|
584
|
+
...component.querySelectorAll('glide-core-dropdown-option'),
|
585
|
+
].filter(({ hidden }) => !hidden);
|
586
|
+
expect(options.length).to.equal(2);
|
587
|
+
});
|
@@ -8,8 +8,6 @@ declare global {
|
|
8
8
|
}
|
9
9
|
}
|
10
10
|
/**
|
11
|
-
* @description Aligns form control labels and the controls themselves in two columns. Only horizontally oriented controls are supported.
|
12
|
-
*
|
13
11
|
* @slot - GlideCoreCheckbox | GlideCoreCheckboxGroup | GlideCoreDropdown | GlideCoreInput | GlideCoreTextArea.
|
14
12
|
*/
|
15
13
|
export default class GlideCoreFormControlsLayout extends LitElement {
|
package/dist/icon-button.d.ts
CHANGED
@@ -5,9 +5,7 @@ declare global {
|
|
5
5
|
}
|
6
6
|
}
|
7
7
|
/**
|
8
|
-
* @
|
9
|
-
*
|
10
|
-
* @slot - Reserved for the icon to display inside of the button.
|
8
|
+
* @slot - An icon.
|
11
9
|
*/
|
12
10
|
export default class GlideCoreIconButton extends LitElement {
|
13
11
|
#private;
|
@@ -17,9 +15,9 @@ export default class GlideCoreIconButton extends LitElement {
|
|
17
15
|
ariaExpanded: 'true' | 'false' | null;
|
18
16
|
ariaHasPopup: 'true' | 'false' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | null;
|
19
17
|
disabled: boolean;
|
20
|
-
/** For screenreaders. Required. */
|
21
18
|
label: string;
|
22
19
|
variant: 'primary' | 'secondary' | 'tertiary';
|
20
|
+
click(): void;
|
23
21
|
firstUpdated(): void;
|
24
22
|
render(): import("lit").TemplateResult<1>;
|
25
23
|
}
|
package/dist/icon-button.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(t,e,o,r){var i,a=arguments.length,l=a<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(t,e,o,r);else for(var n=t.length-1;n>=0;n--)(i=t[n])&&(l=(a<3?i(l):a>3?i(e,o,l):i(e,o))||l);return a>3&&l&&Object.defineProperty(e,o,l),l};import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{owSlot}from"./library/ow.js";import styles from"./icon-button.styles.js";let GlideCoreIconButton=class GlideCoreIconButton extends LitElement{constructor(){super(...arguments),this.ariaControls=null,this.ariaExpanded=null,this.ariaHasPopup=null,this.disabled=!1,this.label="",this.variant="primary",this.#t=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#
|
1
|
+
var __decorate=this&&this.__decorate||function(t,e,o,r){var i,a=arguments.length,l=a<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(t,e,o,r);else for(var n=t.length-1;n>=0;n--)(i=t[n])&&(l=(a<3?i(l):a>3?i(e,o,l):i(e,o))||l);return a>3&&l&&Object.defineProperty(e,o,l),l};import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{owSlot}from"./library/ow.js";import styles from"./icon-button.styles.js";let GlideCoreIconButton=class GlideCoreIconButton extends LitElement{constructor(){super(...arguments),this.ariaControls=null,this.ariaExpanded=null,this.ariaHasPopup=null,this.disabled=!1,this.label="",this.variant="primary",this.#t=createRef(),this.#e=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}click(){this.#t.value?.click()}firstUpdated(){owSlot(this.#e.value)}render(){return html`<button aria-controls="${ifDefined(this.ariaControls??void 0)}" aria-expanded="${ifDefined(this.ariaExpanded??void 0)}" aria-haspopup="${ifDefined(this.ariaHasPopup??void 0)}" aria-label="${this.label}" class="${classMap({component:!0,primary:"primary"===this.variant,secondary:"secondary"===this.variant,tertiary:"tertiary"===this.variant})}" data-test="button" type="button" ?disabled="${this.disabled}" ${ref(this.#t)}><slot @slotchange="${this.#o}" ${ref(this.#e)}></slot></button>`}#t;#e;#o(){owSlot(this.#e.value)}};__decorate([property({attribute:"aria-controls",reflect:!0})],GlideCoreIconButton.prototype,"ariaControls",void 0),__decorate([property({attribute:"aria-expanded",reflect:!0})],GlideCoreIconButton.prototype,"ariaExpanded",void 0),__decorate([property({attribute:"aria-haspopup",reflect:!0})],GlideCoreIconButton.prototype,"ariaHasPopup",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreIconButton.prototype,"disabled",void 0),__decorate([property()],GlideCoreIconButton.prototype,"label",void 0),__decorate([property({reflect:!0})],GlideCoreIconButton.prototype,"variant",void 0),GlideCoreIconButton=__decorate([customElement("glide-core-icon-button")],GlideCoreIconButton);export default GlideCoreIconButton;
|
@@ -1,106 +1,38 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
2
|
import './icon-button.js';
|
3
3
|
import { ArgumentError } from 'ow';
|
4
|
-
import {
|
4
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
5
5
|
import GlideCoreIconButton from './icon-button.js';
|
6
6
|
import sinon from 'sinon';
|
7
7
|
GlideCoreIconButton.shadowRootOptions.mode = 'open';
|
8
|
-
const icon = html `<svg
|
9
|
-
width="16"
|
10
|
-
height="16"
|
11
|
-
stroke="currentColor"
|
12
|
-
fill="none"
|
13
|
-
stroke-linecap="round"
|
14
|
-
stroke-linejoin="round"
|
15
|
-
stroke-width="2"
|
16
|
-
viewBox="0 0 24 24"
|
17
|
-
aria-hidden="true"
|
18
|
-
>
|
19
|
-
<path d="M16.51 9.873l-4.459 4.31-4.458-4.31"></path>
|
20
|
-
</svg>`;
|
21
8
|
it('registers', async () => {
|
22
9
|
expect(window.customElements.get('glide-core-icon-button')).to.equal(GlideCoreIconButton);
|
23
10
|
});
|
24
11
|
it('is accessible', async () => {
|
25
|
-
const component = await fixture(html `<glide-core-icon-button label="
|
26
|
-
|
27
|
-
>`);
|
12
|
+
const component = await fixture(html `<glide-core-icon-button label="Label">
|
13
|
+
<div>Icon</div>
|
14
|
+
</glide-core-icon-button>`);
|
28
15
|
await expect(component).to.be.accessible();
|
29
16
|
});
|
30
17
|
it('has defaults', async () => {
|
31
|
-
const component = await fixture(html `<glide-core-icon-button label="
|
32
|
-
|
33
|
-
>`);
|
34
|
-
const button = component.shadowRoot?.querySelector('button');
|
35
|
-
assert(button);
|
18
|
+
const component = await fixture(html `<glide-core-icon-button label="Label">
|
19
|
+
<div>Icon</div>
|
20
|
+
</glide-core-icon-button>`);
|
21
|
+
const button = component.shadowRoot?.querySelector('[data-test="button"]');
|
36
22
|
expect(component.ariaControls).to.equal(null);
|
37
23
|
expect(component.ariaExpanded).to.equal(null);
|
38
24
|
expect(component.ariaHasPopup).to.equal(null);
|
39
|
-
expect(component.disabled).to.
|
25
|
+
expect(component.disabled).to.be.false;
|
40
26
|
expect(component.variant).to.equal('primary');
|
41
|
-
expect(button
|
42
|
-
expect(button
|
43
|
-
expect(button
|
44
|
-
expect(button
|
45
|
-
expect([...button.classList]).to.deep.equal(['component', 'primary']);
|
46
|
-
});
|
47
|
-
it('delegates focus', async () => {
|
48
|
-
const component = await fixture(html `<glide-core-icon-button label="test-icon-button"
|
49
|
-
>${icon}</glide-core-icon-button
|
50
|
-
>`);
|
51
|
-
component.focus();
|
52
|
-
expect(component.shadowRoot?.activeElement).to.equal(component.shadowRoot?.querySelector('button'));
|
53
|
-
});
|
54
|
-
it('uses the provided "label" for the aria-label', async () => {
|
55
|
-
const component = await fixture(html `<glide-core-icon-button label="test-icon-button"
|
56
|
-
>${icon}</glide-core-icon-button
|
57
|
-
>`);
|
58
|
-
expect(component.shadowRoot?.querySelector('button')?.getAttribute('aria-label')).to.equal('test-icon-button');
|
59
|
-
});
|
60
|
-
it('renders a default slot', async () => {
|
61
|
-
const component = await fixture(html `<glide-core-icon-button label="test-icon-button"
|
62
|
-
><span data-content>Inner content</span></glide-core-icon-button
|
63
|
-
>`);
|
64
|
-
expect(component.querySelector('[data-content]')).to.be.ok;
|
65
|
-
expect(component.querySelector('[data-content]')).to.be.visible;
|
66
|
-
});
|
67
|
-
it('renders a primary variant', async () => {
|
68
|
-
const component = await fixture(html `<glide-core-icon-button label="test-icon-button" variant="primary"
|
69
|
-
>${icon}</glide-core-icon-button
|
70
|
-
>`);
|
71
|
-
expect([
|
72
|
-
...component.shadowRoot.querySelector('button').classList,
|
73
|
-
]).to.deep.equal(['component', 'primary']);
|
74
|
-
});
|
75
|
-
it('renders a secondary variant', async () => {
|
76
|
-
const component = await fixture(html `<glide-core-icon-button label="test-icon-button" variant="secondary"
|
77
|
-
>${icon}</glide-core-icon-button
|
78
|
-
>`);
|
79
|
-
expect([
|
80
|
-
...component.shadowRoot.querySelector('button').classList,
|
81
|
-
]).to.deep.equal(['component', 'secondary']);
|
82
|
-
});
|
83
|
-
it('renders a tertiary variant', async () => {
|
84
|
-
const component = await fixture(html `<glide-core-icon-button label="test-icon-button" variant="tertiary"
|
85
|
-
>${icon}</glide-core-icon-button
|
86
|
-
>`);
|
87
|
-
expect([
|
88
|
-
...component.shadowRoot.querySelector('button').classList,
|
89
|
-
]).to.deep.equal(['component', 'tertiary']);
|
90
|
-
});
|
91
|
-
it('sets the disabled attribute', async () => {
|
92
|
-
const component = await fixture(html `<glide-core-icon-button label="test-icon-button" disabled
|
93
|
-
>${icon}</glide-core-icon-button
|
94
|
-
>`);
|
95
|
-
expect(component.disabled).to.equal(true);
|
96
|
-
expect(component.shadowRoot?.querySelector('button')?.disabled).to.equal(true);
|
27
|
+
expect(button?.getAttribute('aria-controls')).to.equal(null);
|
28
|
+
expect(button?.ariaExpanded).to.equal(null);
|
29
|
+
expect(button?.ariaHasPopup).to.equal(null);
|
30
|
+
expect(button?.disabled).to.be.false;
|
97
31
|
});
|
98
32
|
it('throws if it does not have a default slot', async () => {
|
99
33
|
const spy = sinon.spy();
|
100
34
|
try {
|
101
|
-
await fixture(html `<glide-core-icon-button
|
102
|
-
label="test-icon-button"
|
103
|
-
></glide-core-icon-button>`);
|
35
|
+
await fixture(html `<glide-core-icon-button label="Label"></glide-core-icon-button>`);
|
104
36
|
}
|
105
37
|
catch (error) {
|
106
38
|
if (error instanceof ArgumentError) {
|
@@ -0,0 +1 @@
|
|
1
|
+
import './icon-button.js';
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
|
+
import './icon-button.js';
|
3
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
4
|
+
import GlideCoreIconButton from './icon-button.js';
|
5
|
+
GlideCoreIconButton.shadowRootOptions.mode = 'open';
|
6
|
+
it('focuses its button when `focus()` is called', async () => {
|
7
|
+
const component = await fixture(html `<glide-core-icon-button label="Label">
|
8
|
+
<div>Icon</div>
|
9
|
+
</glide-core-icon-button>`);
|
10
|
+
component.focus();
|
11
|
+
const button = component.shadowRoot?.querySelector('[data-test="button"]');
|
12
|
+
expect(component.shadowRoot?.activeElement).to.equal(button);
|
13
|
+
});
|
package/dist/input.d.ts
CHANGED
@@ -9,16 +9,14 @@ declare global {
|
|
9
9
|
export declare const SUPPORTED_TYPES: readonly ["email", "number", "password", "search", "tel", "text", "url"];
|
10
10
|
type SupportedTypes = (typeof SUPPORTED_TYPES)[number];
|
11
11
|
/**
|
12
|
-
* @description An input with a label and optional description and tooltip. Participates in forms and validation via `FormData` and various methods.
|
13
|
-
*
|
14
12
|
* @event change - `(event: Event) => void`
|
15
13
|
* @event input - `(event: Event) => void`
|
16
14
|
* @event invalid - `(event: Event) => void`
|
17
15
|
*
|
18
16
|
* @slot tooltip - Content for the tooltip.
|
19
17
|
* @slot description - Additional information or context.
|
20
|
-
* @slot prefix - An optional icon
|
21
|
-
* @slot suffix - An optional icon
|
18
|
+
* @slot prefix-icon - An optional icon before the input field.
|
19
|
+
* @slot suffix-icon - An optional icon after the input field.
|
22
20
|
*/
|
23
21
|
export default class GlideCoreInput extends LitElement {
|
24
22
|
#private;
|
@@ -26,7 +24,7 @@ export default class GlideCoreInput extends LitElement {
|
|
26
24
|
static shadowRootOptions: ShadowRootInit;
|
27
25
|
static styles: import("lit").CSSResult[];
|
28
26
|
type: SupportedTypes;
|
29
|
-
name
|
27
|
+
name: string;
|
30
28
|
value: string;
|
31
29
|
label?: string;
|
32
30
|
hideLabel: boolean;
|
@@ -35,6 +33,7 @@ export default class GlideCoreInput extends LitElement {
|
|
35
33
|
clearable: boolean;
|
36
34
|
spellcheck: boolean;
|
37
35
|
autocapitalize: 'on' | 'off' | 'none' | 'sentences' | 'words' | 'characters';
|
36
|
+
autocomplete: 'on' | 'off';
|
38
37
|
/** For 'password' type, whether to show a button to toggle the password's visibility */
|
39
38
|
passwordToggle: boolean;
|
40
39
|
required: boolean;
|
package/dist/input.js
CHANGED
@@ -1 +1 @@
|
|
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="${
|
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-icon"></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="${this.autocapitalize}" autocomplete="${this.autocomplete}" spellcheck="${this.spellcheck}" ?required="${this.required}" ?readonly="${this.readonly}" ?disabled="${this.disabled}" @focus="${this.#s}" @blur="${this.#a}" @change="${this.#l}" @input="${this.#n}" @keydown="${this.#d}" ${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.#h.term("clearEntry",this.label)}" @click="${this.#p}"><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.#c}">${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-icon">${"search"===this.type?magnifyingGlassIcon:html`<slot name="suffix-icon"></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.#h.term("displayedCharacterCount",this.#u,this.maxlength)} </span><span class="hidden" data-test="character-count-announcement">${this.#h.term("announcedCharacterCount",this.#u,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.name="",this.value="",this.hideLabel=!1,this.orientation="horizontal",this.clearable=!1,this.spellcheck=!1,this.autocapitalize="on",this.autocomplete="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.#h=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;#h;get#u(){return this.value.length}#o;get#t(){return Boolean(!this.disabled&&!this.readonly&&this.maxlength&&this.#u>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))}#p(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}#d(e){"Enter"===e.key&&this.form?.requestSubmit()}#c(){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({reflect:!0})],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({reflect:!0})],GlideCoreInput.prototype,"placeholder",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"clearable",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreInput.prototype,"spellcheck",void 0),__decorate([property({reflect:!0})],GlideCoreInput.prototype,"autocapitalize",void 0),__decorate([property({reflect:!0})],GlideCoreInput.prototype,"autocomplete",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({reflect:!0,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),reflect:!0})],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
@@ -83,7 +83,7 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
|
|
83
83
|
}
|
84
84
|
}
|
85
85
|
|
86
|
-
.suffix {
|
86
|
+
.suffix-icon {
|
87
87
|
align-items: center;
|
88
88
|
display: flex;
|
89
89
|
}
|
@@ -91,7 +91,7 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
|
|
91
91
|
|
92
92
|
.clear-icon-button,
|
93
93
|
.password-toggle,
|
94
|
-
::slotted([slot='suffix']) {
|
94
|
+
::slotted([slot='suffix-icon']) {
|
95
95
|
align-items: center;
|
96
96
|
background: none;
|
97
97
|
border: none;
|
@@ -104,8 +104,8 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
|
|
104
104
|
.clear-icon-button,
|
105
105
|
.password-toggle,
|
106
106
|
.search-icon,
|
107
|
-
::slotted([slot='prefix']),
|
108
|
-
::slotted([slot='suffix']) {
|
107
|
+
::slotted([slot='prefix-icon']),
|
108
|
+
::slotted([slot='suffix-icon']) {
|
109
109
|
display: flex;
|
110
110
|
}
|
111
111
|
|
@@ -136,55 +136,3 @@ it('does not render a character count when attribute `maxlength` is set less tha
|
|
136
136
|
const container = component.shadowRoot?.querySelector('[data-test="character-count-container"]');
|
137
137
|
expect(container).to.be.null;
|
138
138
|
});
|
139
|
-
it('supports a "tooltip" slot', async () => {
|
140
|
-
const component = await fixture(html `<glide-core-input label="test">
|
141
|
-
<div slot="tooltip">Tooltip</div>
|
142
|
-
</glide-core-input>`);
|
143
|
-
const assignedElements = component.shadowRoot
|
144
|
-
?.querySelector('slot[name="tooltip"]')
|
145
|
-
?.assignedElements();
|
146
|
-
expect(assignedElements?.at(0)?.textContent).to.equal('Tooltip');
|
147
|
-
});
|
148
|
-
it('supports a "description" slot', async () => {
|
149
|
-
const component = await fixture(html `
|
150
|
-
<glide-core-input label="Test">
|
151
|
-
<div slot="description">Description</div>
|
152
|
-
</glide-core-input>
|
153
|
-
`);
|
154
|
-
const assignedElements = component.shadowRoot
|
155
|
-
?.querySelector('slot[name="description"]')
|
156
|
-
?.assignedElements();
|
157
|
-
expect(assignedElements?.at(0)?.textContent).to.equal('Description');
|
158
|
-
});
|
159
|
-
it('supports a "prefix" icon slot', async () => {
|
160
|
-
const component = await fixture(html `
|
161
|
-
<glide-core-input label="Test">
|
162
|
-
<div slot="prefix">
|
163
|
-
<span data-svg></span>
|
164
|
-
</div>
|
165
|
-
</glide-core-input>
|
166
|
-
`);
|
167
|
-
const assignedElements = component.shadowRoot
|
168
|
-
?.querySelector('slot[name="prefix"]')
|
169
|
-
?.assignedElements();
|
170
|
-
const slottedSvg = assignedElements
|
171
|
-
?.at(0)
|
172
|
-
?.querySelector('[data-svg]');
|
173
|
-
expect(slottedSvg).to.exist;
|
174
|
-
});
|
175
|
-
it('supports a "suffix" icon slot', async () => {
|
176
|
-
const component = await fixture(html `
|
177
|
-
<glide-core-input label="Test">
|
178
|
-
<div slot="suffix">
|
179
|
-
<span data-svg></span>
|
180
|
-
</div>
|
181
|
-
</glide-core-input>
|
182
|
-
`);
|
183
|
-
const assignedElements = component.shadowRoot
|
184
|
-
?.querySelector('slot[name="suffix"]')
|
185
|
-
?.assignedElements();
|
186
|
-
const slottedSvg = assignedElements
|
187
|
-
?.at(0)
|
188
|
-
?.querySelector('[data-svg]');
|
189
|
-
expect(slottedSvg).to.exist;
|
190
|
-
});
|