@crowdstrike/glide-core 0.9.0 → 0.9.2
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/accordion.styles.js +2 -4
- package/dist/button-group.button.d.ts +1 -4
- package/dist/button-group.button.styles.js +4 -8
- package/dist/button-group.d.ts +3 -0
- package/dist/button-group.styles.js +2 -2
- package/dist/button.d.ts +4 -0
- package/dist/button.js +1 -1
- package/dist/button.styles.js +2 -4
- package/dist/button.test.events.js +86 -10
- package/dist/checkbox-group.d.ts +6 -2
- package/dist/checkbox-group.stories.d.ts +1 -1
- package/dist/checkbox.d.ts +5 -4
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.stories.d.ts +1 -1
- package/dist/checkbox.styles.js +43 -6
- package/dist/checkbox.test.basics.js +15 -6
- package/dist/checkbox.test.events.js +12 -4
- package/dist/checkbox.test.focus.js +1 -1
- package/dist/checkbox.test.form.js +17 -0
- package/dist/checkbox.test.interactions.js +52 -7
- 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 +7 -4
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.styles.js +1 -0
- package/dist/dropdown.styles.js +47 -26
- package/dist/dropdown.test.focus.filterable.js +20 -0
- package/dist/dropdown.test.focus.js +1 -0
- package/dist/dropdown.test.form.js +23 -112
- package/dist/dropdown.test.interactions.filterable.js +121 -17
- package/dist/dropdown.test.interactions.multiple.js +15 -22
- package/dist/dropdown.test.interactions.single.js +44 -22
- package/dist/icon-button.d.ts +2 -0
- package/dist/icon-button.styles.js +2 -4
- package/dist/icons/checked.d.ts +5 -0
- package/dist/icons/checked.js +1 -1
- package/dist/input.d.ts +5 -4
- package/dist/input.js +1 -1
- package/dist/input.stories.d.ts +0 -4
- package/dist/input.styles.d.ts +1 -1
- package/dist/input.styles.js +93 -93
- package/dist/input.test.basics.js +45 -45
- package/dist/input.test.form.js +17 -0
- package/dist/label.styles.js +11 -13
- package/dist/library/localize.d.ts +1 -0
- package/dist/library/localize.test.js +45 -0
- package/dist/menu.button.styles.js +1 -0
- package/dist/menu.js +1 -1
- package/dist/menu.link.styles.js +1 -0
- package/dist/menu.styles.js +3 -1
- package/dist/menu.test.events.js +101 -7
- package/dist/menu.test.focus.js +26 -3
- package/dist/menu.test.interactions.js +5 -2
- package/dist/modal.d.ts +0 -7
- package/dist/modal.icon-button.test.basics.js +9 -9
- package/dist/modal.stories.d.ts +1 -0
- package/dist/modal.styles.js +2 -4
- package/dist/modal.tertiary-icon.test.basics.js +15 -15
- package/dist/modal.test.accessibility.js +16 -27
- package/dist/modal.test.basics.js +64 -68
- package/dist/modal.test.close.js +12 -16
- package/dist/modal.test.events.js +32 -44
- package/dist/modal.test.lock-scroll.js +15 -25
- package/dist/modal.test.methods.js +8 -12
- package/dist/modal.test.scrollbars.js +2 -4
- 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.test.basics.js +3 -3
- package/dist/radio-group.test.events.js +6 -6
- package/dist/radio-group.test.form.js +19 -0
- package/dist/radio.d.ts +1 -2
- package/dist/radio.js +1 -1
- package/dist/radio.styles.js +2 -6
- package/dist/split-button.styles.js +2 -4
- package/dist/split-container.d.ts +1 -1
- package/dist/split-container.styles.js +2 -4
- package/dist/status-indicator.d.ts +1 -1
- package/dist/styles/focus-outline.d.ts +1 -1
- package/dist/styles/focus-outline.js +7 -1
- package/dist/styles/menu-opening-animation.d.ts +2 -0
- package/dist/styles/menu-opening-animation.js +26 -0
- package/dist/styles/variables.css +1 -1
- package/dist/styles/visually-hidden.d.ts +1 -1
- package/dist/styles/visually-hidden.js +14 -1
- package/dist/tab.group.d.ts +6 -6
- package/dist/tab.group.js +1 -1
- package/dist/tab.group.styles.js +46 -5
- package/dist/tab.group.test.basics.js +9 -2
- package/dist/tab.group.test.interactions.js +70 -93
- package/dist/tab.js +1 -1
- package/dist/tab.panel.styles.js +3 -9
- package/dist/tab.styles.js +6 -13
- package/dist/tab.test.basics.js +15 -17
- package/dist/tabs.stories.d.ts +1 -0
- package/dist/tag.d.ts +3 -6
- package/dist/tag.js +1 -1
- package/dist/tag.styles.js +2 -4
- package/dist/tag.test.basics.js +28 -27
- package/dist/tag.test.events.js +3 -3
- package/dist/tag.test.focus.js +4 -4
- package/dist/textarea.d.ts +5 -4
- package/dist/textarea.stories.d.ts +0 -4
- package/dist/textarea.styles.d.ts +1 -1
- package/dist/textarea.styles.js +63 -67
- package/dist/textarea.test.basics.js +52 -52
- package/dist/toasts.d.ts +5 -0
- package/dist/toasts.styles.js +1 -1
- package/dist/toggle.d.ts +3 -3
- package/dist/toggle.js +1 -1
- package/dist/toggle.stories.d.ts +1 -1
- package/dist/toggle.styles.js +2 -1
- package/dist/toggle.test.interactions.js +37 -0
- package/dist/tooltip.d.ts +2 -2
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +22 -18
- package/dist/tooltip.test.interactions.js +6 -6
- package/dist/translations/en.js +1 -1
- package/dist/translations/fr.d.ts +3 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/ja.d.ts +3 -1
- package/dist/translations/ja.js +1 -1
- package/dist/tree.d.ts +1 -1
- package/dist/tree.item.d.ts +0 -3
- 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 -0
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.menu.test.basics.js +15 -0
- package/dist/tree.item.styles.js +13 -3
- package/dist/tree.item.test.basics.d.ts +2 -1
- package/dist/tree.item.test.basics.js +16 -4
- package/dist/tree.js +1 -1
- package/dist/tree.test.focus.js +91 -4
- package/package.json +2 -1
- package/dist/button.test.form.d.ts +0 -1
- package/dist/button.test.form.js +0 -50
- package/dist/input.test.translations.js +0 -38
- package/dist/tag.test.translations.d.ts +0 -1
- package/dist/tag.test.translations.js +0 -25
- package/dist/textarea.test.translations.d.ts +0 -1
- package/dist/textarea.test.translations.js +0 -34
- /package/dist/{input.test.translations.d.ts → library/localize.test.d.ts} +0 -0
@@ -3,10 +3,6 @@ declare const meta: Meta;
|
|
3
3
|
export default meta;
|
4
4
|
export declare const Default: StoryObj;
|
5
5
|
export declare const WithError: StoryObj;
|
6
|
-
export declare const Description: StoryObj;
|
7
|
-
export declare const Readonly: StoryObj;
|
8
|
-
export declare const Disabled: StoryObj;
|
9
|
-
export declare const Placeholder: StoryObj;
|
10
6
|
export declare const MaxLength: StoryObj;
|
11
7
|
export declare const MaxLengthAndDescription: StoryObj;
|
12
8
|
export declare const Tooltip: StoryObj;
|
@@ -1,2 +1,2 @@
|
|
1
|
-
declare const _default: import("lit").CSSResult;
|
1
|
+
declare const _default: import("lit").CSSResult[];
|
2
2
|
export default _default;
|
package/dist/textarea.styles.js
CHANGED
@@ -1,81 +1,77 @@
|
|
1
|
-
import{css,unsafeCSS}from"lit";import visuallyHidden from"./styles/visually-hidden.js";const fieldSizingContent=unsafeCSS("\n field-sizing: content;\n");export default
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
display: flex;
|
9
|
-
}
|
1
|
+
import{css,unsafeCSS}from"lit";import visuallyHidden from"./styles/visually-hidden.js";const fieldSizingContent=unsafeCSS("\n field-sizing: content;\n");export default[css`
|
2
|
+
${visuallyHidden(".character-count .hidden")}
|
3
|
+
`,css`
|
4
|
+
glide-core-private-label::part(tooltips-and-label) {
|
5
|
+
align-items: flex-start;
|
6
|
+
margin-block-start: var(--glide-core-spacing-sm);
|
7
|
+
}
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
.textarea-container {
|
10
|
+
display: flex;
|
11
|
+
}
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
border: 1px solid var(--glide-core-border-base-light);
|
19
|
-
border-radius: 0.5rem;
|
20
|
-
color: var(--glide-core-text-body-1);
|
21
|
-
cursor: inherit;
|
22
|
-
display: block;
|
23
|
-
flex-grow: 1;
|
24
|
-
font-family: var(--glide-core-body-xs-font-family);
|
25
|
-
font-size: var(--glide-core-body-sm-font-size);
|
26
|
-
font-weight: var(--glide-core-body-xs-font-weight);
|
27
|
-
max-block-size: 5lh;
|
28
|
-
min-block-size: 3lh;
|
29
|
-
padding: var(--glide-core-spacing-xs) var(--glide-core-spacing-sm);
|
30
|
-
resize: vertical;
|
31
|
-
transition: border-color 200ms ease-in-out;
|
13
|
+
.description {
|
14
|
+
display: block;
|
15
|
+
}
|
32
16
|
|
33
|
-
|
17
|
+
textarea {
|
18
|
+
appearance: none;
|
19
|
+
background-color: var(--glide-core-surface-base-lighter);
|
20
|
+
border: 1px solid var(--glide-core-border-base);
|
21
|
+
border-radius: 0.5rem;
|
22
|
+
color: var(--glide-core-text-body-1);
|
23
|
+
cursor: inherit;
|
24
|
+
display: block;
|
25
|
+
flex-grow: 1;
|
26
|
+
font-family: var(--glide-core-body-xs-font-family);
|
27
|
+
font-size: var(--glide-core-body-sm-font-size);
|
28
|
+
font-weight: var(--glide-core-body-xs-font-weight);
|
29
|
+
max-block-size: 5lh;
|
30
|
+
min-block-size: 3lh;
|
31
|
+
padding: var(--glide-core-spacing-xs) var(--glide-core-spacing-sm);
|
32
|
+
resize: vertical;
|
33
|
+
transition: border-color 200ms ease-in-out;
|
34
34
|
|
35
|
-
|
36
|
-
border-color: var(--glide-core-border-base);
|
37
|
-
}
|
35
|
+
${fieldSizingContent};
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
&:focus {
|
38
|
+
outline: none;
|
39
|
+
}
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
&:focus-visible,
|
42
|
+
&:focus-visible[readonly],
|
43
|
+
&:hover {
|
44
|
+
border-color: var(--glide-core-border-focus);
|
45
|
+
}
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
&.error {
|
48
|
+
border-color: var(--glide-core-status-error);
|
49
|
+
}
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
&[readonly] {
|
52
|
+
border-color: transparent;
|
53
|
+
outline: none;
|
54
|
+
resize: none;
|
55
|
+
transition: none;
|
56
|
+
}
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
&[disabled] {
|
59
|
+
background-color: var(--glide-core-surface-disabled);
|
60
|
+
border: 0.0625rem solid var(--glide-core-border-base-light);
|
61
|
+
color: var(--glide-core-text-tertiary-disabled);
|
62
|
+
}
|
62
63
|
}
|
63
|
-
}
|
64
|
-
|
65
|
-
.meta {
|
66
|
-
column-gap: var(--glide-core-spacing-xs);
|
67
|
-
display: flex;
|
68
|
-
font-size: var(--glide-core-body-xs-font-size);
|
69
|
-
justify-content: space-between;
|
70
|
-
}
|
71
64
|
|
72
|
-
|
73
|
-
|
74
|
-
|
65
|
+
.meta {
|
66
|
+
column-gap: var(--glide-core-spacing-xs);
|
67
|
+
display: flex;
|
68
|
+
font-size: var(--glide-core-body-xs-font-size);
|
69
|
+
justify-content: space-between;
|
75
70
|
}
|
76
71
|
|
77
|
-
.
|
78
|
-
|
72
|
+
.character-count {
|
73
|
+
&.error {
|
74
|
+
font-weight: var(--glide-core-font-weight-bold);
|
75
|
+
}
|
79
76
|
}
|
80
|
-
|
81
|
-
`;
|
77
|
+
`];
|
@@ -7,171 +7,171 @@ it('registers', async () => {
|
|
7
7
|
expect(window.customElements.get('glide-core-textarea')).to.equal(GlideCoreTextarea);
|
8
8
|
});
|
9
9
|
it('is accessible', async () => {
|
10
|
-
const
|
10
|
+
const component = await fixture(html `<glide-core-textarea
|
11
11
|
value="value"
|
12
12
|
label="label"
|
13
13
|
></glide-core-textarea>`);
|
14
|
-
await expect(
|
14
|
+
await expect(component).to.be.accessible();
|
15
15
|
});
|
16
16
|
it('renders a textarea with two rows and value when attribute `value` is set ', async () => {
|
17
|
-
const
|
17
|
+
const component = await fixture(html `<glide-core-textarea
|
18
18
|
value="value"
|
19
19
|
label="label"
|
20
20
|
></glide-core-textarea>`);
|
21
|
-
const textarea =
|
22
|
-
expect(
|
23
|
-
expect(
|
21
|
+
const textarea = component.shadowRoot.querySelector('textarea');
|
22
|
+
expect(component);
|
23
|
+
expect(component).to.have.attribute('rows', '2');
|
24
24
|
expect(textarea).to.exist;
|
25
25
|
expect(textarea).to.have.attribute('rows', '2');
|
26
26
|
});
|
27
27
|
it('renders the `rows` attribute on the textarea when set', async () => {
|
28
|
-
const
|
28
|
+
const component = await fixture(html `<glide-core-textarea
|
29
29
|
value="value"
|
30
30
|
label="label"
|
31
31
|
rows="5"
|
32
32
|
></glide-core-textarea>`);
|
33
|
-
const textarea =
|
33
|
+
const textarea = component.shadowRoot.querySelector('textarea');
|
34
34
|
expect(textarea).to.have.attribute('rows', '5');
|
35
35
|
});
|
36
36
|
it('renders a label when attribute `label` is set', async () => {
|
37
|
-
const
|
37
|
+
const component = await fixture(html `<glide-core-textarea
|
38
38
|
value="value"
|
39
39
|
label="label"
|
40
40
|
></glide-core-textarea>`);
|
41
|
-
const label =
|
41
|
+
const label = component.shadowRoot.querySelector('label');
|
42
42
|
expect(label).to.exist;
|
43
43
|
expect(label?.textContent?.trim()).to.be.equal('label');
|
44
44
|
});
|
45
45
|
it('renders the textarea as readonly when attribute `readonly` is set', async () => {
|
46
|
-
const
|
46
|
+
const component = await fixture(html `<glide-core-textarea
|
47
47
|
value="value"
|
48
48
|
label="label"
|
49
49
|
readonly
|
50
50
|
></glide-core-textarea>`);
|
51
|
-
const textarea =
|
51
|
+
const textarea = component.shadowRoot.querySelector('textarea');
|
52
52
|
expect(textarea).to.have.attribute('readonly');
|
53
53
|
});
|
54
54
|
it('renders the textarea as disabled when attribute `disabled` is set', async () => {
|
55
|
-
const
|
55
|
+
const component = await fixture(html `<glide-core-textarea
|
56
56
|
value="value"
|
57
57
|
label="label"
|
58
58
|
disabled
|
59
59
|
></glide-core-textarea>`);
|
60
|
-
const textarea =
|
60
|
+
const textarea = component.shadowRoot.querySelector('textarea');
|
61
61
|
expect(textarea).to.have.attribute('disabled');
|
62
62
|
});
|
63
63
|
it('renders the textarea with a placeholder when attribute `placeholder` is set', async () => {
|
64
|
-
const
|
64
|
+
const component = await fixture(html `<glide-core-textarea
|
65
65
|
value=""
|
66
66
|
label="label"
|
67
67
|
placeholder="placeholder"
|
68
68
|
></glide-core-textarea>`);
|
69
|
-
const textarea =
|
69
|
+
const textarea = component.shadowRoot.querySelector('textarea');
|
70
70
|
expect(textarea).to.have.attribute('placeholder', 'placeholder');
|
71
71
|
});
|
72
72
|
it('renders `required` on textarea when set', async () => {
|
73
|
-
const
|
73
|
+
const component = await fixture(html `<glide-core-textarea
|
74
74
|
value="value"
|
75
75
|
label="label"
|
76
76
|
required
|
77
77
|
></glide-core-textarea>`);
|
78
|
-
const textarea =
|
78
|
+
const textarea = component.shadowRoot.querySelector('textarea');
|
79
79
|
expect(textarea).to.have.attribute('required');
|
80
80
|
});
|
81
81
|
it('renders a `name` attribute on the textarea when set', async () => {
|
82
|
-
const
|
82
|
+
const component = await fixture(html `<glide-core-textarea
|
83
83
|
value="value"
|
84
84
|
label="label"
|
85
85
|
name="test-name"
|
86
86
|
></glide-core-textarea>`);
|
87
|
-
const textarea =
|
87
|
+
const textarea = component.shadowRoot.querySelector('textarea');
|
88
88
|
expect(textarea).to.have.attribute('name', 'test-name');
|
89
89
|
});
|
90
90
|
it('supports a "tooltip" slot', async () => {
|
91
|
-
const
|
91
|
+
const component = await fixture(html `
|
92
92
|
<glide-core-textarea value="value" label="label" required>
|
93
93
|
<div slot="tooltip">Tooltip</div>
|
94
94
|
</glide-core-textarea>
|
95
95
|
`);
|
96
|
-
const assignedElements =
|
96
|
+
const assignedElements = component.shadowRoot
|
97
97
|
?.querySelector('slot[name="tooltip"]')
|
98
98
|
?.assignedElements();
|
99
99
|
expect(assignedElements?.at(0)?.textContent).to.equal('Tooltip');
|
100
100
|
});
|
101
101
|
it('renders a slot with description', async () => {
|
102
|
-
const
|
102
|
+
const component = await fixture(html `<glide-core-textarea value="value" label="label"
|
103
103
|
><span slot="description" data-test-content
|
104
104
|
>Description</span
|
105
105
|
></glide-core-textarea
|
106
106
|
>`);
|
107
|
-
expect(
|
108
|
-
const contentRendered =
|
107
|
+
expect(component).to.exist;
|
108
|
+
const contentRendered = component.querySelector('[data-test-content]');
|
109
109
|
expect(contentRendered).to.exist;
|
110
110
|
expect(contentRendered?.textContent).to.be.equal('Description');
|
111
111
|
});
|
112
112
|
it('displays visually hidden character count text for screenreaders', async () => {
|
113
|
-
const
|
113
|
+
const component = await fixture(html `<glide-core-textarea
|
114
114
|
label="label"
|
115
115
|
maxlength="10"
|
116
116
|
></glide-core-textarea>`);
|
117
|
-
const maxCharacterCountAnnouncement =
|
117
|
+
const maxCharacterCountAnnouncement = component.shadowRoot?.querySelector('[data-test="character-count-announcement"]');
|
118
118
|
expect(maxCharacterCountAnnouncement?.textContent?.trim()).to.equal('Character count 0 of 10');
|
119
119
|
});
|
120
120
|
it('renders a character count when attribute `maxlength` is set greater than zero', async () => {
|
121
|
-
const
|
121
|
+
const component = await fixture(html `<glide-core-textarea value="value" label="label" maxlength="10"
|
122
122
|
><span slot="description">Description</span></glide-core-textarea
|
123
123
|
>`);
|
124
|
-
const container =
|
124
|
+
const container = component.shadowRoot.querySelector('[data-test="character-count-text"]');
|
125
125
|
expect(container?.textContent?.trim()).to.be.equal('5/10');
|
126
126
|
});
|
127
127
|
it('does not render a character count when attribute `maxlength` is set less than than zero', async () => {
|
128
|
-
const
|
128
|
+
const component = await fixture(html `<glide-core-textarea value="value" label="label" maxlength="0"
|
129
129
|
><span slot="description">Description</span></glide-core-textarea
|
130
130
|
>`);
|
131
|
-
const container =
|
131
|
+
const container = component.shadowRoot?.querySelector('[data-test="character-count-container"]');
|
132
132
|
expect(container).to.be.null;
|
133
133
|
});
|
134
134
|
it('focuses the textarea when the label is clicked', async () => {
|
135
|
-
const
|
135
|
+
const component = await fixture(html `<glide-core-textarea
|
136
136
|
value="value"
|
137
137
|
label="label"
|
138
138
|
></glide-core-textarea>`);
|
139
|
-
const label =
|
139
|
+
const label = component.shadowRoot.querySelector('label');
|
140
140
|
label?.click();
|
141
|
-
expect(
|
142
|
-
await expect(
|
141
|
+
expect(component).to.have.focus;
|
142
|
+
await expect(component.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.be.equal('textarea');
|
143
143
|
});
|
144
144
|
it('has tabbable textarea', async () => {
|
145
|
-
const
|
145
|
+
const component = await fixture(html `<glide-core-textarea
|
146
146
|
value="value"
|
147
147
|
label="label"
|
148
148
|
></glide-core-textarea>`);
|
149
149
|
await sendKeys({ press: 'Tab' });
|
150
|
-
expect(
|
151
|
-
await expect(
|
150
|
+
expect(component).to.have.focus;
|
151
|
+
await expect(component.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.be.equal('textarea');
|
152
152
|
});
|
153
153
|
it('renders text when typed into text area', async () => {
|
154
|
-
const
|
155
|
-
const textarea =
|
156
|
-
|
154
|
+
const component = await fixture(html `<glide-core-textarea value="" label="label"></glide-core-textarea>`);
|
155
|
+
const textarea = component.shadowRoot.querySelector('textarea');
|
156
|
+
component.focus();
|
157
157
|
await sendKeys({ type: 'test text' });
|
158
158
|
expect(textarea?.value).to.equal('test text');
|
159
159
|
});
|
160
160
|
it('returns the content of the textarea when getting the `value` property', async () => {
|
161
|
-
const
|
162
|
-
|
161
|
+
const component = await fixture(html `<glide-core-textarea value="" label="label"></glide-core-textarea>`);
|
162
|
+
component.focus();
|
163
163
|
await sendKeys({ type: 'test text' });
|
164
|
-
expect(
|
164
|
+
expect(component.value).to.equal('test text');
|
165
165
|
});
|
166
166
|
it('focuses the textarea when `focus()` is called', async () => {
|
167
|
-
const
|
168
|
-
|
169
|
-
await expect(
|
167
|
+
const component = await fixture(html `<glide-core-textarea value="" label="label"></glide-core-textarea>`);
|
168
|
+
component.focus();
|
169
|
+
await expect(component.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.be.equal('textarea');
|
170
170
|
});
|
171
171
|
it('blurs the textarea when `blur` is called', async () => {
|
172
|
-
const
|
173
|
-
|
174
|
-
await expect(
|
175
|
-
|
176
|
-
await expect(
|
172
|
+
const component = await fixture(html `<glide-core-textarea value="" label="label"></glide-core-textarea>`);
|
173
|
+
component.focus();
|
174
|
+
await expect(component.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.be.equal('textarea');
|
175
|
+
component.blur();
|
176
|
+
await expect(component.shadowRoot?.activeElement?.tagName.toLocaleLowerCase()).to.not.equal('textarea');
|
177
177
|
});
|
package/dist/toasts.d.ts
CHANGED
@@ -19,6 +19,11 @@ export default class GlideCoreToasts extends LitElement {
|
|
19
19
|
#private;
|
20
20
|
static shadowRootOptions: ShadowRootInit;
|
21
21
|
static styles: import("lit").CSSResult[];
|
22
|
+
/**
|
23
|
+
* @param {number} [toast.duration=5000]
|
24
|
+
* Optional: Number of milliseconds before the Toast auto-hides.
|
25
|
+
* Minimum: `5000`. Default: `5000`. For a Toast that never auto-hides, set to `Infinity`
|
26
|
+
* */
|
22
27
|
add(toast: Toast): import("./toasts.toast.js").default & {
|
23
28
|
variant: "success" | "informational";
|
24
29
|
label: string;
|
package/dist/toasts.styles.js
CHANGED
package/dist/toggle.d.ts
CHANGED
@@ -8,9 +8,9 @@ declare global {
|
|
8
8
|
/**
|
9
9
|
* @description A toggle with a label and optional tooltip, summary, and description.
|
10
10
|
*
|
11
|
-
* @event change -
|
12
|
-
* @event input -
|
13
|
-
|
11
|
+
* @event change - `(event: Event) => void`
|
12
|
+
* @event input - `(event: Event) => void`
|
13
|
+
*
|
14
14
|
* @slot description - Additional information or context.
|
15
15
|
* @slot tooltip - Content for the tooltip.
|
16
16
|
*/
|
package/dist/toggle.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,t,o,i){var r,l=arguments.length,s=l<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,i);else for(var d=e.length-1;d>=0;d--)(r=e[d])&&(s=(l<3?r(s):l>3?r(t,o,s):r(t,o))||s);return l>3&&s&&Object.defineProperty(t,o,s),s};import"./label.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import styles from"./toggle.styles.js";let GlideCoreToggle=class GlideCoreToggle extends LitElement{constructor(){super(...arguments),this.checked=!1,this.disabled=!1,this.hideLabel=!1,this.orientation="horizontal",this.#e=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}click(){this.#e.value?.click()}focus(e){this.#e.value?.focus(e)}render(){return html`<div data-test="component"><glide-core-private-label orientation="${this.orientation}" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?hide="${this.hideLabel}"><slot name="tooltip" slot="tooltip"></slot><label for="input">${this.label}</label><div class="toggle-and-input" slot="control"><input aria-checked="${this.checked}" aria-describedby="summary description" data-test="input" id="input" role="switch" type="checkbox"
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,i){var r,l=arguments.length,s=l<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,i);else for(var d=e.length-1;d>=0;d--)(r=e[d])&&(s=(l<3?r(s):l>3?r(t,o,s):r(t,o))||s);return l>3&&s&&Object.defineProperty(t,o,s),s};import"./label.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import styles from"./toggle.styles.js";let GlideCoreToggle=class GlideCoreToggle extends LitElement{constructor(){super(...arguments),this.checked=!1,this.disabled=!1,this.hideLabel=!1,this.orientation="horizontal",this.#e=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}click(){this.#e.value?.click()}focus(e){this.#e.value?.focus(e)}render(){return html`<div data-test="component"><glide-core-private-label orientation="${this.orientation}" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?hide="${this.hideLabel}"><slot name="tooltip" slot="tooltip"></slot><label for="input">${this.label}</label><div class="toggle-and-input" slot="control"><input aria-checked="${this.checked}" aria-describedby="summary description" data-test="input" id="input" role="switch" type="checkbox" .checked="${this.checked}" ?disabled="${this.disabled}" @change="${this.#t}" @input="${this.#t}" ${ref(this.#e)}></div><div slot="summary" id="summary">${this.summary}</div><slot class="description" id="description" name="description" slot="description"></slot></glide-core-private-label></div>`}#e;#t(e){e.target instanceof HTMLInputElement&&(this.checked=e.target.checked),"change"===e.type&&this.dispatchEvent(new Event(e.type,e))}};__decorate([property({type:Boolean})],GlideCoreToggle.prototype,"checked",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreToggle.prototype,"disabled",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreToggle.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreToggle.prototype,"label",void 0),__decorate([property({reflect:!0})],GlideCoreToggle.prototype,"orientation",void 0),__decorate([property({reflect:!0})],GlideCoreToggle.prototype,"name",void 0),__decorate([property()],GlideCoreToggle.prototype,"privateSplit",void 0),__decorate([property({reflect:!0})],GlideCoreToggle.prototype,"summary",void 0),GlideCoreToggle=__decorate([customElement("glide-core-toggle")],GlideCoreToggle);export default GlideCoreToggle;
|
package/dist/toggle.stories.d.ts
CHANGED
package/dist/toggle.styles.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
|
2
|
+
${focusOutline(".toggle-and-input:has(input:focus-visible)")}
|
3
|
+
`,css`
|
2
4
|
/*
|
3
5
|
Most states are handled on the host. But ":checked" is handled on the input
|
4
6
|
because browsers don't support that class on the host. And using attribute
|
@@ -30,7 +32,6 @@ Use the ":checked" pseudo class on the host and throughout when browsers support
|
|
30
32
|
position: relative;
|
31
33
|
|
32
34
|
&:has(input:focus-visible) {
|
33
|
-
${focusOutline};
|
34
35
|
outline-offset: 4px;
|
35
36
|
}
|
36
37
|
|
@@ -42,3 +42,40 @@ it('is still unchecked after being clicked when unchecked and disabled', async (
|
|
42
42
|
const input = component.shadowRoot?.querySelector('[data-test="input"]');
|
43
43
|
expect(input?.getAttribute('aria-checked')).to.equal('false');
|
44
44
|
});
|
45
|
+
it('is unchecked after being clicked then forcibly unchecked via a "change" listener', async () => {
|
46
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
47
|
+
component.addEventListener('change', async () => {
|
48
|
+
await component.updateComplete;
|
49
|
+
component.checked = false;
|
50
|
+
});
|
51
|
+
component.click();
|
52
|
+
await elementUpdated(component);
|
53
|
+
expect(component.hasAttribute('checked')).to.be.false;
|
54
|
+
expect(component.checked).to.equal(false);
|
55
|
+
const input = component.shadowRoot?.querySelector('[data-test="input"]');
|
56
|
+
expect(input?.getAttribute('aria-checked')).to.equal('false');
|
57
|
+
});
|
58
|
+
it('is unchecked after being clicked then forcibly unchecked via an "input" listener', async () => {
|
59
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
60
|
+
component.addEventListener('input', async () => {
|
61
|
+
await component.updateComplete;
|
62
|
+
component.checked = false;
|
63
|
+
});
|
64
|
+
component.click();
|
65
|
+
await elementUpdated(component);
|
66
|
+
expect(component.hasAttribute('checked')).to.be.false;
|
67
|
+
expect(component.checked).to.equal(false);
|
68
|
+
const input = component.shadowRoot?.querySelector('[data-test="input"]');
|
69
|
+
expect(input?.getAttribute('aria-checked')).to.equal('false');
|
70
|
+
});
|
71
|
+
it('remains unchecked when its "click" event is canceled', async () => {
|
72
|
+
const component = await fixture(html `<glide-core-toggle label="Label"></glide-core-toggle>`);
|
73
|
+
component.addEventListener('click', async (event) => {
|
74
|
+
event.preventDefault();
|
75
|
+
});
|
76
|
+
component.click();
|
77
|
+
expect(component.hasAttribute('checked')).to.be.false;
|
78
|
+
expect(component.checked).to.equal(false);
|
79
|
+
const input = component.shadowRoot?.querySelector('[data-test="input"]');
|
80
|
+
expect(input?.getAttribute('aria-checked')).to.equal('false');
|
81
|
+
});
|
package/dist/tooltip.d.ts
CHANGED
@@ -5,8 +5,8 @@ declare global {
|
|
5
5
|
}
|
6
6
|
}
|
7
7
|
/**
|
8
|
-
* @slot - The
|
9
|
-
* @slot target - The element to which the tooltip should
|
8
|
+
* @slot - The content of the tooltip.
|
9
|
+
* @slot target - The element to which the tooltip should anchor.
|
10
10
|
*/
|
11
11
|
export default class GlideCoreTooltip extends LitElement {
|
12
12
|
#private;
|
package/dist/tooltip.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,t,o,l){var i,s=arguments.length,a=s<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,o,l);else for(var n=e.length-1;n>=0;n--)(i=e[n])&&(a=(s<3?i(a):s>3?i(t,o,a):i(t,o))||a);return s>3&&a&&Object.defineProperty(t,o,a),a};import{LitElement,html}from"lit";import{arrow,autoUpdate,computePosition,flip,limitShift,offset,shift}from"@floating-ui/dom";import{choose}from"lit/directives/choose.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 ow,{owSlot}from"./library/ow.js";import styles from"./tooltip.styles.js";let GlideCoreTooltip=class GlideCoreTooltip extends LitElement{constructor(){super(...arguments),this.offset=4,this.effectivePlacement=this.placement??"bottom",this.#e=createRef(),this.#t=createRef(),this.#o=!1,this.#l=!1,this.#i=createRef(),this.#s=createRef(),this.#a=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}get disabled(){return this.#o}set disabled(e){this.#o=e,this.open&&!e?this.#n():this.#r()}get open(){return this.#l}set open(e){this.#l=e,e&&!this.disabled?this.#n():this.#r()}disconnectedCallback(){super.disconnectedCallback(),clearTimeout(this.#f),clearTimeout(this.#p)}firstUpdated(){owSlot(this.#t.value),owSlot(this.#s.value),ow(this.#a.value,ow.object.instanceOf(HTMLElement)),this.#a.value.popover="manual",this.open&&!this.disabled&&this.#n()}render(){return html`<div class="component" @mouseover="${this.#
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,l){var i,s=arguments.length,a=s<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,o,l);else for(var n=e.length-1;n>=0;n--)(i=e[n])&&(a=(s<3?i(a):s>3?i(t,o,a):i(t,o))||a);return s>3&&a&&Object.defineProperty(t,o,a),a};import{LitElement,html}from"lit";import{arrow,autoUpdate,computePosition,flip,limitShift,offset,shift}from"@floating-ui/dom";import{choose}from"lit/directives/choose.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 ow,{owSlot}from"./library/ow.js";import styles from"./tooltip.styles.js";let GlideCoreTooltip=class GlideCoreTooltip extends LitElement{constructor(){super(...arguments),this.offset=4,this.effectivePlacement=this.placement??"bottom",this.#e=createRef(),this.#t=createRef(),this.#o=!1,this.#l=!1,this.#i=createRef(),this.#s=createRef(),this.#a=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}get disabled(){return this.#o}set disabled(e){this.#o=e,this.open&&!e?this.#n():this.#r()}get open(){return this.#l}set open(e){this.#l=e,e&&!this.disabled?this.#n():this.#r()}disconnectedCallback(){super.disconnectedCallback(),clearTimeout(this.#f),clearTimeout(this.#p)}firstUpdated(){owSlot(this.#t.value),owSlot(this.#s.value),ow(this.#a.value,ow.object.instanceOf(HTMLElement)),this.#a.value.popover="manual",this.open&&!this.disabled&&this.#n()}render(){return html`<div class="component" data-test="component" @mouseover="${this.#d}" @mouseout="${this.#h}"><div aria-labelledby="${ifDefined(this.disabled?void 0:"tooltip")}" class="target" data-test="target" slot="target" @focusin="${this.#c}" @focusout="${this.#m}" @keydown="${this.#u}" ${ref(this.#i)}><slot @slotchange="${this.#v}" ${ref(this.#s)} name="target"></slot></div><div class="${classMap({tooltip:!0,[this.effectivePlacement]:!0})}" id="tooltip" data-test="tooltip" data-open-delay="300" data-close-delay="200" role="${ifDefined(this.disabled?void 0:"tooltip")}" ${ref(this.#a)}><div class="${classMap({arrow:!0,[this.effectivePlacement]:!0})}" data-test="arrow" ${ref(this.#e)}>${choose(this.effectivePlacement,[["top",()=>html`<svg viewBox="0 0 10 6" fill="none"><path d="M4.23178 5.07814C4.63157 5.55789 5.36843 5.55789 5.76822 5.07813L10 -7.9486e-08L-2.62268e-07 3.57628e-07L4.23178 5.07814Z" fill="#212121"/></svg>`],["right",()=>html`<svg viewBox="0 0 6 10" fill="none"><path d="M0.921865 4.23178C0.442111 4.63157 0.442112 5.36843 0.921866 5.76822L6 10L6 -2.62268e-07L0.921865 4.23178Z" fill="#212121"/></svg>`],["bottom",()=>html`<svg viewBox="0 0 10 6" fill="none"><path d="M4.23178 0.921865C4.63157 0.442111 5.36843 0.442112 5.76822 0.921866L10 6L-2.62268e-07 6L4.23178 0.921865Z" fill="#212121"/></svg>`],["left",()=>html`<svg viewBox="0 0 6 10" fill="none"><path d="M5.07814 4.23178C5.55789 4.63157 5.55789 5.36843 5.07813 5.76822L-4.37114e-07 10L0 -2.62268e-07L5.07814 4.23178Z" fill="#212121"/></svg>`]])}</div><span aria-label="${ifDefined(this.disabled?void 0:"Tooltip: ")}"></span><slot class="default-slot" @slotchange="${this.#R}" ${ref(this.#t)}></slot></div></div>`}#e;#g;#f;#t;#o;#l;#p;#i;#s;#a;#E(){clearTimeout(this.#f)}#r(){this.#a.value?.hidePopover(),this.#g&&this.#g()}#R(){owSlot(this.#t.value)}#c(){this.open=!0}#m(){this.open=!1}#u(e){"Escape"===e.key&&(this.open=!1)}#h(){this.#w(),clearTimeout(this.#p)}#d(){ow(this.#a.value,ow.object.instanceOf(HTMLElement)),this.#E(),this.#p=setTimeout((()=>{this.open=!0}),Number(this.#a.value.dataset.openDelay))}#v(){owSlot(this.#s.value)}#w(){ow(this.#a.value,ow.object.instanceOf(HTMLElement)),this.#f=setTimeout((()=>{this.open=!1}),Number(this.#a.value.dataset.closeDelay))}#n(){this.disabled||(this.#g?.(),this.#i.value&&this.#a.value&&(this.#g=autoUpdate(this.#i.value,this.#a.value,(()=>{(async()=>{if(this.#i.value&&this.#a.value&&this.#e.value){const{x:e,y:t,placement:o,middlewareData:l}=await computePosition(this.#i.value,this.#a.value,{placement:this.placement,middleware:[offset(this.offset),flip({fallbackStrategy:"initialPlacement"}),shift({limiter:limitShift({offset:20})}),arrow({element:this.#e.value})]});Object.assign(this.#a.value.style,{left:`${e}px`,top:`${t}px`}),Object.assign(this.#e.value.style,{left:l.arrow?.x?`${l.arrow.x}px`:null,top:l.arrow?.y?`${l.arrow.y}px`:null}),this.effectivePlacement=o,this.#a.value.showPopover()}})()}))))}};__decorate([property({reflect:!0,type:Boolean})],GlideCoreTooltip.prototype,"disabled",null),__decorate([property({reflect:!0,type:Number})],GlideCoreTooltip.prototype,"offset",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTooltip.prototype,"open",null),__decorate([property()],GlideCoreTooltip.prototype,"placement",void 0),__decorate([state()],GlideCoreTooltip.prototype,"effectivePlacement",void 0),GlideCoreTooltip=__decorate([customElement("glide-core-tooltip")],GlideCoreTooltip);export default GlideCoreTooltip;
|
package/dist/tooltip.styles.js
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
|
2
|
-
|
2
|
+
${focusOutline(".target:focus-visible")}
|
3
|
+
`,css`
|
4
|
+
@keyframes opacity-and-scale {
|
3
5
|
from {
|
4
6
|
opacity: 0;
|
5
7
|
transform: scale(0.95);
|
@@ -11,6 +13,12 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
11
13
|
}
|
12
14
|
}
|
13
15
|
|
16
|
+
@media (prefers-reduced-motion: reduce) {
|
17
|
+
.tooltip:popover-open {
|
18
|
+
animation: none !important;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
14
22
|
:host {
|
15
23
|
display: inline-block;
|
16
24
|
}
|
@@ -28,9 +36,9 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
28
36
|
background-color: transparent;
|
29
37
|
border-width: 0;
|
30
38
|
|
31
|
-
/*
|
32
|
-
Additional whitespace from line height and the tooltip won't be vertically
|
33
|
-
centered against its target.
|
39
|
+
/*
|
40
|
+
Additional whitespace from line height and the tooltip won't be vertically
|
41
|
+
centered against its target.
|
34
42
|
*/
|
35
43
|
display: flex;
|
36
44
|
|
@@ -43,10 +51,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
43
51
|
outline: none;
|
44
52
|
}
|
45
53
|
|
46
|
-
&:focus-visible {
|
47
|
-
${focusOutline};
|
48
|
-
}
|
49
|
-
|
50
54
|
::slotted svg {
|
51
55
|
display: block;
|
52
56
|
}
|
@@ -68,19 +72,19 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
68
72
|
}
|
69
73
|
|
70
74
|
&:popover-open {
|
71
|
-
animation:
|
75
|
+
animation: opacity-and-scale 250ms cubic-bezier(0.25, 0, 0.3, 1);
|
72
76
|
display: flex;
|
73
77
|
|
74
|
-
/*
|
78
|
+
/*
|
75
79
|
Elements with a "popover" attribute don't allow overflow. So the arrow can't
|
76
|
-
be positioned with "position: absolute". Relative positioning is used instead.
|
77
|
-
Flex is used to get the arrow on the correct side of the tooltip. Floating UI
|
78
|
-
handles the rest.
|
79
|
-
|
80
|
-
A simple "transform" could replace Floating UI for the arrow if not for a Chrome
|
81
|
-
bug with "popover" when "scale()" is animated on the popover or a container within
|
82
|
-
it. With "transform" on the arrow, the arrow is initially offset by a couple pixels
|
83
|
-
before landing in the correct position when the animation finishes. It only happens
|
80
|
+
be positioned with "position: absolute". Relative positioning is used instead.
|
81
|
+
Flex is used to get the arrow on the correct side of the tooltip. Floating UI
|
82
|
+
handles the rest.
|
83
|
+
|
84
|
+
A simple "transform" could replace Floating UI for the arrow if not for a Chrome
|
85
|
+
bug with "popover" when "scale()" is animated on the popover or a container within
|
86
|
+
it. With "transform" on the arrow, the arrow is initially offset by a couple pixels
|
87
|
+
before landing in the correct position when the animation finishes. It only happens
|
84
88
|
when the tooltip is left or right of its target.
|
85
89
|
*/
|
86
90
|
|