-
-
Notifications
You must be signed in to change notification settings - Fork 215
/
Copy pathShadowRoot.ts
228 lines (202 loc) · 5.73 KB
/
ShadowRoot.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
import DocumentFragment from '../document-fragment/DocumentFragment.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import XMLParser from '../../xml-parser/XMLParser.js';
import XMLSerializer from '../../xml-serializer/XMLSerializer.js';
import Element from '../element/Element.js';
import CSSStyleSheet from '../../css/CSSStyleSheet.js';
import HTMLElement from '../../nodes/html-element/HTMLElement.js';
import Event from '../../event/Event.js';
import SVGElement from '../svg-element/SVGElement.js';
/**
* ShadowRoot.
*/
export default class ShadowRoot extends DocumentFragment {
// Public properties
public declare cloneNode: (deep?: boolean) => ShadowRoot;
// Events
public onslotchange: (event: Event) => void | null = null;
// Internal properties
public [PropertySymbol.adoptedStyleSheets]: CSSStyleSheet[] = [];
public [PropertySymbol.mode] = 'open';
public [PropertySymbol.host]: Element | null = null;
public [PropertySymbol.clonable]: boolean = false;
public [PropertySymbol.delegatesFocus]: boolean = false;
public [PropertySymbol.serializable]: boolean = false;
public [PropertySymbol.slotAssignment]: 'named' | 'manual' = 'named';
/**
* Returns mode.
*
* @returns Mode.
*/
public get mode(): string {
return this[PropertySymbol.mode];
}
/**
* Returns host.
*
* @returns Host.
*/
public get host(): Element {
return this[PropertySymbol.host];
}
/**
* Returns clonable.
*
* @returns Clonable.
*/
public get clonable(): boolean {
return this[PropertySymbol.clonable];
}
/**
* Returns delegates focus.
*
* @returns Delegates focus.
*/
public get delegatesFocus(): boolean {
// TODO: Implement delegates focus
return this[PropertySymbol.delegatesFocus];
}
/**
* Returns serializable.
*
* @returns Serializable.
*/
public get serializable(): boolean {
return this[PropertySymbol.serializable];
}
/**
* Returns slot assignment.
*
* @returns Slot assignment.
*/
public get slotAssignment(): 'named' | 'manual' {
return this[PropertySymbol.slotAssignment];
}
/**
* The element that's currently in full screen mode for this shadow tree.
*
* @returns Fullscreen element.
*/
public get fullscreenElement(): Element | null {
// TODO: Implement fullscreen element
return null;
}
/**
* Returns the Element within the shadow tree that is currently being presented in picture-in-picture mode.
*
* @returns Picture-in-picture element.
*/
public get pictureInPictureElement(): Element | null {
// TODO: Implement picture-in-picture element
return null;
}
/**
* Returns the Element set as the target for mouse events while the pointer is locked. null if lock is pending, pointer is unlocked, or if the target is in another tree.
*
* @returns Pointer lock element.
*/
public get pointerLockElement(): Element | null {
// TODO: Implement pointer lock element
return null;
}
/**
* Returns inner HTML.
*
* @returns HTML.
*/
public get innerHTML(): string {
const xmlSerializer = new XMLSerializer();
let xml = '';
for (const node of this[PropertySymbol.nodeArray]) {
xml += xmlSerializer.serializeToString(node);
}
return xml;
}
/**
* Sets inner HTML.
*
* @param html HTML.
*/
public set innerHTML(html: string) {
const childNodes = this[PropertySymbol.nodeArray];
while (childNodes.length) {
this.removeChild(childNodes[0]);
}
XMLParser.parse(this[PropertySymbol.ownerDocument], html, { rootNode: this });
}
/**
* Returns adopted style sheets.
*
* @returns Adopted style sheets.
*/
public get adoptedStyleSheets(): CSSStyleSheet[] {
return this[PropertySymbol.adoptedStyleSheets];
}
/**
* Sets adopted style sheets.
*
* @param value Adopted style sheets.
*/
public set adoptedStyleSheets(value: CSSStyleSheet[]) {
this[PropertySymbol.adoptedStyleSheets] = value;
}
/**
* Returns active element.
*
* @returns Active element.
*/
public get activeElement(): HTMLElement | SVGElement | null {
const activeElement: HTMLElement | SVGElement =
this[PropertySymbol.ownerDocument][PropertySymbol.activeElement];
if (
activeElement &&
activeElement[PropertySymbol.isConnected] &&
activeElement.getRootNode() === this
) {
return activeElement;
}
return null;
}
/**
* Returns an array of all Animation objects currently in effect, whose target elements are descendants of the shadow tree.
*
* @returns Array of animations.
*/
public getAnimations(): object[] {
// TODO: Implement getAnimations()
return [];
}
/**
* Parses a string of HTML into a document fragment, without sanitization, which then replaces the shadowroot's original subtree. The HTML string may include declarative shadow roots, which would be parsed as template elements the HTML was set using ShadowRoot.innerHTML.
*
* @param html HTML.
*/
public setHTMLUnsafe(html: string): void {
// TODO: Implement support for declarative shadow roots
const childNodes = this[PropertySymbol.nodeArray];
while (childNodes.length) {
this.removeChild(childNodes[0]);
}
XMLParser.parse(this[PropertySymbol.ownerDocument], html, { rootNode: this });
}
/**
* Converts to string.
*
* @returns String.
*/
public toString(): string {
return this.innerHTML;
}
/**
* @override
*/
public override [PropertySymbol.cloneNode](deep = false): ShadowRoot {
const clone = <ShadowRoot>super[PropertySymbol.cloneNode](deep);
clone[PropertySymbol.mode] = this[PropertySymbol.mode];
clone[PropertySymbol.clonable] = this[PropertySymbol.clonable];
clone[PropertySymbol.delegatesFocus] = this[PropertySymbol.delegatesFocus];
clone[PropertySymbol.serializable] = this[PropertySymbol.serializable];
clone[PropertySymbol.slotAssignment] = this[PropertySymbol.slotAssignment];
return clone;
}
}