@crowdstrike/glide-core 0.8.0 → 0.9.1
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/accordion.d.ts +7 -3
- package/dist/button-group.button.d.ts +12 -16
- package/dist/button-group.button.js +1 -1
- package/dist/button-group.button.styles.js +76 -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 +10 -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.d.ts +3 -0
- package/dist/button.test.basics.js +1 -1
- package/dist/checkbox-group.d.ts +6 -2
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.stories.d.ts +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 +12 -5
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.stories.d.ts +1 -1
- package/dist/checkbox.styles.js +10 -0
- package/dist/checkbox.test.basics.js +15 -6
- package/dist/checkbox.test.events.js +16 -8
- package/dist/checkbox.test.focus.js +3 -3
- package/dist/checkbox.test.form.js +1 -0
- package/dist/checkbox.test.interactions.js +123 -0
- package/dist/drawer.d.ts +5 -5
- package/dist/drawer.js +1 -1
- package/dist/drawer.stories.d.ts +0 -1
- package/dist/dropdown.d.ts +9 -6
- 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.d.ts +2 -0
- 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 +4 -9
- 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 +25 -13
- package/dist/label.test.basics.js +26 -24
- package/dist/library/expect-argument-error.js +1 -1
- package/dist/library/localize.d.ts +4 -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.events.js +197 -7
- package/dist/menu.test.focus.d.ts +1 -0
- package/dist/menu.test.focus.js +13 -6
- package/dist/menu.test.interactions.js +214 -58
- package/dist/modal.icon-button.test.basics.js +1 -1
- package/dist/modal.js +1 -1
- package/dist/modal.stories.d.ts +1 -0
- 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 +3 -3
- package/dist/modal.test.basics.js +1 -1
- package/dist/modal.test.events.js +10 -10
- package/dist/radio-group.d.ts +4 -3
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.stories.d.ts +1 -1
- package/dist/radio-group.styles.js +1 -1
- package/dist/radio-group.test.focus.js +3 -3
- package/dist/radio.d.ts +2 -2
- package/dist/radio.js +1 -1
- package/dist/radio.styles.js +33 -0
- package/dist/split-container.d.ts +1 -1
- package/dist/split-container.test.basics.js +4 -0
- package/dist/split-link.test.interactions.js +1 -1
- package/dist/status-indicator.d.ts +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/tabs.stories.d.ts +1 -0
- package/dist/tag.d.ts +3 -6
- package/dist/tag.test.basics.js +2 -2
- package/dist/textarea.d.ts +4 -4
- 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.d.ts +3 -3
- package/dist/toggle.js +1 -1
- package/dist/toggle.stories.d.ts +1 -1
- package/dist/toggle.test.focus.js +1 -1
- package/dist/toggle.test.interactions.d.ts +1 -0
- package/dist/{toggle.test.states.js → toggle.test.interactions.js} +26 -0
- package/dist/tooltip.d.ts +9 -7
- 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 +1 -2
- package/dist/tree.item.d.ts +1 -5
- package/dist/tree.item.icon-button.d.ts +1 -0
- package/dist/tree.item.icon-button.js +1 -1
- package/dist/tree.item.icon-button.test.basics.js +9 -0
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +2 -1
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.menu.test.basics.js +15 -0
- package/dist/tree.item.styles.js +2 -0
- package/dist/tree.item.test.basics.d.ts +2 -1
- package/dist/tree.item.test.basics.js +46 -4
- package/dist/tree.js +1 -1
- package/dist/tree.test.basics.js +1 -1
- package/dist/tree.test.focus.js +91 -4
- package/package.json +3 -4
- package/dist/checkbox.test.states.js +0 -63
- 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/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
|
+
});
|
@@ -1,15 +1,17 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
2
|
import './input.js';
|
3
|
-
import { expect, fixture, html } from '@open-wc/testing';
|
3
|
+
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
|
4
4
|
import { sendKeys } from '@web/test-runner-commands';
|
5
|
-
import
|
6
|
-
|
5
|
+
import GlideCoreInput from './input.js';
|
6
|
+
GlideCoreInput.shadowRootOptions.mode = 'open';
|
7
7
|
it('is valid if empty but not required', async () => {
|
8
8
|
const input = await fixture(html `<glide-core-input></glide-core-input>`);
|
9
9
|
expect(input.validity?.valid).to.be.true;
|
10
10
|
expect(input.validity?.valueMissing).to.be.false;
|
11
11
|
expect(input.checkValidity()).to.be.true;
|
12
12
|
expect(input.reportValidity()).to.be.true;
|
13
|
+
await elementUpdated(input);
|
14
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
13
15
|
});
|
14
16
|
it('is valid after being filled in when empty and required', async () => {
|
15
17
|
const input = await fixture(html `<glide-core-input required></glide-core-input>`);
|
@@ -19,6 +21,8 @@ it('is valid after being filled in when empty and required', async () => {
|
|
19
21
|
expect(input.validity?.valueMissing).to.be.false;
|
20
22
|
expect(input.checkValidity()).to.be.true;
|
21
23
|
expect(input.reportValidity()).to.be.true;
|
24
|
+
await elementUpdated(input);
|
25
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
22
26
|
});
|
23
27
|
it('is invalid if no value and required', async () => {
|
24
28
|
const input = await fixture(html `<glide-core-input required></glide-core-input>`);
|
@@ -27,6 +31,8 @@ it('is invalid if no value and required', async () => {
|
|
27
31
|
expect(input.willValidate).to.be.true;
|
28
32
|
expect(input.checkValidity()).to.be.false;
|
29
33
|
expect(input.reportValidity()).to.be.false;
|
34
|
+
await elementUpdated(input);
|
35
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'true');
|
30
36
|
});
|
31
37
|
it('is invalid after value is cleared when required', async () => {
|
32
38
|
const input = await fixture(html `<glide-core-input
|
@@ -34,13 +40,76 @@ it('is invalid after value is cleared when required', async () => {
|
|
34
40
|
value="value"
|
35
41
|
required
|
36
42
|
></glide-core-input>`);
|
37
|
-
const clearButton = input.shadowRoot?.querySelector('
|
43
|
+
const clearButton = input.shadowRoot?.querySelector('[data-test="clear-button"]');
|
38
44
|
clearButton?.click();
|
39
45
|
await input.updateComplete;
|
40
46
|
expect(input.validity?.valid).to.be.false;
|
41
47
|
expect(input.validity?.valueMissing).to.be.true;
|
42
48
|
expect(input.checkValidity()).to.be.false;
|
43
49
|
expect(input.reportValidity()).to.be.false;
|
50
|
+
await elementUpdated(input);
|
51
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'true');
|
52
|
+
});
|
53
|
+
it('is valid when empty and does not exceed `maxlength`', async () => {
|
54
|
+
const input = await fixture(html `<glide-core-input maxlength="3"></glide-core-input>`);
|
55
|
+
expect(input.validity?.valid).to.be.true;
|
56
|
+
expect(input.validity?.valueMissing).to.be.false;
|
57
|
+
expect(input.validity?.tooLong).to.be.false;
|
58
|
+
expect(input.checkValidity()).to.be.true;
|
59
|
+
expect(input.reportValidity()).to.be.true;
|
60
|
+
await elementUpdated(input);
|
61
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
62
|
+
});
|
63
|
+
it('is valid when filled in and does not exceed `maxlength`', async () => {
|
64
|
+
const input = await fixture(html `<glide-core-input maxlength="3"></glide-core-input>`);
|
65
|
+
input.focus();
|
66
|
+
await sendKeys({ type: 'val' });
|
67
|
+
expect(input.validity?.valid).to.be.true;
|
68
|
+
expect(input.validity?.valueMissing).to.be.false;
|
69
|
+
expect(input.validity?.tooLong).to.be.false;
|
70
|
+
expect(input.checkValidity()).to.be.true;
|
71
|
+
expect(input.reportValidity()).to.be.true;
|
72
|
+
await elementUpdated(input);
|
73
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
74
|
+
});
|
75
|
+
it('is valid when filled in, disabled, and value exceeds `maxlength`', async () => {
|
76
|
+
const input = await fixture(html `<glide-core-input
|
77
|
+
value="value"
|
78
|
+
maxlength="3"
|
79
|
+
disabled
|
80
|
+
></glide-core-input>`);
|
81
|
+
expect(input.validity?.valid).to.be.true;
|
82
|
+
expect(input.validity?.valueMissing).to.be.false;
|
83
|
+
expect(input.validity?.tooLong).to.be.false;
|
84
|
+
expect(input.checkValidity()).to.be.true;
|
85
|
+
expect(input.reportValidity()).to.be.true;
|
86
|
+
await elementUpdated(input);
|
87
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
88
|
+
});
|
89
|
+
it('is valid when filled in, readonly, and value exceeds `maxlength`', async () => {
|
90
|
+
const input = await fixture(html `<glide-core-input
|
91
|
+
value="value"
|
92
|
+
maxlength="3"
|
93
|
+
readonly
|
94
|
+
></glide-core-input>`);
|
95
|
+
expect(input.validity?.valid).to.be.true;
|
96
|
+
expect(input.validity?.valueMissing).to.be.false;
|
97
|
+
expect(input.validity?.tooLong).to.be.false;
|
98
|
+
expect(input.checkValidity()).to.be.true;
|
99
|
+
expect(input.reportValidity()).to.be.true;
|
100
|
+
await elementUpdated(input);
|
101
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
102
|
+
});
|
103
|
+
it('is invalid when filled in and exceeds `maxlength`', async () => {
|
104
|
+
const input = await fixture(html `<glide-core-input maxlength="3"></glide-core-input>`);
|
105
|
+
input.focus();
|
106
|
+
await sendKeys({ type: 'value' });
|
107
|
+
expect(input.validity?.valid).to.be.false;
|
108
|
+
expect(input.validity?.tooLong).to.be.true;
|
109
|
+
expect(input.checkValidity()).to.be.false;
|
110
|
+
expect(input.reportValidity()).to.be.false;
|
111
|
+
await elementUpdated(input);
|
112
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'true');
|
44
113
|
});
|
45
114
|
it('is valid if no value and required but disabled', async () => {
|
46
115
|
const input = await fixture(html `<glide-core-input disabled required></glide-core-input>`);
|
@@ -48,4 +117,64 @@ it('is valid if no value and required but disabled', async () => {
|
|
48
117
|
expect(input.validity?.valueMissing).to.be.false;
|
49
118
|
expect(input.checkValidity()).to.be.true;
|
50
119
|
expect(input.reportValidity()).to.be.true;
|
120
|
+
await elementUpdated(input);
|
121
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
122
|
+
});
|
123
|
+
it('updates validity when `required` and `value` is changed programmatically', async () => {
|
124
|
+
const input = await fixture(html `<glide-core-input label="Label" required></glide-core-input>`);
|
125
|
+
expect(input.validity?.valid).to.be.false;
|
126
|
+
expect(input.validity?.valueMissing).to.be.true;
|
127
|
+
expect(input.checkValidity()).to.be.false;
|
128
|
+
expect(input.reportValidity()).to.be.false;
|
129
|
+
await elementUpdated(input);
|
130
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'true');
|
131
|
+
input.value = 'text';
|
132
|
+
await elementUpdated(input);
|
133
|
+
expect(input.validity?.valid).to.be.true;
|
134
|
+
expect(input.validity?.valueMissing).to.be.false;
|
135
|
+
expect(input.checkValidity()).to.be.true;
|
136
|
+
expect(input.reportValidity()).to.be.true;
|
137
|
+
await elementUpdated(input);
|
138
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
139
|
+
// Resetting the value to empty to ensure it goes
|
140
|
+
// back to an invalid state
|
141
|
+
input.value = '';
|
142
|
+
await elementUpdated(input);
|
143
|
+
expect(input.validity?.valid).to.be.false;
|
144
|
+
expect(input.validity?.valueMissing).to.be.true;
|
145
|
+
expect(input.checkValidity()).to.be.false;
|
146
|
+
expect(input.reportValidity()).to.be.false;
|
147
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'true');
|
148
|
+
});
|
149
|
+
it('is invalid when `value` is empty and `required` is set to `true` programmatically', async () => {
|
150
|
+
const input = await fixture(html `<glide-core-input label="Label"></glide-core-input>`);
|
151
|
+
expect(input.validity?.valid).to.be.true;
|
152
|
+
expect(input.validity?.valueMissing).to.be.false;
|
153
|
+
expect(input.checkValidity()).to.be.true;
|
154
|
+
expect(input.reportValidity()).to.be.true;
|
155
|
+
await elementUpdated(input);
|
156
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
157
|
+
input.required = true;
|
158
|
+
await elementUpdated(input);
|
159
|
+
expect(input.validity?.valid).to.be.false;
|
160
|
+
expect(input.validity?.valueMissing).to.be.true;
|
161
|
+
expect(input.checkValidity()).to.be.false;
|
162
|
+
expect(input.reportValidity()).to.be.false;
|
163
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'true');
|
164
|
+
});
|
165
|
+
it('is valid when `value` is empty and `required` is set to `false` programmatically', async () => {
|
166
|
+
const input = await fixture(html `<glide-core-input label="Label" required></glide-core-input>`);
|
167
|
+
expect(input.validity?.valid).to.be.false;
|
168
|
+
expect(input.validity?.valueMissing).to.be.true;
|
169
|
+
expect(input.checkValidity()).to.be.false;
|
170
|
+
expect(input.reportValidity()).to.be.false;
|
171
|
+
await elementUpdated(input);
|
172
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'true');
|
173
|
+
input.required = false;
|
174
|
+
await elementUpdated(input);
|
175
|
+
expect(input.validity?.valid).to.be.true;
|
176
|
+
expect(input.validity?.valueMissing).to.be.false;
|
177
|
+
expect(input.checkValidity()).to.be.true;
|
178
|
+
expect(input.reportValidity()).to.be.true;
|
179
|
+
expect(input.shadowRoot?.querySelector('input')).to.have.attribute('aria-invalid', 'false');
|
51
180
|
});
|
package/dist/label.d.ts
CHANGED
package/dist/label.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,t,o,l){var i,s=arguments.length,r=s<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,o,l);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(r=(s<3?i(r):s>3?i(t,o,r):i(t,o))||r);return s>3&&r&&Object.defineProperty(t,o,r),r};import"./tooltip.js";import{LitElement,html}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 ow,{owSlot}from"./library/ow.js";import styles from"./label.styles.js";
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,l){var i,s=arguments.length,r=s<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,o,l);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(r=(s<3?i(r):s>3?i(t,o,r):i(t,o))||r);return s>3&&r&&Object.defineProperty(t,o,r),r};import"./tooltip.js";import{LitElement,html,svg}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 ow,{owSlot}from"./library/ow.js";import styles from"./label.styles.js";const infoCircleIcon=svg`<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"><path d="M12 16L12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="8" r="1" fill="currentColor">`;let GlideCoreLabel=class GlideCoreLabel extends LitElement{constructor(){super(...arguments),this.disabled=!1,this.error=!1,this.hide=!1,this.orientation="horizontal",this.required=!1,this.hasDescriptionSlot=!1,this.hasSummarySlot=!1,this.hasTooltipSlot=!1,this.isLabelTooltip=!1,this.label="",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#i=new LocalizeController(this),this.#s=createRef(),this.#r=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#t.value),owSlot(this.#e.value)}render(){return html`<div class="${classMap({component:!0,horizontal:"horizontal"===this.orientation,vertical:"vertical"===this.orientation,left:"left"===this.split,middle:"middle"===this.split,"hidden-label":this.hide})}"><div class="${classMap({"tooltips-and-label":!0,hidden:this.hide,left:"left"===this.split,middle:"middle"===this.split})}" part="tooltips-and-label"><glide-core-tooltip class="${classMap({"optional-tooltip":!0,vertical:"vertical"===this.orientation,visible:this.hasTooltipSlot})}" placement="${"vertical"===this.orientation?"right":"bottom"}"><span class="optional-tooltip-target" slot="target" tabindex="0"><svg aria-label="${this.#i.term("moreInformation")}" width="16" height="16" viewBox="0 0 24 24" fill="none">${infoCircleIcon}</svg></span><slot name="tooltip" @slotchange="${this.#a}" ${ref(this.#r)}></slot></glide-core-tooltip><glide-core-tooltip class="label-tooltip" placement="right" ?disabled="${!this.isLabelTooltip}"><div class="${classMap({label:!0,disabled:this.disabled})}" data-test="label" slot="target" ${ref(this.#l)}><slot @slotchange="${this.#n}" ${ref(this.#t)}></slot>${this.required?html`<span aria-hidden="true" class="required-symbol">*</span>`:""}</div><div aria-hidden="true">${this.label}</div></glide-core-tooltip></div><div class="control-and-summary"><slot class="${classMap({control:!0,error:this.error,disabled:this.disabled,vertical:"vertical"===this.orientation,summaryless:!this.hasSummarySlot,"hidden-label":this.hide})}" name="control" @slotchange="${this.#d}" ${ref(this.#e)}></slot><slot class="${classMap({summary:!0,error:this.error})}" name="summary" @slotchange="${this.#c}" ${ref(this.#s)}></slot></div><slot class="${classMap({description:!0,visible:this.hasDescriptionSlot,error:this.error,tooltip:this.hasTooltipSlot})}" id="description" name="description" @slotchange="${this.#h}" ${ref(this.#o)}></slot></div>`}#e;#t;#o;#l;#i;#s;#r;#d(){owSlot(this.#e.value)}#n(){owSlot(this.#t.value);const e=this.#t.value?.assignedElements().at(0),t=this.#l.value;ow(e,ow.object.instanceOf(Element)),ow(t,ow.object.instanceOf(HTMLElement)),e.textContent&&(this.label=e.textContent);new ResizeObserver((()=>{this.isLabelTooltip=e.getBoundingClientRect().width>t.getBoundingClientRect().width})).observe(t)}#h(){const e=this.#o.value?.assignedNodes({flatten:!0});this.hasDescriptionSlot=Boolean(e&&e.length>0)}#c(){const e=this.#s.value?.assignedNodes({flatten:!0});this.hasSummarySlot=Boolean(e&&e.length>0)}#a(){const e=this.#r.value?.assignedNodes({flatten:!0});this.hasTooltipSlot=Boolean(e&&e.length>0)}};__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"disabled",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"error",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"hide",void 0),__decorate([property({reflect:!0})],GlideCoreLabel.prototype,"orientation",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"required",void 0),__decorate([property()],GlideCoreLabel.prototype,"split",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasDescriptionSlot",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasSummarySlot",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasTooltipSlot",void 0),__decorate([state()],GlideCoreLabel.prototype,"isLabelTooltip",void 0),__decorate([state()],GlideCoreLabel.prototype,"label",void 0),GlideCoreLabel=__decorate([customElement("glide-core-private-label")],GlideCoreLabel);export default GlideCoreLabel;
|
package/dist/label.styles.js
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
|
2
2
|
.component {
|
3
3
|
&.horizontal {
|
4
|
+
--column-gap: var(--glide-core-spacing-sm);
|
5
|
+
|
4
6
|
column-gap: var(--glide-core-spacing-sm);
|
5
7
|
display: grid;
|
6
|
-
|
7
|
-
/*
|
8
|
-
Since 1fr is actually minmax(auto, 1fr), this explicit minmax will make it so
|
9
|
-
the first column is sized to its content, and the second column fills the rest
|
10
|
-
of the space.
|
11
|
-
*/
|
12
|
-
grid-template-columns: auto minmax(0, 1fr);
|
8
|
+
grid-template-columns: auto minmax(min-content, 1fr);
|
13
9
|
}
|
14
10
|
|
15
11
|
&.vertical {
|
@@ -22,7 +18,9 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
|
|
22
18
|
}
|
23
19
|
|
24
20
|
&.middle {
|
25
|
-
grid-template-columns:
|
21
|
+
grid-template-columns: calc(50% - var(--column-gap) / 2) calc(
|
22
|
+
50% - var(--column-gap) / 2
|
23
|
+
);
|
26
24
|
}
|
27
25
|
|
28
26
|
&.hidden-label {
|
@@ -35,10 +33,20 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
|
|
35
33
|
align-items: center;
|
36
34
|
column-gap: var(--glide-core-spacing-xs);
|
37
35
|
display: flex;
|
38
|
-
justify-content: flex-end;
|
39
36
|
|
40
|
-
/*
|
41
|
-
|
37
|
+
/*
|
38
|
+
Allows for an ellipsis on the label. See the linked comment for why it's "3ch"
|
39
|
+
instead of "0".
|
40
|
+
|
41
|
+
- https://github.com/CrowdStrike/glide-core/pull/317#issuecomment-2297025365
|
42
|
+
- https://css-tricks.com/flexbox-truncated-text/#aa-the-solution-is-min-width-0-on-the-flex-child
|
43
|
+
*/
|
44
|
+
min-inline-size: 3ch;
|
45
|
+
|
46
|
+
&.middle,
|
47
|
+
&.left {
|
48
|
+
justify-content: flex-end;
|
49
|
+
}
|
42
50
|
|
43
51
|
&.hidden {
|
44
52
|
${visuallyHidden};
|
@@ -110,8 +118,12 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
|
|
110
118
|
}
|
111
119
|
}
|
112
120
|
|
113
|
-
.label-
|
114
|
-
|
121
|
+
.label-tooltip {
|
122
|
+
display: flex;
|
123
|
+
max-inline-size: 100%;
|
124
|
+
|
125
|
+
/* https://css-tricks.com/flexbox-truncated-text/#aa-the-solution-is-min-width-0-on-the-flex-child */
|
126
|
+
min-inline-size: 0;
|
115
127
|
}
|
116
128
|
|
117
129
|
.required-symbol {
|
@@ -5,13 +5,13 @@ import GlideCoreLabel from './label.js';
|
|
5
5
|
import sinon from 'sinon';
|
6
6
|
GlideCoreLabel.shadowRootOptions.mode = 'open';
|
7
7
|
it('registers', async () => {
|
8
|
-
expect(window.customElements.get('glide-core-label')).to.equal(GlideCoreLabel);
|
8
|
+
expect(window.customElements.get('glide-core-private-label')).to.equal(GlideCoreLabel);
|
9
9
|
});
|
10
10
|
it('has defaults', async () => {
|
11
|
-
const component = await fixture(html `<glide-core-label>
|
11
|
+
const component = await fixture(html `<glide-core-private-label>
|
12
12
|
<label for="input">Label</label>
|
13
13
|
<input id="input" slot="control" />
|
14
|
-
</glide-core-label>`);
|
14
|
+
</glide-core-private-label>`);
|
15
15
|
expect(component.getAttribute('error')).to.equal(null);
|
16
16
|
expect(component.error).to.equal(false);
|
17
17
|
expect(component.getAttribute('hide')).to.equal(null);
|
@@ -22,80 +22,80 @@ it('has defaults', async () => {
|
|
22
22
|
expect(component.required).to.be.false;
|
23
23
|
});
|
24
24
|
it('is accessible', async () => {
|
25
|
-
const component = await fixture(html `<glide-core-label>
|
25
|
+
const component = await fixture(html `<glide-core-private-label>
|
26
26
|
<label for="input">Label</label>
|
27
27
|
<input id="input" slot="control" />
|
28
28
|
<div slot="tooltip">Tooltip</div>
|
29
29
|
<div slot="description">Description</div>
|
30
|
-
</glide-core-label>`);
|
30
|
+
</glide-core-private-label>`);
|
31
31
|
await expect(component).to.be.accessible();
|
32
32
|
});
|
33
33
|
it('can have a label', async () => {
|
34
|
-
const component = await fixture(html `<glide-core-label>
|
34
|
+
const component = await fixture(html `<glide-core-private-label>
|
35
35
|
<label for="input">Label</label>
|
36
36
|
<input id="input" slot="control" />
|
37
|
-
</glide-core-label>`);
|
37
|
+
</glide-core-private-label>`);
|
38
38
|
const assignedElements = component.shadowRoot
|
39
39
|
?.querySelector('slot:not([name])')
|
40
40
|
?.assignedElements();
|
41
41
|
expect(assignedElements?.at(0)?.textContent).to.equal('Label');
|
42
42
|
});
|
43
43
|
it('can have a description', async () => {
|
44
|
-
const component = await fixture(html `<glide-core-label>
|
44
|
+
const component = await fixture(html `<glide-core-private-label>
|
45
45
|
<label for="input">Label</label>
|
46
46
|
<input id="input" slot="control" />
|
47
47
|
<div slot="description">Description</div>
|
48
|
-
</glide-core-label>`);
|
48
|
+
</glide-core-private-label>`);
|
49
49
|
const assignedElements = component.shadowRoot
|
50
50
|
?.querySelector('slot[name="description"]')
|
51
51
|
?.assignedElements();
|
52
52
|
expect(assignedElements?.at(0)?.textContent).to.equal('Description');
|
53
53
|
});
|
54
54
|
it('can have a tooltip', async () => {
|
55
|
-
const component = await fixture(html `<glide-core-label>
|
55
|
+
const component = await fixture(html `<glide-core-private-label>
|
56
56
|
<label for="input">Label</label>
|
57
57
|
<input id="input" slot="control" />
|
58
58
|
<div slot="tooltip">Tooltip</div>
|
59
|
-
</glide-core-label>`);
|
59
|
+
</glide-core-private-label>`);
|
60
60
|
const assignedElements = component.shadowRoot
|
61
61
|
?.querySelector('slot[name="tooltip"]')
|
62
62
|
?.assignedElements();
|
63
63
|
expect(assignedElements?.at(0)?.textContent).to.equal('Tooltip');
|
64
64
|
});
|
65
65
|
it('can be required', async () => {
|
66
|
-
const component = await fixture(html `<glide-core-label required>
|
66
|
+
const component = await fixture(html `<glide-core-private-label required>
|
67
67
|
<label for="input">Label</label>
|
68
68
|
<input id="input" slot="control" />
|
69
|
-
</glide-core-label>`);
|
69
|
+
</glide-core-private-label>`);
|
70
70
|
expect(component.hasAttribute('required')).to.be.true;
|
71
71
|
expect(component.required).to.equal(true);
|
72
72
|
const label = component.shadowRoot?.querySelector('[data-test="label"]');
|
73
73
|
expect(label?.textContent?.includes('*')).to.be.true;
|
74
74
|
});
|
75
75
|
it('can have an `error`', async () => {
|
76
|
-
const component = await fixture(html `<glide-core-label ?error=${true}>
|
76
|
+
const component = await fixture(html `<glide-core-private-label ?error=${true}>
|
77
77
|
<label for="input">Label</label>
|
78
78
|
<input id="input" slot="control" />
|
79
|
-
</glide-core-label>`);
|
79
|
+
</glide-core-private-label>`);
|
80
80
|
expect(component.hasAttribute('error')).to.be.true;
|
81
81
|
expect(component.error).to.equal(true);
|
82
82
|
});
|
83
83
|
it('places the tooltip on the bottom when horizontal', async () => {
|
84
|
-
const component = await fixture(html `<glide-core-label>
|
84
|
+
const component = await fixture(html `<glide-core-private-label>
|
85
85
|
<label for="input">Label</label>
|
86
86
|
<input id="input" slot="control" />
|
87
87
|
<div slot="tooltip">Tooltip</div>
|
88
|
-
</glide-core-label>`);
|
88
|
+
</glide-core-private-label>`);
|
89
89
|
expect(component.shadowRoot
|
90
90
|
?.querySelector('glide-core-tooltip')
|
91
91
|
?.getAttribute('placement')).to.equal('bottom');
|
92
92
|
});
|
93
93
|
it('places the tooltip on the right when vertical', async () => {
|
94
|
-
const component = await fixture(html `<glide-core-label orientation="vertical">
|
94
|
+
const component = await fixture(html `<glide-core-private-label orientation="vertical">
|
95
95
|
<label for="input">Label</label>
|
96
96
|
<input id="input" slot="control" />
|
97
97
|
<div slot="tooltip">Tooltip</div>
|
98
|
-
</glide-core-label>`);
|
98
|
+
</glide-core-private-label>`);
|
99
99
|
expect(component.shadowRoot
|
100
100
|
?.querySelector('glide-core-tooltip')
|
101
101
|
?.getAttribute('placement')).to.equal('right');
|
@@ -103,29 +103,31 @@ it('places the tooltip on the right when vertical', async () => {
|
|
103
103
|
it('throws if it does not have a default slot', async () => {
|
104
104
|
const spy = sinon.spy();
|
105
105
|
try {
|
106
|
-
await fixture(html `<glide-core-
|
106
|
+
await fixture(html `<glide-core-private-label
|
107
|
+
><input slot="control"
|
108
|
+
/></glide-core-private-label>`);
|
107
109
|
}
|
108
110
|
catch (error) {
|
109
111
|
if (error instanceof ArgumentError) {
|
110
112
|
spy();
|
111
113
|
}
|
112
114
|
}
|
113
|
-
expect(spy.
|
115
|
+
expect(spy.callCount).to.equal(1);
|
114
116
|
});
|
115
117
|
it('throws if it does not have a "control" slot', async () => {
|
116
118
|
const spy = sinon.spy();
|
117
119
|
const stub = sinon.stub(console, 'error');
|
118
120
|
try {
|
119
|
-
await fixture(html `<glide-core-label>
|
121
|
+
await fixture(html `<glide-core-private-label>
|
120
122
|
<label>Label</label>
|
121
|
-
</glide-core-label>`);
|
123
|
+
</glide-core-private-label>`);
|
122
124
|
}
|
123
125
|
catch (error) {
|
124
126
|
if (error instanceof ArgumentError) {
|
125
127
|
spy();
|
126
128
|
}
|
127
129
|
}
|
128
|
-
expect(spy.
|
130
|
+
expect(spy.callCount).to.equal(1);
|
129
131
|
// It's not clear to me why the error logged by Ow shows up in the console
|
130
132
|
// here and not in the above test or elsewhere. A bug in Web Test Runner?
|
131
133
|
// Something I don't understand about Lit's lifecycle?
|
@@ -1 +1 @@
|
|
1
|
-
import{ArgumentError}from"ow";import{expect}from"@open-wc/testing";import sinon from"sinon";export default async function(o){const
|
1
|
+
import{ArgumentError}from"ow";import{expect}from"@open-wc/testing";import sinon from"sinon";export default async function(o){const n=window.onerror;window.onerror=null;const r=sinon.spy();try{await o.call(context)}catch(o){o instanceof ArgumentError&&r()}expect(r.callCount).to.equal(1),window.onerror=n}
|
@@ -10,10 +10,13 @@ export interface Translation extends DefaultTranslation {
|
|
10
10
|
dismiss: string;
|
11
11
|
open: string;
|
12
12
|
selectAll: string;
|
13
|
-
clearEntry: string;
|
14
13
|
moreInformation: string;
|
15
14
|
notifications: string;
|
16
15
|
nextTab: string;
|
17
16
|
previousTab: string;
|
17
|
+
announcedCharacterCount: (current: number, maximum: number) => string;
|
18
|
+
displayedCharacterCount: (current: number, maximum: number) => string;
|
19
|
+
clearEntry: (label: string) => string;
|
18
20
|
removeTag: (name: string) => string;
|
21
|
+
actionsFor: (label: string) => string;
|
19
22
|
}
|