Skip to content

Commit 90bbc2e

Browse files
committed
Split component, template, styles, and functionality
1 parent eca9480 commit 90bbc2e

File tree

4 files changed

+169
-156
lines changed

4 files changed

+169
-156
lines changed

aegis-modal.js

Lines changed: 5 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,9 @@
11
import { html } from '@aegisjsproject/core/parsers/html.js';
2-
import { css } from '@aegisjsproject/core/parsers/css.js';
32
import { AegisComponent } from '@aegisjsproject/component/base.js';
43
import { SYMBOLS, TRIGGERS } from '@aegisjsproject/component/consts.js';
5-
import { dark, light } from '@aegisjsproject/styles/palette/gnome.js';
6-
import { registerCallback } from '@aegisjsproject/core/callbackRegistry.js';
7-
import { EVENTS, AEGIS_EVENT_HANDLER_CLASS } from '@aegisjsproject/core/events.js';
8-
import { closeIcon } from './icons.js';
9-
10-
const inertMap = new WeakMap();
11-
12-
const tabElsSelector = 'a[href]:not([inert]), input:not([inert]), select:not([inert]), textarea:not([inert]), button:not([inert]), iframe:not([inert]), audio:not([inert]), video:not([inert]), [tabindex]:not([inert]), [contenteditable="true"]:not([inert], [is]:defined:not([inert])';
13-
14-
const getCustomElements = () => Array.from(document.querySelectorAll(':defined'))
15-
.filter(el => el.tagName.includes('-') || el.hasAttribute('is'));
16-
17-
function getOtherElements(modal) {
18-
return [
19-
...Array.from(document.body.querySelectorAll(tabElsSelector)),
20-
...getCustomElements(modal),
21-
].filter(el => ! (modal.isSameNode(el) || modal.contains(el) || el.contains(modal)));
22-
}
23-
24-
function toggleInert(modal, inert) {
25-
if (inert) {
26-
const els = getOtherElements(modal);
27-
inertMap.set(modal, els);
28-
els.forEach(el => el.inert = true);
29-
} else if (inertMap.has(modal)) {
30-
inertMap.get(modal).forEach(el => el.inert = false);
31-
inertMap.delete(modal);
32-
}
33-
}
34-
35-
const styles = css`
36-
:host(:not([open])) {
37-
display: none;
38-
}
39-
40-
:host([open]:not([theme])), :host([open][theme]) {
41-
background-color: transparent;
42-
}
43-
44-
:host([open]) {
45-
position: fixed;
46-
z-index: 2147483647;
47-
top: 0;
48-
left: 0;
49-
bottom: 0;
50-
right: 0;
51-
isolation: isolate;
52-
}
53-
54-
:host([open]) .backdrop {
55-
width: 100%;
56-
height: 100%;
57-
background-color: rgba(0, 0, 0, 0.7);
58-
display: flex;
59-
align-items: center;
60-
justify-content: center;
61-
}
62-
63-
.sticky {
64-
position: sticky;
65-
top: 0;
66-
}
67-
68-
.flex {
69-
display: flex;
70-
}
71-
72-
.flex.row {
73-
flex-direction: row;
74-
}
75-
76-
.flex.no-wrap {
77-
flex-wrap: no-wrap;
78-
}
79-
80-
.container {
81-
display: flex;
82-
min-width: 85%;
83-
max-width: 95%;
84-
min-height: 50%;
85-
max-height: 95%;
86-
overflow: auto;
87-
isolation: isolate;
88-
flex-direction: column;
89-
}
90-
91-
.header {
92-
background-color: ${dark[3]};
93-
color: ${light[1]};
94-
padding: 0.7rem;
95-
}
96-
97-
.header-container {
98-
flex-grow: 1;
99-
}
100-
101-
.close-btn {
102-
display: inline-block;
103-
width: 1.3rem;
104-
height: 1.3rem;
105-
cursor: pointer;
106-
background-color: transparent;
107-
border: none;
108-
box-sizing: content-box;
109-
color: inherit;
110-
}
111-
112-
.body {
113-
background-color: ${light[1]};
114-
color: ${dark[4]};
115-
flex-grow: 1;
116-
padding: 0.4rem;
117-
}
118-
119-
:host([theme="dark"]) .body {
120-
background-color: ${dark[2]};
121-
color: ${light[1]};
122-
}
123-
124-
@media (prefers-color-scheme: dark) {
125-
:host(:not([theme="light"])) .body {
126-
background-color: ${dark[2]};
127-
color: ${light[1]};
128-
}
129-
}
130-
`;
131-
132-
const closeHandler = registerCallback(
133-
'aegis-modal:close',
134-
event => event.target.getRootNode().host.close(),
135-
);
136-
137-
138-
const template = html`
139-
<div part="backdrop" class="backdrop">
140-
<div part="container" id="container" class="container">
141-
<div part="header" id="header" class="header sticky top flex row no-wrap">
142-
<div class="header-container">
143-
<slot name="header"></slot>
144-
</div>
145-
<button type="button" title="Close modal" ${EVENTS.onClick}="${closeHandler}" id="close" class="btn close-btn ${AEGIS_EVENT_HANDLER_CLASS}" part="btn close" aria-label="Close Modal" aria-keyshortcuts="Escape">
146-
<slot name="close-icon">X</slot>
147-
</button>
148-
</div>
149-
<div part="body" id="body" class="body">
150-
<slot id="content"></slot>
151-
</div>
152-
</div>
153-
</div>
154-
`;
4+
import { styles } from './styles.js';
5+
import { template } from './template.js';
6+
import { toggleInert, renable } from './functions.js';
1557

1568
export class AegisModalElement extends AegisComponent {
1579
#removeController;
@@ -168,7 +20,6 @@ export class AegisModalElement extends AegisComponent {
16820
internals.ariaHidden = this.open ? 'false' : 'true';
16921
internals.ariaLabel = 'Aegis Modal Dialog';
17022
internals.ariaModal = 'true';
171-
shadow.getElementById('close').replaceChildren(closeIcon.cloneNode(true));
17223
setTimeout(() => console.log(internals), 2000);
17324
this.hidden = ! this.open;
17425
break;
@@ -184,10 +35,8 @@ export class AegisModalElement extends AegisComponent {
18435
this.close();
18536
}
18637

187-
if (inertMap.has(this)) {
188-
toggleInert(this, false);
189-
inertMap.delete(this);
190-
}
38+
renable(this);
39+
19140
break;
19241

19342
case TRIGGERS.slotChanged:

functions.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const inertMap = new WeakMap();
2+
3+
const tabElsSelector = 'a[href]:not([inert]), input:not([inert]), select:not([inert]), textarea:not([inert]), button:not([inert]), iframe:not([inert]), audio:not([inert]), video:not([inert]), [tabindex]:not([inert]), [contenteditable="true"]:not([inert], [is]:defined:not([inert])';
4+
5+
const getCustomElements = () => Array.from(document.querySelectorAll(':defined'))
6+
.filter(el => el.tagName.includes('-') || el.hasAttribute('is'));
7+
8+
function getOtherElements(modal) {
9+
return [
10+
...Array.from(document.body.querySelectorAll(tabElsSelector)),
11+
...getCustomElements(modal),
12+
].filter(el => ! (modal.isSameNode(el) || modal.contains(el) || el.contains(modal)));
13+
}
14+
15+
export function toggleInert(modal, inert) {
16+
if (inert) {
17+
const els = getOtherElements(modal);
18+
inertMap.set(modal, els);
19+
els.forEach(el => el.inert = true);
20+
} else if (inertMap.has(modal)) {
21+
inertMap.get(modal).forEach(el => el.inert = false);
22+
inertMap.delete(modal);
23+
}
24+
}
25+
26+
export function renable(modal) {
27+
if (inertMap.has(modal)) {
28+
toggleInert(modal, false);
29+
inertMap.delete(modal);
30+
return true;
31+
} else {
32+
return false;
33+
}
34+
}

styles.js

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { css } from '@aegisjsproject/core/parsers/css.js';
2+
import { dark, light } from '@aegisjsproject/styles/palette/gnome.js';
3+
4+
export const styles = css`
5+
:host(:not([open])) {
6+
display: none;
7+
}
8+
9+
:host([open]:not([theme])), :host([open][theme]) {
10+
background-color: transparent;
11+
}
12+
13+
:host([open]) {
14+
position: fixed;
15+
z-index: 2147483647;
16+
top: 0;
17+
left: 0;
18+
bottom: 0;
19+
right: 0;
20+
isolation: isolate;
21+
}
22+
23+
:host([open]) .backdrop {
24+
width: 100%;
25+
height: 100%;
26+
background-color: rgba(0, 0, 0, 0.7);
27+
display: flex;
28+
align-items: center;
29+
justify-content: center;
30+
}
31+
32+
.sticky {
33+
position: sticky;
34+
top: 0;
35+
}
36+
37+
.flex {
38+
display: flex;
39+
}
40+
41+
.flex.row {
42+
flex-direction: row;
43+
}
44+
45+
.flex.no-wrap {
46+
flex-wrap: no-wrap;
47+
}
48+
49+
.container {
50+
display: flex;
51+
min-width: 85%;
52+
max-width: 95%;
53+
min-height: 50%;
54+
max-height: 95%;
55+
overflow: auto;
56+
isolation: isolate;
57+
flex-direction: column;
58+
}
59+
60+
.header {
61+
background-color: ${dark[3]};
62+
color: ${light[1]};
63+
padding: 0.7rem;
64+
}
65+
66+
.header-container {
67+
flex-grow: 1;
68+
}
69+
70+
.close-btn {
71+
display: inline-block;
72+
width: 1.3rem;
73+
height: 1.3rem;
74+
cursor: pointer;
75+
background-color: transparent;
76+
border: none;
77+
box-sizing: content-box;
78+
color: inherit;
79+
}
80+
81+
.body {
82+
background-color: ${light[1]};
83+
color: ${dark[4]};
84+
flex-grow: 1;
85+
padding: 0.4rem;
86+
}
87+
88+
:host([theme="dark"]) .body {
89+
background-color: ${dark[2]};
90+
color: ${light[1]};
91+
}
92+
93+
@media (prefers-color-scheme: dark) {
94+
:host(:not([theme="light"])) .body {
95+
background-color: ${dark[2]};
96+
color: ${light[1]};
97+
}
98+
}
99+
`;

template.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { html } from '@aegisjsproject/core/parsers/html.js';
2+
import { registerCallback } from '@aegisjsproject/core/callbackRegistry.js';
3+
import { EVENTS, AEGIS_EVENT_HANDLER_CLASS } from '@aegisjsproject/core/events.js';
4+
import { closeIcon } from './icons.js';
5+
6+
const closeHandler = registerCallback(
7+
'aegis-modal:close',
8+
event => event.target.getRootNode().host.close(),
9+
);
10+
11+
const template = html`
12+
<div part="backdrop" class="backdrop">
13+
<div part="container" id="container" class="container">
14+
<div part="header" id="header" class="header sticky top flex row no-wrap">
15+
<div class="header-container">
16+
<slot name="header"></slot>
17+
</div>
18+
<button type="button" title="Close modal" ${EVENTS.onClick}="${closeHandler}" id="close" class="btn close-btn ${AEGIS_EVENT_HANDLER_CLASS}" part="btn close" aria-label="Close Modal" aria-keyshortcuts="Escape">
19+
<slot name="close-icon">X</slot>
20+
</button>
21+
</div>
22+
<div part="body" id="body" class="body">
23+
<slot id="content"></slot>
24+
</div>
25+
</div>
26+
</div>
27+
`;
28+
29+
template.getElementById('close').replaceChildren(closeIcon.cloneNode(true));
30+
31+
export { template };

0 commit comments

Comments
 (0)