-
Notifications
You must be signed in to change notification settings - Fork 1
/
disclosure.ts
89 lines (69 loc) · 2.13 KB
/
disclosure.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { cancel, goodbye, hello } from 'hello-goodbye';
import { shouldOpenInNewTab } from '../utils';
export default class DisclosureElement extends HTMLElement {
static get observedAttributes() {
return ['open'];
}
public connectedCallback(): void {
this.content.hidden = !this.open;
this.button.setAttribute('aria-expanded', String(this.open));
this.button.addEventListener('click', this.onButtonClick);
}
public disconnectedCallback(): void {
cancel(this.content);
this.button.removeAttribute('aria-expanded');
this.button.removeEventListener('click', this.onButtonClick);
}
private onButtonClick = (e: MouseEvent) => {
if (!shouldOpenInNewTab(e) && !this.disabled) {
this.open = !this.open;
e.preventDefault();
}
};
get open() {
return this.hasAttribute('open');
}
set open(val) {
if (val) {
this.setAttribute('open', '');
} else {
this.removeAttribute('open');
}
}
get disabled() {
return this.hasAttribute('disabled');
}
public attributeChangedCallback(
name: string,
oldValue: string,
newValue: string
): void {
if (name !== 'open') return;
if (newValue !== null) {
this.wasOpened();
} else {
this.wasClosed();
}
}
private wasOpened() {
if (this.content.hidden) {
this.content.hidden = false;
hello(this.content);
}
this.button.setAttribute('aria-expanded', 'true');
this.dispatchEvent(new Event('toggle'));
}
private wasClosed() {
if (!this.content.hidden) {
goodbye(this.content).then(() => (this.content.hidden = true));
}
this.button.setAttribute('aria-expanded', 'false');
this.dispatchEvent(new Event('toggle'));
}
private get button(): HTMLElement {
return this.querySelector('button, [role=button]')!;
}
private get content(): HTMLElement {
return this.children[1] as HTMLElement;
}
}