-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhost-element.ts
94 lines (75 loc) · 2.44 KB
/
host-element.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
import { CONTAINER_TYPE } from "./constants";
import type { Container, Instance, TextInstance } from "./reconciler";
import type { JsonNode} from "./render-to-json";
import { renderToJson } from "./render-to-json";
export type HostNode = HostElement | string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type HostElementProps = Record<string, any>;
const instanceToHostElementMap = new WeakMap<Container | Instance, HostElement>();
export class HostElement {
private instance: Instance | Container;
private constructor(instance: Instance | Container) {
this.instance = instance;
}
get type(): string {
return this.instance.tag === "INSTANCE" ? this.instance.type : CONTAINER_TYPE;
}
get props(): HostElementProps {
if (this.instance.tag === "CONTAINER") {
return {};
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { children, ...restProps } = this.instance.props;
return restProps;
}
get children(): HostNode[] {
const result = this.instance.children
.filter((child) => !child.isHidden)
.map((child) => HostElement.fromInstance(child));
return result;
}
get parent(): HostElement | null {
const parentInstance = this.instance.parent;
if (parentInstance == null) {
return null;
}
switch (parentInstance.tag) {
case "INSTANCE":
return HostElement.fromInstance(parentInstance) as HostElement;
case "CONTAINER":
return HostElement.fromContainer(parentInstance);
}
}
get $$typeof(): symbol {
return Symbol.for("react.test.json");
}
toJSON(): JsonNode | null {
return renderToJson(this.instance);
}
/** @internal */
static fromContainer(container: Container): HostElement {
const hostElement = instanceToHostElementMap.get(container);
if (hostElement) {
return hostElement;
}
const result = new HostElement(container);
instanceToHostElementMap.set(container, result);
return result;
}
/** @internal */
static fromInstance(instance: Instance | TextInstance): HostNode {
switch (instance.tag) {
case "TEXT":
return instance.text;
case "INSTANCE": {
const hostElement = instanceToHostElementMap.get(instance);
if (hostElement) {
return hostElement;
}
const result = new HostElement(instance);
instanceToHostElementMap.set(instance, result);
return result;
}
}
}
}