react-component-instance 0.0.2 → 0.0.4
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/index.d.mts +7 -7
- package/package.json +5 -3
- package/src/common/index.mjs +198 -0
- package/src/container/index.mjs +21 -16
- package/src/index.mjs +69 -63
package/index.d.mts
CHANGED
|
@@ -7,7 +7,7 @@ declare global {
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
export type FiberNode =
|
|
10
|
-
|
|
|
10
|
+
| FiberNodeForClassComponent
|
|
11
11
|
| FiberNodeForFunctionComponent
|
|
12
12
|
| FiberNodeForInstrinsicElement
|
|
13
13
|
| FiberNodeForTextNode
|
|
@@ -22,7 +22,7 @@ declare global {
|
|
|
22
22
|
stateNode: {
|
|
23
23
|
current: FiberRootNode
|
|
24
24
|
}
|
|
25
|
-
return
|
|
25
|
+
return?: FiberRootNode
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export interface FiberNodeForFunctionComponent {
|
|
@@ -33,10 +33,10 @@ declare global {
|
|
|
33
33
|
type: React.FunctionComponent
|
|
34
34
|
|
|
35
35
|
stateNode: null
|
|
36
|
-
return
|
|
36
|
+
return?: FiberNode
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
export interface
|
|
39
|
+
export interface FiberNodeForClassComponent {
|
|
40
40
|
child: FiberNode | null
|
|
41
41
|
sibling: FiberNode | null
|
|
42
42
|
|
|
@@ -44,7 +44,7 @@ declare global {
|
|
|
44
44
|
type: React.ComponentClass
|
|
45
45
|
|
|
46
46
|
stateNode: React.Component
|
|
47
|
-
return
|
|
47
|
+
return?: FiberNode
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export interface FiberNodeForInstrinsicElement {
|
|
@@ -55,7 +55,7 @@ declare global {
|
|
|
55
55
|
type: keyof React.JSX.IntrinsicElements
|
|
56
56
|
|
|
57
57
|
stateNode: HTMLElement
|
|
58
|
-
return
|
|
58
|
+
return?: FiberNode
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
export interface FiberNodeForTextNode {
|
|
@@ -66,7 +66,7 @@ declare global {
|
|
|
66
66
|
type: null
|
|
67
67
|
|
|
68
68
|
stateNode: Text
|
|
69
|
-
return
|
|
69
|
+
return?: FiberNode
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-component-instance",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Get a React class component instance from its DOM Element",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@babel/eslint-parser": "^7.26.10",
|
|
36
36
|
"@babel/preset-env": "^7.26.9",
|
|
37
37
|
"@babel/preset-react": "^7.26.3",
|
|
38
|
-
"@sequencemedia/eslint-config-standard": "^0.2.
|
|
39
|
-
"@sequencemedia/eslint-config-typescript": "^0.1.
|
|
38
|
+
"@sequencemedia/eslint-config-standard": "^0.2.43",
|
|
39
|
+
"@sequencemedia/eslint-config-typescript": "^0.1.62",
|
|
40
40
|
"@testing-library/jest-dom": "^6.6.3",
|
|
41
41
|
"@testing-library/react": "^16.2.0",
|
|
42
42
|
"@types/debug": "^4.1.12",
|
|
@@ -53,10 +53,12 @@
|
|
|
53
53
|
},
|
|
54
54
|
"imports": {
|
|
55
55
|
"#react-component-instance": "./src/index.mjs",
|
|
56
|
+
"#react-component-instance/common": "./src/common/index.mjs",
|
|
56
57
|
"#react-component-instance/container": "./src/container/index.mjs"
|
|
57
58
|
},
|
|
58
59
|
"exports": {
|
|
59
60
|
".": "./src/index.mjs",
|
|
61
|
+
"./common": "./src/common/index.mjs",
|
|
60
62
|
"./container": "./src/container/index.mjs"
|
|
61
63
|
}
|
|
62
64
|
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {ReactComponentInstanceTypes.FiberNode} FiberNode
|
|
3
|
+
* @typedef {ReactComponentInstanceTypes.FiberRootNode} FiberRootNode
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {PropertyKey} key
|
|
8
|
+
* @returns {boolean}
|
|
9
|
+
*/
|
|
10
|
+
export function isReactFiberKey (key) {
|
|
11
|
+
return String(key).startsWith('__reactFiber$')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {PropertyKey} key
|
|
16
|
+
* @returns {boolean}
|
|
17
|
+
*/
|
|
18
|
+
export function isReactPropsKey (key) {
|
|
19
|
+
return String(key).startsWith('__reactProps$')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {PropertyKey} key
|
|
24
|
+
* @returns {boolean}
|
|
25
|
+
*/
|
|
26
|
+
export function isReactContainerFiberKey (key) {
|
|
27
|
+
return String(key).startsWith('__reactContainer$')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {Element} element
|
|
32
|
+
* @returns {string | undefined}
|
|
33
|
+
*/
|
|
34
|
+
export function getReactFiberKey (element) {
|
|
35
|
+
return (
|
|
36
|
+
Object.keys(element)
|
|
37
|
+
.find(isReactFiberKey)
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {Element} element
|
|
43
|
+
* @returns {string | undefined}
|
|
44
|
+
*/
|
|
45
|
+
export function getReactPropsKey (element) {
|
|
46
|
+
return (
|
|
47
|
+
Object.keys(element)
|
|
48
|
+
.find(isReactPropsKey)
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {Element} element
|
|
54
|
+
* @returns {string | undefined}
|
|
55
|
+
*/
|
|
56
|
+
export function getReactContainerFiberKey (element) {
|
|
57
|
+
return (
|
|
58
|
+
Object.keys(element)
|
|
59
|
+
.find(isReactContainerFiberKey)
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {Element} element
|
|
65
|
+
* @returns {FiberNode | null | undefined}
|
|
66
|
+
*/
|
|
67
|
+
export function getFiberFrom (element) {
|
|
68
|
+
const key = getReactFiberKey(element)
|
|
69
|
+
|
|
70
|
+
if (key) {
|
|
71
|
+
const { // @ts-expect-error
|
|
72
|
+
[key]: fiber
|
|
73
|
+
} = element
|
|
74
|
+
|
|
75
|
+
return fiber
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
throw new Error('Fiber is not found')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {Element} element
|
|
83
|
+
* @returns {FiberNode | null | undefined}
|
|
84
|
+
*/
|
|
85
|
+
export function getParentFiberFrom (element) {
|
|
86
|
+
const key = getReactFiberKey(element)
|
|
87
|
+
|
|
88
|
+
if (key) {
|
|
89
|
+
const { // @ts-expect-error
|
|
90
|
+
[key]: {
|
|
91
|
+
return: fiber
|
|
92
|
+
}
|
|
93
|
+
} = element
|
|
94
|
+
|
|
95
|
+
return fiber
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
throw new Error('Fiber is not found')
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @param {Element} element
|
|
103
|
+
* @returns {FiberNode | null | undefined}
|
|
104
|
+
*/
|
|
105
|
+
export function getChildFiberFrom (element) {
|
|
106
|
+
const key = getReactFiberKey(element)
|
|
107
|
+
|
|
108
|
+
if (key) {
|
|
109
|
+
const { // @ts-expect-error
|
|
110
|
+
[key]: {
|
|
111
|
+
child: fiber
|
|
112
|
+
}
|
|
113
|
+
} = element
|
|
114
|
+
|
|
115
|
+
return fiber
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
throw new Error('Fiber is not found')
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param {Element} element
|
|
123
|
+
* @returns {FiberRootNode | null | undefined}
|
|
124
|
+
*/
|
|
125
|
+
export function getContainerFiberFrom (element) {
|
|
126
|
+
const key = getReactContainerFiberKey(element)
|
|
127
|
+
|
|
128
|
+
if (key) {
|
|
129
|
+
const { // @ts-expect-error
|
|
130
|
+
[key]: fiber
|
|
131
|
+
} = element
|
|
132
|
+
|
|
133
|
+
return fiber
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
throw new Error('Fiber is not found')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {FiberNode} fiber
|
|
141
|
+
* @returns {FiberNode | null | undefined}
|
|
142
|
+
*/
|
|
143
|
+
export function getParentFiber ({ return: parentFiber }) {
|
|
144
|
+
return parentFiber
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @param {FiberNode} fiber
|
|
149
|
+
* @returns {FiberNode | null | undefined}
|
|
150
|
+
*/
|
|
151
|
+
export function getChildFiber ({ child: childFiber }) {
|
|
152
|
+
return childFiber
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @param {FiberNode} fiber
|
|
157
|
+
* @returns {React.Component<any, any, any> | HTMLElement | Text | null}
|
|
158
|
+
*/
|
|
159
|
+
export function getComponentInstance ({ stateNode: instance }) {
|
|
160
|
+
return instance
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @param {(() => React.JSX.Element) | typeof React.Component} Component
|
|
165
|
+
* @param {FiberNode} fiber
|
|
166
|
+
* @returns {boolean}
|
|
167
|
+
*/
|
|
168
|
+
export function isComponentType (Component, { type }) {
|
|
169
|
+
return Component === type
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @param {(() => React.JSX.Element) | typeof React.Component} Component
|
|
174
|
+
* @returns {(fiber: FiberNode) => boolean}
|
|
175
|
+
*/
|
|
176
|
+
export function getIsComponentType (Component) {
|
|
177
|
+
return function isComponentType ({ type }) {
|
|
178
|
+
return Component === type
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @param {FiberNode} fiber
|
|
184
|
+
* @returns {Generator<FiberNode | null | undefined, null, unknown>}
|
|
185
|
+
*/
|
|
186
|
+
export function * traverseFiberParents (fiber) {
|
|
187
|
+
let currentFiber = getParentFiber(fiber)
|
|
188
|
+
|
|
189
|
+
while (currentFiber) {
|
|
190
|
+
yield currentFiber
|
|
191
|
+
|
|
192
|
+
if (currentFiber) {
|
|
193
|
+
currentFiber = getParentFiber(currentFiber)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return null
|
|
198
|
+
}
|
package/src/container/index.mjs
CHANGED
|
@@ -2,28 +2,31 @@
|
|
|
2
2
|
* @typedef {ReactComponentInstanceTypes.FiberRootNode} FiberRootNode
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import {
|
|
6
|
+
getContainerFiberFrom
|
|
7
|
+
} from '#react-component-instance/common'
|
|
8
|
+
|
|
5
9
|
/**
|
|
6
|
-
* @param {
|
|
7
|
-
* @returns {
|
|
10
|
+
* @param {Element | null | undefined} container
|
|
11
|
+
* @returns {FiberRootNode | null | undefined}
|
|
8
12
|
*/
|
|
9
|
-
function
|
|
10
|
-
|
|
13
|
+
export function getContainerFiberNodeFrom (container) {
|
|
14
|
+
if (container instanceof HTMLElement) {
|
|
15
|
+
return (
|
|
16
|
+
getContainerFiberFrom(container)
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
throw new Error('Container is not an Element')
|
|
11
21
|
}
|
|
12
22
|
|
|
13
23
|
/**
|
|
14
|
-
* @param {
|
|
24
|
+
* @param {Element | null | undefined} container
|
|
15
25
|
* @returns {React.Component<any, any, any> | HTMLElement | Text | null}
|
|
16
26
|
*/
|
|
17
|
-
export default function
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.find(isReactContainerKey)
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
if (key) {
|
|
24
|
-
const { // @ts-expect-error
|
|
25
|
-
[key]: fiberNode
|
|
26
|
-
} = container
|
|
27
|
+
export default function getComponentInstanceFrom (container) {
|
|
28
|
+
if (container instanceof HTMLElement) {
|
|
29
|
+
const fiberNode = getContainerFiberFrom(container)
|
|
27
30
|
|
|
28
31
|
if (fiberNode) {
|
|
29
32
|
const {
|
|
@@ -38,7 +41,9 @@ export default function getReactComponentInstanceFrom (container) {
|
|
|
38
41
|
|
|
39
42
|
return stateNode
|
|
40
43
|
}
|
|
44
|
+
|
|
45
|
+
throw new Error('Component instance is not found')
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
throw new Error('
|
|
48
|
+
throw new Error('Container is not an Element')
|
|
44
49
|
}
|
package/src/index.mjs
CHANGED
|
@@ -2,96 +2,102 @@
|
|
|
2
2
|
* @typedef {ReactComponentInstanceTypes.FiberNode} FiberNode
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
import {
|
|
6
|
+
getFiberFrom,
|
|
7
|
+
getParentFiberFrom,
|
|
8
|
+
getChildFiberFrom,
|
|
9
|
+
getComponentInstance,
|
|
10
|
+
isComponentType,
|
|
11
|
+
traverseFiberParents
|
|
12
|
+
} from '#react-component-instance/common'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
* @param {
|
|
15
|
-
* @
|
|
15
|
+
* @param {Element | null | undefined} element
|
|
16
|
+
* @param {(() => React.JSX.Element) | typeof React.Component} Component
|
|
17
|
+
* @returns {React.Component<any, any, any> | HTMLElement | Text | null}
|
|
16
18
|
*/
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
+
export function findComponentInstanceFor (element, Component) {
|
|
20
|
+
if (element instanceof HTMLElement) {
|
|
21
|
+
const fiber = getFiberFrom(element)
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
if (fiber) {
|
|
24
|
+
if (isComponentType(Component, fiber)) {
|
|
25
|
+
return (
|
|
26
|
+
getComponentInstance(fiber)
|
|
27
|
+
)
|
|
28
|
+
}
|
|
22
29
|
|
|
23
|
-
|
|
30
|
+
for (const parentFiber of traverseFiberParents(fiber)) {
|
|
31
|
+
if (parentFiber) {
|
|
32
|
+
if (isComponentType(Component, parentFiber)) {
|
|
33
|
+
return (
|
|
34
|
+
getComponentInstance(parentFiber)
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
throw new Error('Component instance is not found')
|
|
24
42
|
}
|
|
43
|
+
|
|
44
|
+
throw new Error('Element is not an Element')
|
|
25
45
|
}
|
|
26
46
|
|
|
27
47
|
/**
|
|
28
48
|
* @param {Element | null | undefined} element
|
|
29
|
-
* @
|
|
30
|
-
* @returns {React.Component<any, any, any> | HTMLElement | Text | null}
|
|
49
|
+
* @returns {FiberNode | null | undefined}
|
|
31
50
|
*/
|
|
32
|
-
export function
|
|
51
|
+
export function getFiberNodeFrom (element) {
|
|
33
52
|
if (element instanceof HTMLElement) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
.find(isReactFiberKey)
|
|
53
|
+
return (
|
|
54
|
+
getFiberFrom(element)
|
|
37
55
|
)
|
|
56
|
+
}
|
|
38
57
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
[key]: fiberNode
|
|
42
|
-
} = element
|
|
43
|
-
|
|
44
|
-
if (fiberNode) {
|
|
45
|
-
for (const fiber of traverseFiberNodeTree(fiberNode)) {
|
|
46
|
-
const {
|
|
47
|
-
type
|
|
48
|
-
} = fiber
|
|
58
|
+
throw new Error('Element is not an Element')
|
|
59
|
+
}
|
|
49
60
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
/**
|
|
62
|
+
* @param {Element | null | undefined} element
|
|
63
|
+
* @returns {FiberNode | null | undefined}
|
|
64
|
+
*/
|
|
65
|
+
export function getParentFiberNodeFrom (element) {
|
|
66
|
+
if (element instanceof HTMLElement) {
|
|
67
|
+
return (
|
|
68
|
+
getParentFiberFrom(element)
|
|
69
|
+
)
|
|
70
|
+
}
|
|
54
71
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
72
|
+
throw new Error('Element is not an Element')
|
|
73
|
+
}
|
|
60
74
|
|
|
61
|
-
|
|
75
|
+
/**
|
|
76
|
+
* @param {Element | null | undefined} element
|
|
77
|
+
* @returns {FiberNode | null | undefined}
|
|
78
|
+
*/
|
|
79
|
+
export function getChildFiberNodeFrom (element) {
|
|
80
|
+
if (element instanceof HTMLElement) {
|
|
81
|
+
return (
|
|
82
|
+
getChildFiberFrom(element)
|
|
83
|
+
)
|
|
62
84
|
}
|
|
63
85
|
|
|
64
86
|
throw new Error('Element is not an Element')
|
|
65
87
|
}
|
|
66
88
|
|
|
67
89
|
/**
|
|
68
|
-
* @param {Element | null} element
|
|
90
|
+
* @param {Element | null | undefined} element
|
|
69
91
|
* @returns {React.Component<any, any, any> | HTMLElement | Text | null}
|
|
70
92
|
*/
|
|
71
|
-
export default function
|
|
93
|
+
export default function getComponentInstanceFrom (element) {
|
|
72
94
|
if (element instanceof HTMLElement) {
|
|
73
|
-
const
|
|
74
|
-
Object.keys(element)
|
|
75
|
-
.find(isReactFiberKey)
|
|
76
|
-
)
|
|
95
|
+
const parentFiber = getParentFiberFrom(element)
|
|
77
96
|
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (fiberNode) {
|
|
84
|
-
/**
|
|
85
|
-
* `return` is the component which owns `element`
|
|
86
|
-
*/
|
|
87
|
-
const {
|
|
88
|
-
return: {
|
|
89
|
-
stateNode
|
|
90
|
-
}
|
|
91
|
-
} = fiberNode
|
|
92
|
-
|
|
93
|
-
return stateNode
|
|
94
|
-
}
|
|
97
|
+
if (parentFiber) {
|
|
98
|
+
return (
|
|
99
|
+
getComponentInstance(parentFiber)
|
|
100
|
+
)
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
throw new Error('Component instance is not found')
|