@crowdstrike/glide-core 0.9.1 → 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.styles.js +2 -4
- package/dist/button-group.button.styles.js +3 -8
- package/dist/button-group.styles.js +2 -2
- package/dist/button.d.ts +1 -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.js +1 -1
- package/dist/checkbox.styles.js +43 -6
- package/dist/checkbox.test.form.js +16 -0
- package/dist/checkbox.test.interactions.js +8 -0
- package/dist/drawer.js +1 -1
- package/dist/dropdown.d.ts +4 -2
- 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.styles.js +2 -4
- package/dist/icons/checked.d.ts +5 -0
- package/dist/icons/checked.js +1 -1
- package/dist/input.d.ts +1 -1
- 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 +6 -11
- 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 +1 -97
- package/dist/menu.test.focus.js +26 -3
- package/dist/menu.test.interactions.js +3 -0
- package/dist/modal.d.ts +0 -7
- package/dist/modal.icon-button.test.basics.js +9 -9
- package/dist/modal.styles.js +2 -4
- package/dist/modal.tertiary-icon.test.basics.js +14 -14
- 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.js +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.styles.js +2 -6
- package/dist/split-button.styles.js +2 -4
- package/dist/split-container.styles.js +2 -4
- 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/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 +1 -1
- 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.styles.js +2 -1
- package/dist/toggle.test.interactions.js +11 -0
- 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.item.styles.js +11 -3
- package/dist/tree.item.test.basics.js +0 -30
- package/package.json +1 -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
@@ -11,91 +11,89 @@ GlideCoreModal.shadowRootOptions.mode = 'open';
|
|
11
11
|
it('registers', async () => {
|
12
12
|
expect(window.customElements.get('glide-core-modal')).to.equal(GlideCoreModal);
|
13
13
|
});
|
14
|
-
it('
|
15
|
-
const
|
16
|
-
|
17
|
-
</glide-core-modal>`);
|
18
|
-
const dialog = element.shadowRoot?.querySelector('dialog');
|
14
|
+
it('has defaults', async () => {
|
15
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
16
|
+
const dialog = component.shadowRoot?.querySelector('dialog');
|
19
17
|
expect(dialog).to.be.ok;
|
20
18
|
expect(dialog?.hasAttribute('open')).to.be.false;
|
19
|
+
expect(component.size).to.equal('medium');
|
20
|
+
expect(component.getAttribute('size')).to.equal('medium');
|
21
|
+
expect(component.showBackButton).to.be.false;
|
22
|
+
expect(component.hasAttribute('show-back-button')).to.be.false;
|
21
23
|
});
|
22
24
|
it('renders the provided "label"', async () => {
|
23
|
-
const
|
24
|
-
|
25
|
-
|
26
|
-
element.showModal();
|
27
|
-
const label = element.shadowRoot?.querySelector('[data-test="heading"]');
|
25
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
26
|
+
component.showModal();
|
27
|
+
const label = component.shadowRoot?.querySelector('[data-test="heading"]');
|
28
28
|
expect(label).to.be.ok;
|
29
|
-
expect(label?.textContent?.trim()).to.equal('
|
29
|
+
expect(label?.textContent?.trim()).to.equal('Label');
|
30
30
|
});
|
31
31
|
it('does not render the show back button in the label by default', async () => {
|
32
|
-
const
|
33
|
-
|
34
|
-
|
35
|
-
element.showModal();
|
36
|
-
expect(element.shadowRoot?.querySelector('[data-test="back-button"]')).to.be.null;
|
32
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
33
|
+
component.showModal();
|
34
|
+
expect(component.shadowRoot?.querySelector('[data-test="back-button"]')).to.be.null;
|
37
35
|
});
|
38
36
|
it('renders the show back button in the label when provided with "show-back-button"', async () => {
|
39
|
-
const
|
40
|
-
|
37
|
+
const component = await fixture(html `<glide-core-modal label="Label" show-back-button>
|
38
|
+
Content
|
41
39
|
</glide-core-modal>`);
|
42
|
-
|
43
|
-
expect(
|
40
|
+
component.showModal();
|
41
|
+
expect(component.shadowRoot?.querySelector('[data-test="back-button"]')).to.be.ok;
|
44
42
|
});
|
45
43
|
it('renders the provided default slotted content', async () => {
|
46
|
-
const
|
44
|
+
const component = await fixture(html `<glide-core-modal label="Label">
|
47
45
|
<p data-body>Inner content</p>
|
48
46
|
</glide-core-modal>`);
|
49
|
-
|
50
|
-
const body =
|
47
|
+
component.showModal();
|
48
|
+
const body = component.querySelector('[data-body]');
|
51
49
|
expect(body).to.be.ok;
|
52
50
|
});
|
53
51
|
it('renders the provided primary slot content', async () => {
|
54
|
-
const
|
55
|
-
|
52
|
+
const component = await fixture(html `<glide-core-modal label="Label">
|
53
|
+
Content
|
56
54
|
<glide-core-button slot="primary" data-primary>Primary</glide-core-button>
|
57
55
|
</glide-core-modal>`);
|
58
|
-
|
59
|
-
const slotContent =
|
56
|
+
component.showModal();
|
57
|
+
const slotContent = component.querySelector('[data-primary]');
|
60
58
|
expect(slotContent).to.be.ok;
|
61
|
-
const slotNodes =
|
59
|
+
const slotNodes = component.shadowRoot
|
62
60
|
?.querySelector('slot[name="primary"]')
|
63
61
|
?.assignedNodes();
|
64
62
|
expect(slotNodes?.length).to.equal(1);
|
65
63
|
});
|
66
64
|
it('renders the provided secondary slot content', async () => {
|
67
|
-
const
|
68
|
-
|
65
|
+
const component = await fixture(html `<glide-core-modal label="Label">
|
66
|
+
Content
|
69
67
|
<glide-core-button slot="secondary" data-secondary
|
70
68
|
>Secondary</glide-core-button
|
71
69
|
>
|
72
70
|
</glide-core-modal>`);
|
73
|
-
|
74
|
-
const slotContent =
|
71
|
+
component.showModal();
|
72
|
+
const slotContent = component.querySelector('[data-secondary]');
|
75
73
|
expect(slotContent).to.be.ok;
|
76
|
-
const slotNodes =
|
74
|
+
const slotNodes = component.shadowRoot
|
77
75
|
?.querySelector('slot[name="secondary"]')
|
78
76
|
?.assignedNodes();
|
79
77
|
expect(slotNodes?.length).to.equal(1);
|
80
78
|
});
|
81
79
|
it('renders the provided tertiary slot content', async () => {
|
82
|
-
const
|
83
|
-
|
80
|
+
const component = await fixture(html `<glide-core-modal label="Label">
|
81
|
+
Content
|
84
82
|
<glide-core-button slot="tertiary" data-tertiary
|
85
83
|
>Tertiary</glide-core-button
|
86
84
|
>
|
87
85
|
</glide-core-modal>`);
|
88
|
-
|
89
|
-
const slotContent =
|
86
|
+
component.showModal();
|
87
|
+
const slotContent = component.querySelector('[data-tertiary]');
|
90
88
|
expect(slotContent).to.be.ok;
|
91
|
-
const slotNodes =
|
89
|
+
const slotNodes = component.shadowRoot
|
92
90
|
?.querySelector('slot[name="tertiary"]')
|
93
91
|
?.assignedNodes();
|
94
92
|
expect(slotNodes?.length).to.equal(1);
|
95
93
|
});
|
96
94
|
it('renders the provided header-actions slot content', async () => {
|
97
|
-
const
|
98
|
-
|
95
|
+
const component = await fixture(html `<glide-core-modal label="Label">
|
96
|
+
Content
|
99
97
|
|
100
98
|
<glide-core-modal-icon-button slot="header-actions" data-actions="1"
|
101
99
|
>action1</glide-core-modal-icon-button
|
@@ -105,63 +103,61 @@ it('renders the provided header-actions slot content', async () => {
|
|
105
103
|
>action2</glide-core-modal-icon-button
|
106
104
|
>
|
107
105
|
</glide-core-modal>`);
|
108
|
-
|
109
|
-
const slotContent =
|
106
|
+
component.showModal();
|
107
|
+
const slotContent = component.querySelector('[data-actions]');
|
110
108
|
expect(slotContent).to.be.ok;
|
111
|
-
const slotNodes =
|
109
|
+
const slotNodes = component.shadowRoot
|
112
110
|
?.querySelector('slot[name="header-actions"]')
|
113
111
|
?.assignedNodes();
|
114
112
|
expect(slotNodes?.length).to.equal(2);
|
115
113
|
});
|
116
114
|
it('defaults the size to "medium"', async () => {
|
117
|
-
const
|
118
|
-
Modal Content
|
119
|
-
</glide-core-modal>`);
|
115
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
120
116
|
expect([
|
121
|
-
...
|
117
|
+
...component.shadowRoot.querySelector('dialog')
|
122
118
|
.classList,
|
123
119
|
]).to.deep.equal(['component', 'medium']);
|
124
120
|
});
|
125
121
|
it('sets the size to "small"', async () => {
|
126
|
-
const
|
127
|
-
|
122
|
+
const component = await fixture(html `<glide-core-modal label="Label" size="small">
|
123
|
+
Content
|
128
124
|
</glide-core-modal>`);
|
129
125
|
expect([
|
130
|
-
...
|
126
|
+
...component.shadowRoot.querySelector('dialog')
|
131
127
|
.classList,
|
132
128
|
]).to.deep.equal(['component', 'small']);
|
133
129
|
});
|
134
130
|
it('sets the size to "medium"', async () => {
|
135
|
-
const
|
136
|
-
|
131
|
+
const component = await fixture(html `<glide-core-modal label="Label" size="medium">
|
132
|
+
Content
|
137
133
|
</glide-core-modal>`);
|
138
134
|
expect([
|
139
|
-
...
|
135
|
+
...component.shadowRoot.querySelector('dialog')
|
140
136
|
.classList,
|
141
137
|
]).to.deep.equal(['component', 'medium']);
|
142
138
|
});
|
143
139
|
it('sets the size to "large"', async () => {
|
144
|
-
const
|
145
|
-
|
140
|
+
const component = await fixture(html `<glide-core-modal label="Label" size="large">
|
141
|
+
Content
|
146
142
|
</glide-core-modal>`);
|
147
143
|
expect([
|
148
|
-
...
|
144
|
+
...component.shadowRoot.querySelector('dialog')
|
149
145
|
.classList,
|
150
146
|
]).to.deep.equal(['component', 'large']);
|
151
147
|
});
|
152
148
|
it('sets the size to "xlarge"', async () => {
|
153
|
-
const
|
154
|
-
|
149
|
+
const component = await fixture(html `<glide-core-modal label="Label" size="xlarge">
|
150
|
+
Content
|
155
151
|
</glide-core-modal>`);
|
156
152
|
expect([
|
157
|
-
...
|
153
|
+
...component.shadowRoot.querySelector('dialog')
|
158
154
|
.classList,
|
159
155
|
]).to.deep.equal(['component', 'xlarge']);
|
160
156
|
});
|
161
157
|
it('throws if it does not have a default slot', async () => {
|
162
158
|
const spy = sinon.spy();
|
163
159
|
try {
|
164
|
-
await fixture(html `<glide-core-modal label="
|
160
|
+
await fixture(html `<glide-core-modal label="Label"></glide-core-modal>`);
|
165
161
|
}
|
166
162
|
catch (error) {
|
167
163
|
if (error instanceof ArgumentError) {
|
@@ -172,32 +168,32 @@ it('throws if it does not have a default slot', async () => {
|
|
172
168
|
});
|
173
169
|
it('throws an error when the "primary" footer slot has the incorrect type', async () => {
|
174
170
|
await expectArgumentError(() => {
|
175
|
-
return fixture(html `<glide-core-modal label="
|
176
|
-
|
171
|
+
return fixture(html `<glide-core-modal label="Label">
|
172
|
+
Content
|
177
173
|
<span slot="primary">Primary</span>
|
178
174
|
</glide-core-modal>`);
|
179
175
|
});
|
180
176
|
});
|
181
177
|
it('throws an error when the "secondary" footer slot has the incorrect type', async () => {
|
182
178
|
await expectArgumentError(() => {
|
183
|
-
return fixture(html `<glide-core-modal label="
|
184
|
-
|
179
|
+
return fixture(html `<glide-core-modal label="Label">
|
180
|
+
Content
|
185
181
|
<span slot="secondary">Secondary</span>
|
186
182
|
</glide-core-modal>`);
|
187
183
|
});
|
188
184
|
});
|
189
185
|
it('throws an error when the "header actions" slot has the incorrect type', async () => {
|
190
186
|
await expectArgumentError(() => {
|
191
|
-
return fixture(html `<glide-core-modal label="
|
192
|
-
|
187
|
+
return fixture(html `<glide-core-modal label="Label">
|
188
|
+
Content
|
193
189
|
<span slot="header-actions">Header Action</span>
|
194
190
|
</glide-core-modal>`);
|
195
191
|
});
|
196
192
|
});
|
197
193
|
it('throws an error when the "tertiary" footer slot has the incorrect type', async () => {
|
198
194
|
await expectArgumentError(() => {
|
199
|
-
return fixture(html `<glide-core-modal label="
|
200
|
-
|
195
|
+
return fixture(html `<glide-core-modal label="Label">
|
196
|
+
Content
|
201
197
|
<span slot="tertiary">Tertiary</span>
|
202
198
|
</glide-core-modal>`);
|
203
199
|
});
|
package/dist/modal.test.close.js
CHANGED
@@ -4,35 +4,31 @@ import { sendKeys } from '@web/test-runner-commands';
|
|
4
4
|
import GlideCoreModal from './modal.js';
|
5
5
|
GlideCoreModal.shadowRootOptions.mode = 'open';
|
6
6
|
it('closes the modal when the close button is clicked', async () => {
|
7
|
-
const
|
8
|
-
|
9
|
-
|
10
|
-
element.showModal();
|
11
|
-
const button = element.shadowRoot.querySelector('[data-test="close-button"]');
|
7
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
8
|
+
component.showModal();
|
9
|
+
const button = component.shadowRoot.querySelector('[data-test="close-button"]');
|
12
10
|
expect(button).to.be.ok;
|
13
11
|
button?.click();
|
14
|
-
expect(
|
12
|
+
expect(component
|
15
13
|
.shadowRoot.querySelector('dialog')
|
16
14
|
?.hasAttribute('open')).to.be.false;
|
17
15
|
});
|
18
16
|
it('closes the modal when the escape key is pressed', async () => {
|
19
|
-
const
|
20
|
-
|
21
|
-
|
22
|
-
element.showModal();
|
23
|
-
const dialogElement = element.shadowRoot.querySelector('dialog');
|
17
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
18
|
+
component.showModal();
|
19
|
+
const dialogElement = component.shadowRoot.querySelector('dialog');
|
24
20
|
expect(dialogElement?.hasAttribute('open')).to.be.true;
|
25
21
|
await sendKeys({ press: 'Escape' });
|
26
22
|
expect(dialogElement?.hasAttribute('open')).to.be.false;
|
27
23
|
});
|
28
24
|
it('closes the modal via "show-back-button"', async () => {
|
29
|
-
const
|
30
|
-
|
25
|
+
const component = await fixture(html `<glide-core-modal label="Label" show-back-button>
|
26
|
+
Content
|
31
27
|
</glide-core-modal>`);
|
32
|
-
|
33
|
-
const dialogElement =
|
28
|
+
component.showModal();
|
29
|
+
const dialogElement = component.shadowRoot.querySelector('dialog');
|
34
30
|
expect(dialogElement?.hasAttribute('open')).to.be.true;
|
35
|
-
const button =
|
31
|
+
const button = component.shadowRoot.querySelector('[data-test="back-button"]');
|
36
32
|
expect(button).to.be.ok;
|
37
33
|
button?.click();
|
38
34
|
expect(dialogElement?.hasAttribute('open')).to.be.false;
|
@@ -7,44 +7,36 @@ import sinon from 'sinon';
|
|
7
7
|
GlideCoreModal.shadowRootOptions.mode = 'open';
|
8
8
|
it('dispatches a "close" event when the modal is closed via the "close" method', async () => {
|
9
9
|
const spy = sinon.spy();
|
10
|
-
const
|
11
|
-
|
12
|
-
|
13
|
-
element.addEventListener('close', spy);
|
14
|
-
element.showModal();
|
10
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
11
|
+
component.addEventListener('close', spy);
|
12
|
+
component.showModal();
|
15
13
|
expect(spy.callCount).to.equal(0);
|
16
|
-
|
14
|
+
component.close();
|
17
15
|
expect(spy.callCount).to.equal(1);
|
18
16
|
});
|
19
17
|
it('dispatches a "close" event when the modal is closed via the close button', async () => {
|
20
18
|
const spy = sinon.spy();
|
21
|
-
const
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
element.showModal();
|
26
|
-
const button = element.shadowRoot?.querySelector('[data-test="close-button"]');
|
19
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
20
|
+
component.addEventListener('close', spy);
|
21
|
+
component.showModal();
|
22
|
+
const button = component.shadowRoot?.querySelector('[data-test="close-button"]');
|
27
23
|
expect(button).to.be.ok;
|
28
24
|
button?.click();
|
29
25
|
expect(spy.callCount).to.equal(1);
|
30
26
|
});
|
31
27
|
it('dispatches a "close" event when the modal is closed via the escape key', async () => {
|
32
28
|
const spy = sinon.spy();
|
33
|
-
const
|
34
|
-
|
35
|
-
|
36
|
-
element.addEventListener('close', spy);
|
37
|
-
element.showModal();
|
29
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
30
|
+
component.addEventListener('close', spy);
|
31
|
+
component.showModal();
|
38
32
|
await sendKeys({ press: 'Escape' });
|
39
33
|
expect(spy.callCount).to.equal(1);
|
40
34
|
});
|
41
35
|
it('does not dispatch a "close" event when the modal is open and non-escape keys are pressed', async () => {
|
42
36
|
const spy = sinon.spy();
|
43
|
-
const
|
44
|
-
|
45
|
-
|
46
|
-
element.addEventListener('close', spy);
|
47
|
-
element.showModal();
|
37
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
38
|
+
component.addEventListener('close', spy);
|
39
|
+
component.showModal();
|
48
40
|
// Tests only a couple keys.
|
49
41
|
await sendKeys({ press: ' ' });
|
50
42
|
expect(spy.callCount).to.equal(0);
|
@@ -53,24 +45,22 @@ it('does not dispatch a "close" event when the modal is open and non-escape keys
|
|
53
45
|
});
|
54
46
|
it('dispatches a "close" event when the modal is closed via "show-back-button"', async () => {
|
55
47
|
const spy = sinon.spy();
|
56
|
-
const
|
57
|
-
|
48
|
+
const component = await fixture(html `<glide-core-modal label="Label" show-back-button>
|
49
|
+
Content
|
58
50
|
</glide-core-modal>`);
|
59
|
-
|
60
|
-
|
61
|
-
const button =
|
51
|
+
component.addEventListener('close', spy);
|
52
|
+
component.showModal();
|
53
|
+
const button = component.shadowRoot?.querySelector('[data-test="back-button"]');
|
62
54
|
expect(button).to.be.ok;
|
63
55
|
button?.click();
|
64
56
|
expect(spy.callCount).to.equal(1);
|
65
57
|
});
|
66
58
|
it('does not emit a "close" event when clicking inside the dialog and the mouse is not positioned on a "close" button', async () => {
|
67
59
|
const spy = sinon.spy();
|
68
|
-
const
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
element.addEventListener('close', spy);
|
73
|
-
const dialogElement = element?.shadowRoot?.querySelector('dialog');
|
60
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
61
|
+
component.showModal();
|
62
|
+
component.addEventListener('close', spy);
|
63
|
+
const dialogElement = component?.shadowRoot?.querySelector('dialog');
|
74
64
|
const boundingRectangle = dialogElement?.getBoundingClientRect();
|
75
65
|
expect(boundingRectangle).is.not.null;
|
76
66
|
const { top, left } = boundingRectangle;
|
@@ -80,26 +70,24 @@ it('does not emit a "close" event when clicking inside the dialog and the mouse
|
|
80
70
|
});
|
81
71
|
expect(spy.callCount).to.equal(0);
|
82
72
|
});
|
83
|
-
it(`does not emit a "close" event if a mousedown event's origin does not come from the dialog
|
73
|
+
it(`does not emit a "close" event if a mousedown event's origin does not come from the dialog component`, async () => {
|
84
74
|
const spy = sinon.spy();
|
85
|
-
const
|
75
|
+
const component = await fixture(html `<glide-core-modal label="Label">
|
86
76
|
<button data-test="target">Inside Body</button>
|
87
77
|
</glide-core-modal>`);
|
88
|
-
|
89
|
-
|
90
|
-
const button =
|
78
|
+
component.showModal();
|
79
|
+
component.addEventListener('close', spy);
|
80
|
+
const button = component.querySelector('[data-test="target"]');
|
91
81
|
expect(button).to.be.ok;
|
92
82
|
button?.dispatchEvent(new Event('mousedown', { bubbles: true }));
|
93
83
|
expect(spy.callCount).to.equal(0);
|
94
84
|
});
|
95
85
|
it('emits a "close" event when clicking outside the dialog', async () => {
|
96
86
|
const spy = sinon.spy();
|
97
|
-
const
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
element.addEventListener('close', spy);
|
102
|
-
const dialogElement = element?.shadowRoot?.querySelector('dialog');
|
87
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
88
|
+
component.showModal();
|
89
|
+
component.addEventListener('close', spy);
|
90
|
+
const dialogElement = component?.shadowRoot?.querySelector('dialog');
|
103
91
|
const boundingRectangle = dialogElement?.getBoundingClientRect();
|
104
92
|
expect(boundingRectangle).is.not.null;
|
105
93
|
const { top, left } = boundingRectangle;
|
@@ -15,56 +15,46 @@ after(() => {
|
|
15
15
|
removeSpy.restore();
|
16
16
|
});
|
17
17
|
it('adds the "private-glide-core-modal-lock-scroll" class to the documentElement when opened and removes it when closed', async () => {
|
18
|
-
const
|
19
|
-
|
20
|
-
>`);
|
21
|
-
element.showModal();
|
18
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
19
|
+
component.showModal();
|
22
20
|
expect(addSpy.callCount).to.equal(1);
|
23
21
|
expect(addSpy.calledWith('private-glide-core-modal-lock-scroll')).to.be.ok;
|
24
22
|
expect(removeSpy.callCount).to.equal(0);
|
25
|
-
|
23
|
+
component.close();
|
26
24
|
expect(removeSpy.callCount).to.equal(1);
|
27
25
|
expect(removeSpy.calledWith('private-glide-core-modal-lock-scroll')).to.be.ok;
|
28
26
|
// Verify `add` was not called again for some reason
|
29
27
|
expect(addSpy.callCount).to.equal(1);
|
30
28
|
});
|
31
29
|
it('removes the "private-glide-core-modal-lock-scroll" class when the close button is clicked', async () => {
|
32
|
-
const
|
33
|
-
|
34
|
-
>`);
|
35
|
-
element.showModal();
|
30
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
31
|
+
component.showModal();
|
36
32
|
expect(removeSpy.callCount).to.equal(0);
|
37
|
-
const button =
|
33
|
+
const button = component.shadowRoot.querySelector('[data-test="close-button"]');
|
38
34
|
expect(button).to.be.ok;
|
39
35
|
button?.click();
|
40
36
|
expect(removeSpy.callCount).to.equal(1);
|
41
37
|
});
|
42
38
|
it('removes the "private-glide-core-modal-lock-scroll" class when the "close" method is called', async () => {
|
43
|
-
const
|
44
|
-
|
45
|
-
>`);
|
46
|
-
element.showModal();
|
39
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
40
|
+
component.showModal();
|
47
41
|
expect(removeSpy.callCount).to.equal(0);
|
48
|
-
const dialogElement =
|
42
|
+
const dialogElement = component.shadowRoot.querySelector('dialog');
|
49
43
|
expect(dialogElement?.hasAttribute('open')).to.be.true;
|
50
|
-
|
44
|
+
component.close();
|
51
45
|
expect(removeSpy.callCount).to.equal(1);
|
52
46
|
});
|
53
47
|
it('removes the "private-glide-core-modal-lock-scroll" class when the escape key is pressed', async () => {
|
54
|
-
const
|
55
|
-
|
56
|
-
>`);
|
57
|
-
element.showModal();
|
48
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
49
|
+
component.showModal();
|
58
50
|
expect(removeSpy.callCount).to.equal(0);
|
59
51
|
await sendKeys({ press: 'Escape' });
|
60
52
|
expect(removeSpy.callCount).to.equal(1);
|
61
53
|
});
|
62
54
|
it('removes class "private-glide-core-modal-lock-scroll" from document when click is outside dialog', async () => {
|
63
|
-
const
|
64
|
-
|
65
|
-
|
66
|
-
element.showModal();
|
67
|
-
const dialogElement = element?.shadowRoot?.querySelector('dialog');
|
55
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
56
|
+
component.showModal();
|
57
|
+
const dialogElement = component?.shadowRoot?.querySelector('dialog');
|
68
58
|
const boundingRectangle = dialogElement?.getBoundingClientRect();
|
69
59
|
expect(boundingRectangle).is.not.null;
|
70
60
|
expect(document.documentElement.classList.contains('private-glide-core-modal-lock-scroll')).to.be.true;
|
@@ -3,22 +3,18 @@ import { expect, fixture, html } from '@open-wc/testing';
|
|
3
3
|
import GlideCoreModal from './modal.js';
|
4
4
|
GlideCoreModal.shadowRootOptions.mode = 'open';
|
5
5
|
it('opens the modal when the "showModal" method is called and closes it when "close" is called', async () => {
|
6
|
-
const
|
7
|
-
|
8
|
-
|
9
|
-
element.showModal();
|
10
|
-
const dialogElement = element.shadowRoot?.querySelector('dialog');
|
6
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
7
|
+
component.showModal();
|
8
|
+
const dialogElement = component.shadowRoot?.querySelector('dialog');
|
11
9
|
expect(dialogElement?.hasAttribute('open')).to.be.true;
|
12
|
-
|
10
|
+
component.close();
|
13
11
|
expect(dialogElement?.hasAttribute('open')).to.be.false;
|
14
12
|
});
|
15
13
|
it('remains open when the "showModal" method is called twice', async () => {
|
16
|
-
const
|
17
|
-
|
18
|
-
|
19
|
-
element.showModal();
|
20
|
-
const dialogElement = element.shadowRoot?.querySelector('dialog');
|
14
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
15
|
+
component.showModal();
|
16
|
+
const dialogElement = component.shadowRoot?.querySelector('dialog');
|
21
17
|
expect(dialogElement?.hasAttribute('open')).to.be.true;
|
22
|
-
|
18
|
+
component.showModal();
|
23
19
|
expect(dialogElement?.hasAttribute('open')).to.be.true;
|
24
20
|
});
|
@@ -11,10 +11,8 @@ afterEach(() => {
|
|
11
11
|
setPropertySpy.restore();
|
12
12
|
});
|
13
13
|
it('sets the "--glide-scroll-size" variable when the browser does not support scrollbar-gutter', async () => {
|
14
|
-
const
|
15
|
-
|
16
|
-
</glide-core-modal>`);
|
17
|
-
element.showModal();
|
14
|
+
const component = await fixture(html `<glide-core-modal label="Label">Content</glide-core-modal>`);
|
15
|
+
component.showModal();
|
18
16
|
expect(cssSupportsStub.calledWith('scrollbar-gutter')).to.be.ok;
|
19
17
|
expect(setPropertySpy.callCount).to.equal(1);
|
20
18
|
});
|
package/dist/radio-group.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,i,t,o){var s,
|
1
|
+
var __decorate=this&&this.__decorate||function(e,i,t,o){var s,a=arguments.length,d=a<3?i:null===o?o=Object.getOwnPropertyDescriptor(i,t):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)d=Reflect.decorate(e,i,t,o);else for(var r=e.length-1;r>=0;r--)(s=e[r])&&(d=(a<3?s(d):a>3?s(i,t,d):s(i,t))||d);return a>3&&d&&Object.defineProperty(i,t,d),d};import"./label.js";import"./tooltip.js";import{LitElement,html}from"lit";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{owSlot,owSlotType}from"./library/ow.js";import GlideCoreRadio from"./radio.js";import styles from"./radio-group.styles.js";let GlideCoreRadioGroup=class GlideCoreRadioGroup extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}checkValidity(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i),this.#t=void 0}firstUpdated(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#t=this.#s.find((e=>e.checked)),this.#a()}focus(e){let i=this.#s.find((e=>e.checked));i||(i=this.#s.find((e=>0===e.tabIndex))),i?.focus(e)}get form(){return this.#e.form}get validity(){return this.#e.validity}get willValidate(){return this.#e.willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){if(this.#t&&this.contains(this.#t))for(const e of this.#s)this.#d(e===this.#t,e)}render(){return html`<div class="component" @click="${this.#r}" @keydown="${this.#l}" ${ref(this.#n)}><glide-core-private-label orientation="horizontal" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?error="${this.#h}" ?hide="${this.hideLabel}" ?required="${this.required}"><label id="label" data-test="label">${this.label}</label><div class="${classMap({"radio-container":!0,vertical:!0,invalid:this.#h})}" role="radiogroup" slot="control" aria-labelledby="label description" @blur="${this.#c}"><slot ${ref(this.#o)} @slotchange="${this.#p}"></slot></div><slot name="tooltip" slot="tooltip"></slot><slot id="description" name="description" slot="description"></slot></glide-core-private-label></div>`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#e.reportValidity();return this.requestUpdate(),e}updated(e){this.hasUpdated&&(e.has("value")||e.has("required"))&&(this.#f(),this.#u(!this.#e.validity.valid),this.requestUpdate())}willUpdate(e){if(this.hasUpdated){if(e.has("required")&&this.#R(),e.has("disabled")){for(const e of this.#s)this.#m(this.disabled,e);!this.disabled&&this.#b()}if(e.has("value"))for(const e of this.#s)e.checked=e.value===this.value}}constructor(){super(),this.description="",this.disabled=!1,this.label="",this.hideLabel=!1,this.name="",this.required=!1,this.value="",this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#n=createRef(),this.#o=createRef(),this.#t=void 0,this.#i=({formData:e})=>{this.name&&this.value.length>0&&!this.disabled&&e.append(this.name,this.value)},this.#e=this.attachInternals(),this.addEventListener("invalid",this.#v)}#n;#o;#t;#e;#C;#i;#a(){const e=this.#s.find((e=>e.checked));this.value=e?.value??this.#t?.value??"",this.#C=e??this.#t,this.required&&this.#R();for(const e of this.#s)this.disabled?this.#m(this.disabled,e):this.#m(e.disabled,e),e.addEventListener("blur",this.#y.bind(this));!this.disabled&&this.#b()}get#h(){const e=!this.disabled&&!this.validity.valid&&this.isReportValidityOrSubmit;return this.#u(e),e}#c(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1}#r(e){if(this.disabled)return;if(e.target instanceof GlideCoreRadio&&e.target.disabled&&this.#C&&!this.#C.disabled)return void this.#C?.focus();const i=e.target;if(i instanceof GlideCoreRadio&&i&&!i.disabled){this.#d(!0,i);for(const e of this.#s)e!==i&&this.#d(!1,e)}}#p(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#a()}#v(e){if(e.preventDefault(),!this.isCheckingValidity){if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}}#l(e){if(!(this.disabled||e.target instanceof GlideCoreRadio&&e.target?.disabled)&&e.target instanceof GlideCoreRadio){const i=e.target;switch(e.key){case"Enter":this.form?.requestSubmit();break;case"ArrowUp":case"ArrowLeft":{e.preventDefault();let t=i.previousElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(-1);e&&(t=e)}else t=t.previousElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#d(!1,i),this.#d(!0,t));break}case"ArrowDown":case"ArrowRight":{e.preventDefault();let t=i.nextElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(0);e&&(t=e)}else t=t.nextElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#d(!1,i),this.#d(!0,t));break}case" ":if(e.preventDefault(),!i.disabled&&!i.checked){this.#d(!0,i);for(const e of this.#s)e!==i&&this.#d(!1,e)}}}}#y(e){const i=e.relatedTarget;i&&i instanceof GlideCoreRadio&&this.#s.includes(i)||this.#c()}#f(){const e=this.#s.find((e=>e.checked));this.required&&!e?this.#e.setValidity({valueMissing:!0}," ",this.#n.value):this.#e.setValidity({})}get#s(){return this.#o.value?.assignedElements().filter((e=>e instanceof GlideCoreRadio))??[]}#d(e,i){i.checked=e,i.tabIndex=e?0:-1,e&&(this.#C=i,this.value=i.value,i.focus(),i.dispatchEvent(new Event("change",{bubbles:!0})),i.dispatchEvent(new Event("input",{bubbles:!0})))}#m(e,i){i.disabled=e,e&&(i.tabIndex=-1)}#u(e){for(const i of this.#s)i.invalid=e}#b(){if(this.disabled||this.#s.every((e=>e.disabled)))return;let e=null;const i=this.#s.find((e=>!e.disabled&&e.checked));if(i)e=i;else{const i=this.#s.find((e=>!e.disabled));i&&(e=i)}if(e)for(const i of this.#s)i.tabIndex=i===e?0:-1}#R(){for(const e of this.#s)e.required=this.required}};__decorate([property()],GlideCoreRadioGroup.prototype,"description",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"disabled",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreRadioGroup.prototype,"hideLabel",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"name",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"privateSplit",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"required",void 0),__decorate([property({reflect:!0})],GlideCoreRadioGroup.prototype,"value",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isBlurring",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isReportValidityOrSubmit",void 0),GlideCoreRadioGroup=__decorate([customElement("glide-core-radio-group")],GlideCoreRadioGroup);export default GlideCoreRadioGroup;
|
@@ -12,7 +12,7 @@ it('registers', async () => {
|
|
12
12
|
expect(window.customElements.get('glide-core-radio')).to.equal(GlideCoreRadio);
|
13
13
|
});
|
14
14
|
it('is accessible', async () => {
|
15
|
-
const
|
15
|
+
const component = await fixture(html `
|
16
16
|
<glide-core-radio-group label="label" name="name" value="value-1">
|
17
17
|
<glide-core-radio value="value-1" label="One"></glide-core-radio>
|
18
18
|
<glide-core-radio value="value-2" label="Two"></glide-core-radio>
|
@@ -21,7 +21,7 @@ it('is accessible', async () => {
|
|
21
21
|
<div slot="description">Description</div>
|
22
22
|
</glide-core-radio-group>
|
23
23
|
`);
|
24
|
-
await expect(
|
24
|
+
await expect(component).to.be.accessible();
|
25
25
|
});
|
26
26
|
it('renders appropriate attributes on glide-core-radio', async () => {
|
27
27
|
await fixture(html `
|
@@ -170,7 +170,7 @@ it('sets the group "value" when a radio is set as "checked"', async () => {
|
|
170
170
|
const group = document.querySelector('glide-core-radio-group');
|
171
171
|
expect(group).to.have.attribute('value', 'value-2');
|
172
172
|
});
|
173
|
-
it('throws an error when an
|
173
|
+
it('throws an error when an component other than `glide-core-radio` is a child of the default slot', async () => {
|
174
174
|
await expectArgumentError(() => {
|
175
175
|
return fixture(html `
|
176
176
|
<glide-core-radio-group label="label" name="name">
|