@internetarchive/modal-manager 2.0.4-alpha-webdev7960.1 → 2.0.5-webdev-8155.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/.editorconfig +29 -29
- package/.github/workflows/ci.yml +40 -30
- package/.github/workflows/gh-pages-main.yml +42 -42
- package/.github/workflows/pr-preview.yml +40 -40
- package/.prettierrc +4 -0
- package/.vscode/extensions.json +10 -0
- package/.vscode/tasks.json +12 -0
- package/LICENSE +661 -661
- package/README.md +139 -139
- package/custom-elements.json +170 -170
- package/demo/app-root.ts +366 -0
- package/dist/demo/app-root.d.ts +22 -0
- package/dist/demo/app-root.js +338 -0
- package/dist/demo/app-root.js.map +1 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.js +5 -5
- package/dist/src/assets/arrow-left-icon.d.ts +2 -2
- package/dist/src/assets/arrow-left-icon.js +2 -2
- package/dist/src/assets/ia-logo-icon.d.ts +2 -2
- package/dist/src/assets/ia-logo-icon.js +2 -2
- package/dist/src/modal-config.d.ts +104 -104
- package/dist/src/modal-config.js +23 -24
- package/dist/src/modal-config.js.map +1 -1
- package/dist/src/modal-manager-host-bridge-interface.d.ts +12 -12
- package/dist/src/modal-manager-host-bridge-interface.js +1 -1
- package/dist/src/modal-manager-host-bridge.d.ts +34 -34
- package/dist/src/modal-manager-host-bridge.js +62 -62
- package/dist/src/modal-manager-host-bridge.js.map +1 -1
- package/dist/src/modal-manager-interface.d.ts +27 -27
- package/dist/src/modal-manager-interface.js +1 -1
- package/dist/src/modal-manager-mode.d.ts +10 -10
- package/dist/src/modal-manager-mode.js +11 -11
- package/dist/src/modal-manager.d.ts +137 -137
- package/dist/src/modal-manager.js +206 -212
- package/dist/src/modal-manager.js.map +1 -1
- package/dist/src/modal-template.d.ts +41 -41
- package/dist/src/modal-template.js +119 -118
- package/dist/src/modal-template.js.map +1 -1
- package/dist/src/shoelace/active-elements.d.ts +15 -15
- package/dist/src/shoelace/active-elements.js +28 -27
- package/dist/src/shoelace/active-elements.js.map +1 -1
- package/dist/src/shoelace/modal.d.ts +24 -24
- package/dist/src/shoelace/modal.js +130 -131
- package/dist/src/shoelace/modal.js.map +1 -1
- package/dist/src/shoelace/tabbable.d.ts +9 -9
- package/dist/src/shoelace/tabbable.js +168 -169
- package/dist/src/shoelace/tabbable.js.map +1 -1
- package/dist/test/modal-config.test.d.ts +1 -1
- package/dist/test/modal-config.test.js +68 -69
- package/dist/test/modal-config.test.js.map +1 -1
- package/dist/test/modal-manager.test.d.ts +1 -1
- package/dist/test/modal-manager.test.js +279 -282
- package/dist/test/modal-manager.test.js.map +1 -1
- package/dist/test/modal-template.test.d.ts +1 -1
- package/dist/test/modal-template.test.js +158 -167
- package/dist/test/modal-template.test.js.map +1 -1
- package/dist/vite.config.d.ts +2 -2
- package/dist/vite.config.js +22 -22
- package/dist/vitest.config.ci.d.ts +2 -0
- package/dist/vitest.config.ci.js +24 -0
- package/dist/vitest.config.ci.js.map +1 -0
- package/docs/assets/css/main.css +2678 -2678
- package/docs/classes/_src_modal_config_.modalconfig.html +429 -429
- package/docs/classes/_src_modal_manager_.modalmanager.html +7702 -7702
- package/docs/classes/_src_modal_manager_host_bridge_.modalmanagerhostbridge.html +409 -409
- package/docs/classes/_src_modal_template_.modaltemplate.html +7096 -7096
- package/docs/enums/_src_modal_manager_mode_.modalmanagermode.html +196 -196
- package/docs/globals.html +150 -150
- package/docs/index.html +252 -252
- package/docs/interfaces/_src_modal_manager_host_bridge_interface_.modalmanagerhostbridgeinterface.html +210 -210
- package/docs/interfaces/_src_modal_manager_interface_.modalmanagerinterface.html +7095 -7095
- package/docs/modules/_index_.html +208 -208
- package/docs/modules/_src_modal_config_.html +146 -146
- package/docs/modules/_src_modal_manager_.html +146 -146
- package/docs/modules/_src_modal_manager_host_bridge_.html +146 -146
- package/docs/modules/_src_modal_manager_host_bridge_interface_.html +146 -146
- package/docs/modules/_src_modal_manager_interface_.html +146 -146
- package/docs/modules/_src_modal_manager_mode_.html +146 -146
- package/docs/modules/_src_modal_template_.html +146 -146
- package/docs/modules/_test_modal_config_test_.html +106 -106
- package/docs/modules/_test_modal_manager_test_.html +106 -106
- package/docs/modules/_test_modal_template_test_.html +106 -106
- package/eslint.config.mjs +53 -0
- package/index.html +33 -300
- package/package.json +73 -85
- package/renovate.json +7 -7
- package/src/modal-config.ts +14 -14
- package/src/modal-manager-host-bridge.ts +2 -2
- package/src/modal-manager.ts +3 -3
- package/src/modal-template.ts +4 -2
- package/src/shoelace/LICENSE.md +6 -6
- package/src/shoelace/active-elements.ts +3 -2
- package/src/shoelace/modal.ts +5 -5
- package/src/shoelace/tabbable.ts +4 -3
- package/test/modal-config.test.ts +4 -4
- package/test/modal-manager.test.ts +33 -24
- package/test/modal-template.test.ts +42 -35
- package/tsconfig.json +25 -21
- package/vitest.config.ci.ts +27 -0
- package/.eslintrc.js +0 -14
- package/karma.conf.js +0 -24
|
@@ -1,310 +1,307 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { html } from 'lit';
|
|
4
|
-
import '../src/modal-manager';
|
|
5
|
-
import { ModalConfig } from '../src/modal-config';
|
|
6
|
-
import { ModalManagerMode } from '../src/modal-manager-mode';
|
|
7
|
-
import { getTabbableElements } from '../src/shoelace/tabbable';
|
|
8
|
-
describe('Modal Manager', () => {
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { fixture, oneEvent, elementUpdated, nextFrame, fixtureCleanup, } from '@open-wc/testing-helpers';
|
|
2
|
+
import { describe, test, expect, afterEach } from 'vitest';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
import '../src/modal-manager';
|
|
5
|
+
import { ModalConfig } from '../src/modal-config';
|
|
6
|
+
import { ModalManagerMode } from '../src/modal-manager-mode';
|
|
7
|
+
import { getTabbableElements } from '../src/shoelace/tabbable';
|
|
8
|
+
describe('Modal Manager', () => {
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
fixtureCleanup();
|
|
11
|
+
});
|
|
12
|
+
test('defaults to closed', async () => {
|
|
13
|
+
const el = (await fixture(html `
|
|
11
14
|
<modal-manager></modal-manager>
|
|
12
|
-
`));
|
|
13
|
-
expect(el.mode).to.equal('closed');
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
const el = (
|
|
15
|
+
`));
|
|
16
|
+
expect(el.mode).to.equal('closed');
|
|
17
|
+
});
|
|
18
|
+
test('can be closed by calling closeModal', async () => {
|
|
19
|
+
const el = (await fixture(html `
|
|
17
20
|
<modal-manager .mode=${ModalManagerMode.Open}></modal-manager>
|
|
18
|
-
`));
|
|
19
|
-
el.customModalContent = 'foo';
|
|
20
|
-
|
|
21
|
-
expect(el.customModalContent).to.equal('foo');
|
|
22
|
-
el.closeModal();
|
|
23
|
-
|
|
24
|
-
expect(el.mode).to.equal('closed');
|
|
25
|
-
expect(el.customModalContent).to.equal(undefined);
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const el = (yield fixture(html `
|
|
21
|
+
`));
|
|
22
|
+
el.customModalContent = 'foo';
|
|
23
|
+
await elementUpdated(el);
|
|
24
|
+
expect(el.customModalContent).to.equal('foo');
|
|
25
|
+
el.closeModal();
|
|
26
|
+
await elementUpdated(el);
|
|
27
|
+
expect(el.mode).to.equal('closed');
|
|
28
|
+
expect(el.customModalContent).to.equal(undefined);
|
|
29
|
+
});
|
|
30
|
+
test('can be closed by clicking on the backdrop', async () => {
|
|
31
|
+
const el = (await fixture(html `
|
|
30
32
|
<modal-manager .mode=${ModalManagerMode.Open}></modal-manager>
|
|
31
|
-
`));
|
|
32
|
-
const backdrop =
|
|
33
|
-
const clickEvent = new MouseEvent('click');
|
|
34
|
-
backdrop
|
|
35
|
-
|
|
36
|
-
expect(el.mode).to.equal('closed');
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
const el = (
|
|
33
|
+
`));
|
|
34
|
+
const backdrop = el.shadowRoot?.querySelector('.backdrop');
|
|
35
|
+
const clickEvent = new MouseEvent('click');
|
|
36
|
+
backdrop?.dispatchEvent(clickEvent);
|
|
37
|
+
await elementUpdated(el);
|
|
38
|
+
expect(el.mode).to.equal('closed');
|
|
39
|
+
});
|
|
40
|
+
test('emits a modeChanged event when opening', async () => {
|
|
41
|
+
const el = (await fixture(html `
|
|
40
42
|
<modal-manager></modal-manager>
|
|
41
|
-
`));
|
|
42
|
-
const config = new ModalConfig();
|
|
43
|
-
setTimeout(() => {
|
|
44
|
-
el.showModal({ config });
|
|
45
|
-
});
|
|
46
|
-
const response =
|
|
47
|
-
expect(response.detail.mode).to.equal(ModalManagerMode.Open);
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
const el = (
|
|
43
|
+
`));
|
|
44
|
+
const config = new ModalConfig();
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
el.showModal({ config });
|
|
47
|
+
});
|
|
48
|
+
const response = await oneEvent(el, 'modeChanged');
|
|
49
|
+
expect(response.detail.mode).to.equal(ModalManagerMode.Open);
|
|
50
|
+
});
|
|
51
|
+
test('emits a modeChanged event when closing', async () => {
|
|
52
|
+
const el = (await fixture(html `
|
|
51
53
|
<modal-manager></modal-manager>
|
|
52
|
-
`));
|
|
53
|
-
const config = new ModalConfig();
|
|
54
|
-
el.showModal({ config });
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
`));
|
|
55
|
+
const config = new ModalConfig();
|
|
56
|
+
await el.showModal({ config });
|
|
57
|
+
await elementUpdated(el);
|
|
58
|
+
await nextFrame();
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
el.closeModal();
|
|
61
|
+
});
|
|
62
|
+
const response = await oneEvent(el, 'modeChanged');
|
|
63
|
+
expect(response.detail.mode).to.equal(ModalManagerMode.Closed);
|
|
64
|
+
});
|
|
65
|
+
test('can show a modal', async () => {
|
|
66
|
+
const el = (await fixture(html `
|
|
64
67
|
<modal-manager></modal-manager>
|
|
65
|
-
`));
|
|
66
|
-
const config = new ModalConfig();
|
|
67
|
-
el.showModal({ config });
|
|
68
|
-
|
|
69
|
-
expect(el.mode).to.equal(ModalManagerMode.Open);
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
const el = (
|
|
68
|
+
`));
|
|
69
|
+
const config = new ModalConfig();
|
|
70
|
+
el.showModal({ config });
|
|
71
|
+
await elementUpdated(el);
|
|
72
|
+
expect(el.mode).to.equal(ModalManagerMode.Open);
|
|
73
|
+
});
|
|
74
|
+
test('sets the --containerHeight CSS property when the window resizes', async () => {
|
|
75
|
+
const el = (await fixture(html `
|
|
73
76
|
<modal-manager></modal-manager>
|
|
74
|
-
`));
|
|
75
|
-
const config = new ModalConfig();
|
|
76
|
-
el.showModal({ config });
|
|
77
|
-
|
|
78
|
-
const event = new Event('resize');
|
|
79
|
-
const propBefore = el.style.getPropertyValue('--containerHeight');
|
|
80
|
-
expect(propBefore).to.equal('');
|
|
81
|
-
window.dispatchEvent(event);
|
|
82
|
-
|
|
83
|
-
const propAfter = el.style.getPropertyValue('--containerHeight');
|
|
84
|
-
expect(propAfter).to.not.equal('');
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const el = (yield fixture(html `
|
|
77
|
+
`));
|
|
78
|
+
const config = new ModalConfig();
|
|
79
|
+
el.showModal({ config });
|
|
80
|
+
await elementUpdated(el);
|
|
81
|
+
const event = new Event('resize');
|
|
82
|
+
const propBefore = el.style.getPropertyValue('--containerHeight');
|
|
83
|
+
expect(propBefore).to.equal('');
|
|
84
|
+
window.dispatchEvent(event);
|
|
85
|
+
await elementUpdated(el);
|
|
86
|
+
const propAfter = el.style.getPropertyValue('--containerHeight');
|
|
87
|
+
expect(propAfter).to.not.equal('');
|
|
88
|
+
});
|
|
89
|
+
test('calls the userClosedModalCallback when the user taps the backdrop', async () => {
|
|
90
|
+
const el = (await fixture(html `
|
|
89
91
|
<modal-manager></modal-manager>
|
|
90
|
-
`));
|
|
91
|
-
const config = new ModalConfig();
|
|
92
|
-
let callbackCalled = false;
|
|
93
|
-
const callback = () => {
|
|
94
|
-
callbackCalled = true;
|
|
95
|
-
};
|
|
96
|
-
el.showModal({
|
|
97
|
-
config,
|
|
98
|
-
userClosedModalCallback: callback,
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const backdrop =
|
|
102
|
-
const clickEvent = new MouseEvent('click');
|
|
103
|
-
backdrop
|
|
104
|
-
|
|
105
|
-
expect(callbackCalled).to.equal(true);
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
const el = (
|
|
92
|
+
`));
|
|
93
|
+
const config = new ModalConfig();
|
|
94
|
+
let callbackCalled = false;
|
|
95
|
+
const callback = () => {
|
|
96
|
+
callbackCalled = true;
|
|
97
|
+
};
|
|
98
|
+
el.showModal({
|
|
99
|
+
config,
|
|
100
|
+
userClosedModalCallback: callback,
|
|
101
|
+
});
|
|
102
|
+
await elementUpdated(el);
|
|
103
|
+
const backdrop = el.shadowRoot?.querySelector('.backdrop');
|
|
104
|
+
const clickEvent = new MouseEvent('click');
|
|
105
|
+
backdrop?.dispatchEvent(clickEvent);
|
|
106
|
+
await elementUpdated(el);
|
|
107
|
+
expect(callbackCalled).to.equal(true);
|
|
108
|
+
});
|
|
109
|
+
test('does not call the userClosedModalCallback when the modal just closes', async () => {
|
|
110
|
+
const el = (await fixture(html `
|
|
109
111
|
<modal-manager></modal-manager>
|
|
110
|
-
`));
|
|
111
|
-
const config = new ModalConfig();
|
|
112
|
-
let callbackCalled = false;
|
|
113
|
-
const callback = () => {
|
|
114
|
-
callbackCalled = true;
|
|
115
|
-
};
|
|
116
|
-
el.showModal({
|
|
117
|
-
config,
|
|
118
|
-
userClosedModalCallback: callback,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
el.closeModal();
|
|
122
|
-
|
|
123
|
-
expect(callbackCalled).to.equal(false);
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const el = (yield fixture(html `
|
|
112
|
+
`));
|
|
113
|
+
const config = new ModalConfig();
|
|
114
|
+
let callbackCalled = false;
|
|
115
|
+
const callback = () => {
|
|
116
|
+
callbackCalled = true;
|
|
117
|
+
};
|
|
118
|
+
el.showModal({
|
|
119
|
+
config,
|
|
120
|
+
userClosedModalCallback: callback,
|
|
121
|
+
});
|
|
122
|
+
await elementUpdated(el);
|
|
123
|
+
el.closeModal();
|
|
124
|
+
await elementUpdated(el);
|
|
125
|
+
expect(callbackCalled).to.equal(false);
|
|
126
|
+
});
|
|
127
|
+
test('calls the userPressedLeftNavButtonCallback when the user clicks the left nav button', async () => {
|
|
128
|
+
const el = (await fixture(html `
|
|
128
129
|
<modal-manager></modal-manager>
|
|
129
|
-
`));
|
|
130
|
-
const config = new ModalConfig();
|
|
131
|
-
config.showLeftNavButton = true;
|
|
132
|
-
let callbackCalled = false;
|
|
133
|
-
const callback = () => {
|
|
134
|
-
callbackCalled = true;
|
|
135
|
-
};
|
|
136
|
-
el.showModal({
|
|
137
|
-
config,
|
|
138
|
-
userPressedLeftNavButtonCallback: callback,
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const modalTemplate =
|
|
142
|
-
expect(modalTemplate).to.exist;
|
|
143
|
-
modalTemplate
|
|
144
|
-
|
|
145
|
-
expect(callbackCalled).to.equal(true);
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const el = (yield fixture(html `
|
|
130
|
+
`));
|
|
131
|
+
const config = new ModalConfig();
|
|
132
|
+
config.showLeftNavButton = true;
|
|
133
|
+
let callbackCalled = false;
|
|
134
|
+
const callback = () => {
|
|
135
|
+
callbackCalled = true;
|
|
136
|
+
};
|
|
137
|
+
el.showModal({
|
|
138
|
+
config,
|
|
139
|
+
userPressedLeftNavButtonCallback: callback,
|
|
140
|
+
});
|
|
141
|
+
await elementUpdated(el);
|
|
142
|
+
const modalTemplate = el.shadowRoot?.querySelector('modal-template');
|
|
143
|
+
expect(modalTemplate).to.exist;
|
|
144
|
+
modalTemplate?.dispatchEvent(new Event('leftNavButtonPressed'));
|
|
145
|
+
await elementUpdated(el);
|
|
146
|
+
expect(callbackCalled).to.equal(true);
|
|
147
|
+
});
|
|
148
|
+
test('mode is set to closed when close button is pressed', async () => {
|
|
149
|
+
const el = (await fixture(html `
|
|
150
150
|
<modal-manager></modal-manager>
|
|
151
|
-
`));
|
|
152
|
-
const config = new ModalConfig();
|
|
153
|
-
el.showModal({ config });
|
|
154
|
-
|
|
155
|
-
expect(el.mode).to.equal('open');
|
|
156
|
-
const modal =
|
|
157
|
-
const closeButton =
|
|
158
|
-
const clickEvent = new MouseEvent('click');
|
|
159
|
-
closeButton
|
|
160
|
-
|
|
161
|
-
expect(el.mode).to.equal('closed');
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const el = (yield fixture(html `
|
|
151
|
+
`));
|
|
152
|
+
const config = new ModalConfig();
|
|
153
|
+
el.showModal({ config });
|
|
154
|
+
await elementUpdated(el);
|
|
155
|
+
expect(el.mode).to.equal('open');
|
|
156
|
+
const modal = el.shadowRoot?.querySelector('modal-template');
|
|
157
|
+
const closeButton = modal?.shadowRoot?.querySelector('.close-button');
|
|
158
|
+
const clickEvent = new MouseEvent('click');
|
|
159
|
+
closeButton?.dispatchEvent(clickEvent);
|
|
160
|
+
await elementUpdated(el);
|
|
161
|
+
expect(el.mode).to.equal('closed');
|
|
162
|
+
});
|
|
163
|
+
test('mode is set to closed when close button gets spacebar pressed', async () => {
|
|
164
|
+
const el = (await fixture(html `
|
|
166
165
|
<modal-manager></modal-manager>
|
|
167
|
-
`));
|
|
168
|
-
const config = new ModalConfig();
|
|
169
|
-
el.showModal({ config });
|
|
170
|
-
|
|
171
|
-
expect(el.mode).to.equal('open');
|
|
172
|
-
const modal =
|
|
173
|
-
const closeButton =
|
|
174
|
-
// Close with keyboard
|
|
175
|
-
const spacebarEvent = new KeyboardEvent('keydown', { key: ' ' });
|
|
176
|
-
closeButton
|
|
177
|
-
|
|
178
|
-
expect(el.mode).to.equal('closed');
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const el = (yield fixture(html `
|
|
166
|
+
`));
|
|
167
|
+
const config = new ModalConfig();
|
|
168
|
+
el.showModal({ config });
|
|
169
|
+
await elementUpdated(el);
|
|
170
|
+
expect(el.mode).to.equal('open');
|
|
171
|
+
const modal = el.shadowRoot?.querySelector('modal-template');
|
|
172
|
+
const closeButton = modal?.shadowRoot?.querySelector('.close-button');
|
|
173
|
+
// Close with keyboard
|
|
174
|
+
const spacebarEvent = new KeyboardEvent('keydown', { key: ' ' });
|
|
175
|
+
closeButton?.dispatchEvent(spacebarEvent);
|
|
176
|
+
await elementUpdated(el);
|
|
177
|
+
expect(el.mode).to.equal('closed');
|
|
178
|
+
});
|
|
179
|
+
test('mode remains open when close button gets non-button keypress', async () => {
|
|
180
|
+
const el = (await fixture(html `
|
|
183
181
|
<modal-manager></modal-manager>
|
|
184
|
-
`));
|
|
185
|
-
const config = new ModalConfig();
|
|
186
|
-
el.showModal({ config });
|
|
187
|
-
|
|
188
|
-
expect(el.mode).to.equal('open');
|
|
189
|
-
const modal =
|
|
190
|
-
const closeButton =
|
|
191
|
-
// Close with keyboard
|
|
192
|
-
const keyboardEvent = new KeyboardEvent('keydown', { key: '.' });
|
|
193
|
-
closeButton
|
|
194
|
-
|
|
195
|
-
expect(el.mode).to.equal('open');
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const el = (yield fixture(html `
|
|
182
|
+
`));
|
|
183
|
+
const config = new ModalConfig();
|
|
184
|
+
el.showModal({ config });
|
|
185
|
+
await elementUpdated(el);
|
|
186
|
+
expect(el.mode).to.equal('open');
|
|
187
|
+
const modal = el.shadowRoot?.querySelector('modal-template');
|
|
188
|
+
const closeButton = modal?.shadowRoot?.querySelector('.close-button');
|
|
189
|
+
// Close with keyboard
|
|
190
|
+
const keyboardEvent = new KeyboardEvent('keydown', { key: '.' });
|
|
191
|
+
closeButton?.dispatchEvent(keyboardEvent);
|
|
192
|
+
await elementUpdated(el);
|
|
193
|
+
expect(el.mode).to.equal('open');
|
|
194
|
+
});
|
|
195
|
+
test('allows the user to close by clicking on the backdrop if configured to', async () => {
|
|
196
|
+
const el = (await fixture(html `
|
|
200
197
|
<modal-manager></modal-manager>
|
|
201
|
-
`));
|
|
202
|
-
const config = new ModalConfig();
|
|
203
|
-
config.closeOnBackdropClick = true;
|
|
204
|
-
el.showModal({ config });
|
|
205
|
-
|
|
206
|
-
const backdrop =
|
|
207
|
-
const clickEvent = new MouseEvent('click');
|
|
208
|
-
backdrop
|
|
209
|
-
|
|
210
|
-
expect(el.mode).to.equal('closed');
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const el = (yield fixture(html `
|
|
198
|
+
`));
|
|
199
|
+
const config = new ModalConfig();
|
|
200
|
+
config.closeOnBackdropClick = true;
|
|
201
|
+
el.showModal({ config });
|
|
202
|
+
await elementUpdated(el);
|
|
203
|
+
const backdrop = el.shadowRoot?.querySelector('.backdrop');
|
|
204
|
+
const clickEvent = new MouseEvent('click');
|
|
205
|
+
backdrop?.dispatchEvent(clickEvent);
|
|
206
|
+
await elementUpdated(el);
|
|
207
|
+
expect(el.mode).to.equal('closed');
|
|
208
|
+
});
|
|
209
|
+
test("doesn't allow the user to close by clicking on the backdrop if configured to", async () => {
|
|
210
|
+
const el = (await fixture(html `
|
|
215
211
|
<modal-manager></modal-manager>
|
|
216
|
-
`));
|
|
217
|
-
const config = new ModalConfig();
|
|
218
|
-
config.closeOnBackdropClick = false;
|
|
219
|
-
el.showModal({ config });
|
|
220
|
-
|
|
221
|
-
const backdrop =
|
|
222
|
-
const clickEvent = new MouseEvent('click');
|
|
223
|
-
backdrop
|
|
224
|
-
|
|
225
|
-
expect(el.getMode()).to.equal('open');
|
|
226
|
-
})
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const el = (yield fixture(html `
|
|
212
|
+
`));
|
|
213
|
+
const config = new ModalConfig();
|
|
214
|
+
config.closeOnBackdropClick = false;
|
|
215
|
+
el.showModal({ config });
|
|
216
|
+
await elementUpdated(el);
|
|
217
|
+
const backdrop = el.shadowRoot?.querySelector('.backdrop');
|
|
218
|
+
const clickEvent = new MouseEvent('click');
|
|
219
|
+
backdrop?.dispatchEvent(clickEvent);
|
|
220
|
+
await elementUpdated(el);
|
|
221
|
+
expect(el.getMode()).to.equal('open');
|
|
222
|
+
});
|
|
223
|
+
test('ia logo should not visible on modal', async () => {
|
|
224
|
+
const el = (await fixture(html `
|
|
230
225
|
<modal-manager></modal-manager>
|
|
231
|
-
`));
|
|
232
|
-
const config = new ModalConfig();
|
|
233
|
-
config.showHeaderLogo = false;
|
|
234
|
-
el.showModal({ config });
|
|
235
|
-
|
|
236
|
-
const logoIcon =
|
|
237
|
-
expect(logoIcon).to.not.exist;
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const el = (yield fixture(html `
|
|
226
|
+
`));
|
|
227
|
+
const config = new ModalConfig();
|
|
228
|
+
config.showHeaderLogo = false;
|
|
229
|
+
el.showModal({ config });
|
|
230
|
+
await elementUpdated(el);
|
|
231
|
+
const logoIcon = el.shadowRoot?.querySelector('.logo-icon');
|
|
232
|
+
expect(logoIcon).to.not.exist;
|
|
233
|
+
});
|
|
234
|
+
test('should trap Tab key', async () => {
|
|
235
|
+
const el = (await fixture(html `
|
|
242
236
|
<modal-manager></modal-manager>
|
|
243
|
-
`));
|
|
244
|
-
const config = new ModalConfig();
|
|
245
|
-
el.showModal({ config });
|
|
246
|
-
|
|
247
|
-
expect(el.mode).to.equal('open');
|
|
248
|
-
// Tab once to focus
|
|
249
|
-
const tabEvent = new KeyboardEvent('keydown', { key: 'Tab' });
|
|
250
|
-
document.dispatchEvent(tabEvent);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
237
|
+
`));
|
|
238
|
+
const config = new ModalConfig();
|
|
239
|
+
el.showModal({ config });
|
|
240
|
+
await elementUpdated(el);
|
|
241
|
+
expect(el.mode).to.equal('open');
|
|
242
|
+
// Tab once to focus
|
|
243
|
+
const tabEvent = new KeyboardEvent('keydown', { key: 'Tab' });
|
|
244
|
+
document.dispatchEvent(tabEvent);
|
|
245
|
+
await elementUpdated(el);
|
|
246
|
+
await nextFrame();
|
|
247
|
+
// Should be only one tabbable element
|
|
248
|
+
const modal = el.shadowRoot?.querySelector('modal-template');
|
|
249
|
+
const tabbableElements = getTabbableElements(modal);
|
|
250
|
+
expect(tabbableElements?.length).to.equal(1);
|
|
251
|
+
const closeButton = modal?.shadowRoot?.querySelector('.close-button');
|
|
252
|
+
expect(modal?.shadowRoot?.activeElement).to.equal(closeButton);
|
|
253
|
+
// Tab again
|
|
254
|
+
el.dispatchEvent(tabEvent);
|
|
255
|
+
await elementUpdated(el);
|
|
256
|
+
await nextFrame();
|
|
257
|
+
// Should be only one tabbable element
|
|
258
|
+
expect(modal?.shadowRoot?.activeElement).to.equal(closeButton);
|
|
259
|
+
// Shift + Tab
|
|
260
|
+
const shiftTabEvent = new KeyboardEvent('keydown', {
|
|
261
|
+
key: 'Tab',
|
|
262
|
+
shiftKey: true,
|
|
263
|
+
});
|
|
264
|
+
document.dispatchEvent(shiftTabEvent);
|
|
265
|
+
await elementUpdated(el);
|
|
266
|
+
await nextFrame();
|
|
267
|
+
// Should be only one tabbable element
|
|
268
|
+
expect(modal?.shadowRoot?.activeElement).to.equal(closeButton);
|
|
269
|
+
});
|
|
270
|
+
test('returns keyboard focus to the triggering element on close', async () => {
|
|
271
|
+
const config = new ModalConfig();
|
|
272
|
+
const el = (await fixture(html `
|
|
276
273
|
<div>
|
|
277
274
|
<button>Another button</button>
|
|
278
275
|
<button
|
|
279
276
|
id="open-modal-btn"
|
|
280
|
-
@click=${() => {
|
|
281
|
-
const modal = el.querySelector('modal-manager');
|
|
282
|
-
modal.showModal({ config });
|
|
277
|
+
@click=${() => {
|
|
278
|
+
const modal = el.querySelector('modal-manager');
|
|
279
|
+
modal.showModal({ config });
|
|
283
280
|
}}
|
|
284
281
|
>
|
|
285
282
|
Open modal
|
|
286
283
|
</button>
|
|
287
284
|
<modal-manager></modal-manager>
|
|
288
285
|
</div>
|
|
289
|
-
`));
|
|
290
|
-
const openBtn = el.querySelector('#open-modal-btn');
|
|
291
|
-
const modal = el.querySelector('modal-manager');
|
|
292
|
-
// Focus is initially on the Open button
|
|
293
|
-
openBtn.focus();
|
|
294
|
-
expect(document.activeElement).to.equal(openBtn);
|
|
295
|
-
// Focus enters the modal when it is opened
|
|
296
|
-
openBtn.click();
|
|
297
|
-
|
|
298
|
-
expect(document.activeElement).to.equal(modal);
|
|
299
|
-
// With the modal already open, simulate showing different content.
|
|
300
|
-
// This step is to ensure that even if showModal is called multiple times, we still
|
|
301
|
-
// maintain the originally-focused element (subsequent calls do not overwrite it).
|
|
302
|
-
modal.showModal({ config: new ModalConfig() });
|
|
303
|
-
|
|
304
|
-
// Focus returns to the Open button when the modal closes
|
|
305
|
-
modal.closeModal();
|
|
306
|
-
|
|
307
|
-
expect(document.activeElement).to.equal(openBtn);
|
|
308
|
-
})
|
|
309
|
-
});
|
|
286
|
+
`));
|
|
287
|
+
const openBtn = el.querySelector('#open-modal-btn');
|
|
288
|
+
const modal = el.querySelector('modal-manager');
|
|
289
|
+
// Focus is initially on the Open button
|
|
290
|
+
openBtn.focus();
|
|
291
|
+
expect(document.activeElement).to.equal(openBtn);
|
|
292
|
+
// Focus enters the modal when it is opened
|
|
293
|
+
openBtn.click();
|
|
294
|
+
await nextFrame();
|
|
295
|
+
expect(document.activeElement).to.equal(modal);
|
|
296
|
+
// With the modal already open, simulate showing different content.
|
|
297
|
+
// This step is to ensure that even if showModal is called multiple times, we still
|
|
298
|
+
// maintain the originally-focused element (subsequent calls do not overwrite it).
|
|
299
|
+
modal.showModal({ config: new ModalConfig() });
|
|
300
|
+
await nextFrame();
|
|
301
|
+
// Focus returns to the Open button when the modal closes
|
|
302
|
+
modal.closeModal();
|
|
303
|
+
await modal.updateComplete;
|
|
304
|
+
expect(document.activeElement).to.equal(openBtn);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
310
307
|
//# sourceMappingURL=modal-manager.test.js.map
|