@contember/react-multipass-rendering 1.0.0-rc.2 → 1.0.0-rc.22
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/dist/types/BranchNodeList.d.ts +3 -0
- package/dist/types/BranchNodeList.d.ts.map +1 -0
- package/dist/types/ChildrenAnalyzer.d.ts +15 -0
- package/dist/types/ChildrenAnalyzer.d.ts.map +1 -0
- package/dist/types/ChildrenAnalyzerError.d.ts +3 -0
- package/dist/types/ChildrenAnalyzerError.d.ts.map +1 -0
- package/dist/types/ChildrenAnalyzerOptions.d.ts +10 -0
- package/dist/types/ChildrenAnalyzerOptions.d.ts.map +1 -0
- package/dist/types/ErrorMessageFactory.d.ts +3 -0
- package/dist/types/ErrorMessageFactory.d.ts.map +1 -0
- package/dist/types/LeafList.d.ts +3 -0
- package/dist/types/LeafList.d.ts.map +1 -0
- package/dist/types/assertNever.d.ts +2 -0
- package/dist/types/assertNever.d.ts.map +1 -0
- package/dist/types/helpers/getErrorMessage.d.ts +4 -0
- package/dist/types/helpers/getErrorMessage.d.ts.map +1 -0
- package/dist/types/helpers/index.d.ts +2 -0
- package/dist/types/helpers/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/nodeSpecs/BranchNode.d.ts +23 -0
- package/dist/types/nodeSpecs/BranchNode.d.ts.map +1 -0
- package/dist/types/nodeSpecs/BranchNodeOptions.d.ts +5 -0
- package/dist/types/nodeSpecs/BranchNodeOptions.d.ts.map +1 -0
- package/dist/types/nodeSpecs/Leaf.d.ts +20 -0
- package/dist/types/nodeSpecs/Leaf.d.ts.map +1 -0
- package/dist/types/nodeSpecs/RawNodeRepresentation.d.ts +2 -0
- package/dist/types/nodeSpecs/RawNodeRepresentation.d.ts.map +1 -0
- package/dist/types/nodeSpecs/index.d.ts +6 -0
- package/dist/types/nodeSpecs/index.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/ChildrenRepresentationReducer.d.ts +2 -0
- package/dist/types/nodeSpecs/types/ChildrenRepresentationReducer.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/ConstrainedLeafRepresentationFactory.d.ts +3 -0
- package/dist/types/nodeSpecs/types/ConstrainedLeafRepresentationFactory.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/DeclarationSiteNodeRepresentationFactory.d.ts +2 -0
- package/dist/types/nodeSpecs/types/DeclarationSiteNodeRepresentationFactory.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/RepresentationFactorySite.d.ts +2 -0
- package/dist/types/nodeSpecs/types/RepresentationFactorySite.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/StaticContextFactory.d.ts +2 -0
- package/dist/types/nodeSpecs/types/StaticContextFactory.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/SyntheticChildrenFactory.d.ts +3 -0
- package/dist/types/nodeSpecs/types/SyntheticChildrenFactory.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/UnconstrainedLeafRepresentationFactory.d.ts +3 -0
- package/dist/types/nodeSpecs/types/UnconstrainedLeafRepresentationFactory.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/UseSiteBranchNodeRepresentationFactory.d.ts +3 -0
- package/dist/types/nodeSpecs/types/UseSiteBranchNodeRepresentationFactory.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/ValidFactoryName.d.ts +2 -0
- package/dist/types/nodeSpecs/types/ValidFactoryName.d.ts.map +1 -0
- package/dist/types/nodeSpecs/types/index.d.ts +10 -0
- package/dist/types/nodeSpecs/types/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +5 -7
- package/src/BranchNodeList.ts +10 -0
- package/src/ChildrenAnalyzer.ts +250 -0
- package/src/ChildrenAnalyzerError.ts +1 -0
- package/src/ChildrenAnalyzerOptions.ts +12 -0
- package/src/ErrorMessageFactory.ts +5 -0
- package/src/LeafList.ts +8 -0
- package/src/assertNever.ts +3 -0
- package/src/helpers/getErrorMessage.ts +10 -0
- package/src/helpers/index.ts +1 -0
- package/src/index.ts +5 -0
- package/src/nodeSpecs/BranchNode.ts +103 -0
- package/src/nodeSpecs/BranchNodeOptions.ts +4 -0
- package/src/nodeSpecs/Leaf.ts +59 -0
- package/src/nodeSpecs/RawNodeRepresentation.ts +5 -0
- package/src/nodeSpecs/index.ts +6 -0
- package/src/nodeSpecs/types/ChildrenRepresentationReducer.ts +3 -0
- package/src/nodeSpecs/types/ConstrainedLeafRepresentationFactory.ts +6 -0
- package/src/nodeSpecs/types/DeclarationSiteNodeRepresentationFactory.ts +10 -0
- package/src/nodeSpecs/types/RepresentationFactorySite.ts +1 -0
- package/src/nodeSpecs/types/StaticContextFactory.ts +4 -0
- package/src/nodeSpecs/types/SyntheticChildrenFactory.ts +6 -0
- package/src/nodeSpecs/types/UnconstrainedLeafRepresentationFactory.ts +6 -0
- package/src/nodeSpecs/types/UseSiteBranchNodeRepresentationFactory.ts +12 -0
- package/src/nodeSpecs/types/ValidFactoryName.ts +1 -0
- package/src/nodeSpecs/types/index.ts +9 -0
- package/src/tsconfig.json +6 -0
- package/dist/react-multipass-rendering.d.ts +0 -98
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import type { ElementType, ReactNode } from 'react'
|
|
2
|
+
import { assertNever } from './assertNever'
|
|
3
|
+
import type { BranchNodeList } from './BranchNodeList'
|
|
4
|
+
import { ChildrenAnalyzerError } from './ChildrenAnalyzerError'
|
|
5
|
+
import type { ChildrenAnalyzerOptions } from './ChildrenAnalyzerOptions'
|
|
6
|
+
import { getErrorMessage } from './helpers'
|
|
7
|
+
import type { LeafList } from './LeafList'
|
|
8
|
+
import type {
|
|
9
|
+
DeclarationSiteNodeRepresentationFactory,
|
|
10
|
+
RawNodeRepresentation,
|
|
11
|
+
RepresentationFactorySite,
|
|
12
|
+
StaticContextFactory,
|
|
13
|
+
SyntheticChildrenFactory,
|
|
14
|
+
UnconstrainedLeafRepresentationFactory,
|
|
15
|
+
ValidFactoryName,
|
|
16
|
+
} from './nodeSpecs'
|
|
17
|
+
|
|
18
|
+
export class ChildrenAnalyzer<
|
|
19
|
+
AllLeavesRepresentation = any,
|
|
20
|
+
AllBranchNodesRepresentation = never,
|
|
21
|
+
StaticContext = undefined,
|
|
22
|
+
> {
|
|
23
|
+
private static defaultOptions: ChildrenAnalyzerOptions = {
|
|
24
|
+
ignoreRenderProps: true,
|
|
25
|
+
renderPropsErrorMessage: 'Render props (functions as React component children) are not supported.',
|
|
26
|
+
|
|
27
|
+
ignoreUnhandledNodes: true,
|
|
28
|
+
unhandledNodeErrorMessage: 'Encountered an unknown child.',
|
|
29
|
+
|
|
30
|
+
staticContextFactoryName: 'getStaticContext',
|
|
31
|
+
staticRenderFactoryName: 'staticRender',
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private readonly leaves: LeafList<AllLeavesRepresentation, StaticContext>
|
|
35
|
+
private readonly branchNodes: BranchNodeList<AllLeavesRepresentation, AllBranchNodesRepresentation, StaticContext>
|
|
36
|
+
private readonly options: ChildrenAnalyzerOptions<StaticContext>
|
|
37
|
+
|
|
38
|
+
public constructor(
|
|
39
|
+
leaves: LeafList<AllLeavesRepresentation, StaticContext>,
|
|
40
|
+
options?: Partial<ChildrenAnalyzerOptions>,
|
|
41
|
+
)
|
|
42
|
+
public constructor(
|
|
43
|
+
leaves: LeafList<AllLeavesRepresentation, StaticContext>,
|
|
44
|
+
branchNodes: BranchNodeList<AllLeavesRepresentation, AllBranchNodesRepresentation, StaticContext>,
|
|
45
|
+
options?: Partial<ChildrenAnalyzerOptions>,
|
|
46
|
+
)
|
|
47
|
+
public constructor(
|
|
48
|
+
leaves: LeafList<AllLeavesRepresentation, StaticContext>,
|
|
49
|
+
decider:
|
|
50
|
+
| Partial<ChildrenAnalyzerOptions>
|
|
51
|
+
| BranchNodeList<AllLeavesRepresentation, AllBranchNodesRepresentation, StaticContext> = [],
|
|
52
|
+
options: Partial<ChildrenAnalyzerOptions> = {},
|
|
53
|
+
) {
|
|
54
|
+
this.leaves = leaves
|
|
55
|
+
|
|
56
|
+
if (Array.isArray(decider)) {
|
|
57
|
+
this.branchNodes = decider
|
|
58
|
+
} else {
|
|
59
|
+
this.branchNodes = []
|
|
60
|
+
options = decider
|
|
61
|
+
}
|
|
62
|
+
this.options = { ...ChildrenAnalyzer.defaultOptions, ...options }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public processChildren(
|
|
66
|
+
children: ReactNode,
|
|
67
|
+
initialStaticContext: StaticContext,
|
|
68
|
+
): Array<AllLeavesRepresentation | AllBranchNodesRepresentation> {
|
|
69
|
+
const processed = this.processNode(children, initialStaticContext)
|
|
70
|
+
|
|
71
|
+
const rawResult: Array<AllLeavesRepresentation | AllBranchNodesRepresentation | undefined> = Array.isArray(
|
|
72
|
+
processed,
|
|
73
|
+
)
|
|
74
|
+
? processed
|
|
75
|
+
: [processed]
|
|
76
|
+
|
|
77
|
+
return rawResult.filter(
|
|
78
|
+
(item): item is AllLeavesRepresentation | AllBranchNodesRepresentation => item !== undefined,
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private processNode(
|
|
83
|
+
node: ReactNode | Function,
|
|
84
|
+
staticContext: StaticContext,
|
|
85
|
+
): RawNodeRepresentation<AllLeavesRepresentation, AllBranchNodesRepresentation> {
|
|
86
|
+
if (!node || typeof node === 'string' || typeof node === 'number' || typeof node === 'boolean') {
|
|
87
|
+
for (const leaf of this.leaves) {
|
|
88
|
+
const specification = leaf.specification
|
|
89
|
+
if (specification.type === 'useSite') {
|
|
90
|
+
const { ComponentType, factory } = specification
|
|
91
|
+
if (ComponentType === undefined) {
|
|
92
|
+
return factory(node, staticContext)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (node === false || node === undefined || node === null) {
|
|
97
|
+
// This adds seamless support for conditionals and such.
|
|
98
|
+
return undefined
|
|
99
|
+
}
|
|
100
|
+
if (!this.options.ignoreUnhandledNodes) {
|
|
101
|
+
throw new ChildrenAnalyzerError(getErrorMessage(this.options.unhandledNodeErrorMessage, node, staticContext))
|
|
102
|
+
}
|
|
103
|
+
return undefined
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (typeof node === 'function') {
|
|
107
|
+
if (this.options.ignoreRenderProps) {
|
|
108
|
+
return undefined
|
|
109
|
+
}
|
|
110
|
+
throw new ChildrenAnalyzerError(getErrorMessage(this.options.renderPropsErrorMessage, node, staticContext))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (Array.isArray(node)) {
|
|
114
|
+
let mapped: Array<AllLeavesRepresentation | AllBranchNodesRepresentation> = []
|
|
115
|
+
|
|
116
|
+
for (const subNode of node) {
|
|
117
|
+
const processed = this.processNode(subNode, staticContext)
|
|
118
|
+
|
|
119
|
+
if (processed !== undefined) {
|
|
120
|
+
if (Array.isArray(processed)) {
|
|
121
|
+
mapped = mapped.concat(processed)
|
|
122
|
+
} else {
|
|
123
|
+
mapped.push(processed)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return mapped
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let children: ReactNode = undefined
|
|
132
|
+
|
|
133
|
+
if (!('type' in node)) {
|
|
134
|
+
return this.processNode(children, staticContext)
|
|
135
|
+
}
|
|
136
|
+
children = node.props.children
|
|
137
|
+
|
|
138
|
+
if (typeof node.type === 'symbol') {
|
|
139
|
+
// Fragment, Portal or other non-component
|
|
140
|
+
return this.processNode(children, staticContext)
|
|
141
|
+
}
|
|
142
|
+
// if (typeof node.type === 'string') {
|
|
143
|
+
// // Typically a host component
|
|
144
|
+
// if (!this.options.ignoreUnhandledNodes) {
|
|
145
|
+
// throw new ChildrenAnalyzerError(getErrorMessage(this.options.unhandledNodeErrorMessage, node, staticContext))
|
|
146
|
+
// }
|
|
147
|
+
// return this.processNode(children, staticContext)
|
|
148
|
+
// }
|
|
149
|
+
|
|
150
|
+
// Component, PureComponent, FunctionComponent
|
|
151
|
+
|
|
152
|
+
const treeNode = node.type as ElementType &
|
|
153
|
+
{
|
|
154
|
+
[staticMethod in ValidFactoryName]:
|
|
155
|
+
| StaticContextFactory<any, StaticContext>
|
|
156
|
+
| SyntheticChildrenFactory<any, StaticContext>
|
|
157
|
+
| UnconstrainedLeafRepresentationFactory<any, AllLeavesRepresentation, StaticContext>
|
|
158
|
+
| DeclarationSiteNodeRepresentationFactory<any, unknown, AllBranchNodesRepresentation, StaticContext>
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (typeof treeNode !== 'string') {
|
|
162
|
+
if (this.options.staticContextFactoryName in treeNode) {
|
|
163
|
+
const staticContextFactory = treeNode[this.options.staticContextFactoryName] as StaticContextFactory<
|
|
164
|
+
any,
|
|
165
|
+
StaticContext
|
|
166
|
+
>
|
|
167
|
+
staticContext = staticContextFactory(node.props, staticContext)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (this.options.staticRenderFactoryName in treeNode) {
|
|
171
|
+
const factory = treeNode[this.options.staticRenderFactoryName] as SyntheticChildrenFactory<any, StaticContext>
|
|
172
|
+
children = factory(node.props, staticContext)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
for (const leaf of this.leaves) {
|
|
177
|
+
const specification = leaf.specification
|
|
178
|
+
switch (specification.type) {
|
|
179
|
+
case 'declarationSite': {
|
|
180
|
+
const { factoryMethodName } = specification
|
|
181
|
+
|
|
182
|
+
if (typeof treeNode !== 'string' && factoryMethodName in treeNode) {
|
|
183
|
+
const factory = treeNode[factoryMethodName] as UnconstrainedLeafRepresentationFactory<
|
|
184
|
+
any,
|
|
185
|
+
AllBranchNodesRepresentation | AllLeavesRepresentation,
|
|
186
|
+
StaticContext
|
|
187
|
+
>
|
|
188
|
+
return factory(node.props, staticContext)
|
|
189
|
+
}
|
|
190
|
+
break
|
|
191
|
+
}
|
|
192
|
+
case 'useSite': {
|
|
193
|
+
const { ComponentType, factory } = specification
|
|
194
|
+
if (ComponentType === undefined || node.type === ComponentType) {
|
|
195
|
+
return factory(node, staticContext)
|
|
196
|
+
}
|
|
197
|
+
break
|
|
198
|
+
}
|
|
199
|
+
default:
|
|
200
|
+
return assertNever(specification)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const processedChildren = this.processNode(children, staticContext)
|
|
205
|
+
|
|
206
|
+
for (const branchNode of this.branchNodes) {
|
|
207
|
+
const specification = branchNode.specification
|
|
208
|
+
switch (specification.type) {
|
|
209
|
+
case 'declarationSite': {
|
|
210
|
+
const { factoryMethodName, childrenRepresentationReducer } = specification
|
|
211
|
+
|
|
212
|
+
if (typeof treeNode !== 'string' && factoryMethodName in treeNode) {
|
|
213
|
+
if (processedChildren === undefined && !branchNode.options.childrenAreOptional) {
|
|
214
|
+
throw new ChildrenAnalyzerError(branchNode.options.childrenAbsentErrorMessage)
|
|
215
|
+
}
|
|
216
|
+
const factory = treeNode[factoryMethodName] as DeclarationSiteNodeRepresentationFactory<
|
|
217
|
+
any,
|
|
218
|
+
unknown,
|
|
219
|
+
AllBranchNodesRepresentation | AllLeavesRepresentation,
|
|
220
|
+
StaticContext
|
|
221
|
+
>
|
|
222
|
+
return factory(node.props, childrenRepresentationReducer(processedChildren), staticContext)
|
|
223
|
+
}
|
|
224
|
+
break
|
|
225
|
+
}
|
|
226
|
+
case 'useSite': {
|
|
227
|
+
const { factory, ComponentType } = specification
|
|
228
|
+
if (ComponentType === undefined || node.type === ComponentType) {
|
|
229
|
+
if (processedChildren === undefined && !branchNode.options.childrenAreOptional) {
|
|
230
|
+
throw new ChildrenAnalyzerError(branchNode.options.childrenAbsentErrorMessage)
|
|
231
|
+
}
|
|
232
|
+
return factory(node, processedChildren, staticContext)
|
|
233
|
+
}
|
|
234
|
+
break
|
|
235
|
+
}
|
|
236
|
+
default:
|
|
237
|
+
return assertNever(specification)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (
|
|
242
|
+
!this.options.ignoreUnhandledNodes &&
|
|
243
|
+
!(typeof treeNode !== 'string' && this.options.staticRenderFactoryName in treeNode)
|
|
244
|
+
) {
|
|
245
|
+
throw new ChildrenAnalyzerError(getErrorMessage(this.options.unhandledNodeErrorMessage, node, staticContext))
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return processedChildren
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class ChildrenAnalyzerError extends Error {}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ErrorMessageFactory } from './ErrorMessageFactory'
|
|
2
|
+
|
|
3
|
+
export interface ChildrenAnalyzerOptions<StaticContext = any> {
|
|
4
|
+
ignoreRenderProps: boolean
|
|
5
|
+
renderPropsErrorMessage: ErrorMessageFactory<StaticContext>
|
|
6
|
+
|
|
7
|
+
ignoreUnhandledNodes: boolean
|
|
8
|
+
unhandledNodeErrorMessage: ErrorMessageFactory<StaticContext>
|
|
9
|
+
|
|
10
|
+
staticContextFactoryName: string
|
|
11
|
+
staticRenderFactoryName: string
|
|
12
|
+
}
|
package/src/LeafList.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import type { ErrorMessageFactory } from '../ErrorMessageFactory'
|
|
3
|
+
|
|
4
|
+
export const getErrorMessage = <StaticContext>(
|
|
5
|
+
factory: ErrorMessageFactory<StaticContext>,
|
|
6
|
+
node: ReactNode,
|
|
7
|
+
staticContext: StaticContext,
|
|
8
|
+
): string => {
|
|
9
|
+
return typeof factory === 'string' ? factory : factory(node, staticContext)
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './getErrorMessage'
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { ElementType } from 'react'
|
|
2
|
+
import { ChildrenAnalyzerError } from '../ChildrenAnalyzerError'
|
|
3
|
+
import type { BranchNodeOptions } from './BranchNodeOptions'
|
|
4
|
+
import type { ChildrenRepresentationReducer, UseSiteBranchNodeRepresentationFactory, ValidFactoryName } from './types'
|
|
5
|
+
|
|
6
|
+
class BranchNode<
|
|
7
|
+
Props extends {} = {},
|
|
8
|
+
StaticContext = undefined,
|
|
9
|
+
FactoryMethodName extends ValidFactoryName = string,
|
|
10
|
+
ChildrenRepresentation = any,
|
|
11
|
+
ReducedChildrenRepresentation = any,
|
|
12
|
+
Representation = any,
|
|
13
|
+
> {
|
|
14
|
+
private static defaultOptions: BranchNodeOptions = {
|
|
15
|
+
childrenAreOptional: false,
|
|
16
|
+
childrenAbsentErrorMessage: 'Component must have children!',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public readonly specification: BranchNode.Specification<
|
|
20
|
+
Props,
|
|
21
|
+
StaticContext,
|
|
22
|
+
FactoryMethodName,
|
|
23
|
+
ChildrenRepresentation,
|
|
24
|
+
ReducedChildrenRepresentation,
|
|
25
|
+
Representation
|
|
26
|
+
>
|
|
27
|
+
|
|
28
|
+
public readonly options: BranchNodeOptions
|
|
29
|
+
|
|
30
|
+
public constructor(
|
|
31
|
+
factoryMethodName: FactoryMethodName,
|
|
32
|
+
childrenRepresentationReducer: ChildrenRepresentationReducer<ChildrenRepresentation, ReducedChildrenRepresentation>,
|
|
33
|
+
options?: Partial<BranchNodeOptions>,
|
|
34
|
+
)
|
|
35
|
+
public constructor(
|
|
36
|
+
useSiteFactory: UseSiteBranchNodeRepresentationFactory<
|
|
37
|
+
Props,
|
|
38
|
+
ChildrenRepresentation,
|
|
39
|
+
Representation,
|
|
40
|
+
StaticContext
|
|
41
|
+
>,
|
|
42
|
+
ComponentType?: ElementType<Props>,
|
|
43
|
+
options?: Partial<BranchNodeOptions>,
|
|
44
|
+
)
|
|
45
|
+
public constructor(
|
|
46
|
+
factory:
|
|
47
|
+
| FactoryMethodName
|
|
48
|
+
| UseSiteBranchNodeRepresentationFactory<Props, ChildrenRepresentation, Representation, StaticContext>,
|
|
49
|
+
componentOrReducer?:
|
|
50
|
+
| ChildrenRepresentationReducer<ChildrenRepresentation, ReducedChildrenRepresentation>
|
|
51
|
+
| ElementType<Props>,
|
|
52
|
+
options?: Partial<BranchNodeOptions>,
|
|
53
|
+
) {
|
|
54
|
+
if (typeof factory !== 'function') {
|
|
55
|
+
this.specification = {
|
|
56
|
+
type: 'declarationSite',
|
|
57
|
+
factoryMethodName: factory,
|
|
58
|
+
childrenRepresentationReducer: componentOrReducer as ChildrenRepresentationReducer<
|
|
59
|
+
ChildrenRepresentation,
|
|
60
|
+
ReducedChildrenRepresentation
|
|
61
|
+
>,
|
|
62
|
+
}
|
|
63
|
+
} else if (typeof factory === 'function') {
|
|
64
|
+
this.specification = {
|
|
65
|
+
type: 'useSite',
|
|
66
|
+
factory,
|
|
67
|
+
ComponentType: componentOrReducer as ElementType<Props>,
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
throw new ChildrenAnalyzerError('Invalid arguments')
|
|
71
|
+
}
|
|
72
|
+
this.options = {
|
|
73
|
+
...BranchNode.defaultOptions,
|
|
74
|
+
...options,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
namespace BranchNode {
|
|
80
|
+
export type Specification<
|
|
81
|
+
Props extends {} = {},
|
|
82
|
+
StaticContext = any,
|
|
83
|
+
FactoryMethodName extends ValidFactoryName = string,
|
|
84
|
+
ChildrenRepresentation = any,
|
|
85
|
+
ReducedChildrenRepresentation = any,
|
|
86
|
+
Representation = any,
|
|
87
|
+
> =
|
|
88
|
+
| {
|
|
89
|
+
type: 'declarationSite'
|
|
90
|
+
factoryMethodName: FactoryMethodName
|
|
91
|
+
childrenRepresentationReducer: ChildrenRepresentationReducer<
|
|
92
|
+
ChildrenRepresentation,
|
|
93
|
+
ReducedChildrenRepresentation
|
|
94
|
+
>
|
|
95
|
+
}
|
|
96
|
+
| {
|
|
97
|
+
type: 'useSite'
|
|
98
|
+
factory: UseSiteBranchNodeRepresentationFactory<Props, ChildrenRepresentation, Representation, StaticContext>
|
|
99
|
+
ComponentType?: ElementType<Props>
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export { BranchNode }
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ElementType } from 'react'
|
|
2
|
+
import type {
|
|
3
|
+
ConstrainedLeafRepresentationFactory,
|
|
4
|
+
UnconstrainedLeafRepresentationFactory,
|
|
5
|
+
ValidFactoryName,
|
|
6
|
+
} from './types'
|
|
7
|
+
|
|
8
|
+
class Leaf<
|
|
9
|
+
Props extends {} = {},
|
|
10
|
+
StaticContext = any,
|
|
11
|
+
FactoryMethodName extends ValidFactoryName = string,
|
|
12
|
+
Representation = any,
|
|
13
|
+
> {
|
|
14
|
+
public readonly specification: Leaf.Specification<FactoryMethodName, Representation, Props, StaticContext>
|
|
15
|
+
|
|
16
|
+
public constructor(factoryMethodName: FactoryMethodName)
|
|
17
|
+
public constructor(staticFactory: UnconstrainedLeafRepresentationFactory<Props, Representation, StaticContext>)
|
|
18
|
+
public constructor(
|
|
19
|
+
staticFactory: ConstrainedLeafRepresentationFactory<Props, Representation, StaticContext>,
|
|
20
|
+
ComponentType: ElementType<Props>,
|
|
21
|
+
)
|
|
22
|
+
public constructor(
|
|
23
|
+
factory: FactoryMethodName | UnconstrainedLeafRepresentationFactory<Props, Representation, StaticContext>,
|
|
24
|
+
ComponentType?: ElementType<Props>,
|
|
25
|
+
) {
|
|
26
|
+
if (typeof factory === 'function') {
|
|
27
|
+
this.specification = {
|
|
28
|
+
type: 'useSite',
|
|
29
|
+
ComponentType,
|
|
30
|
+
factory,
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
this.specification = {
|
|
34
|
+
type: 'declarationSite',
|
|
35
|
+
factoryMethodName: factory,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
namespace Leaf {
|
|
42
|
+
export type Specification<
|
|
43
|
+
FactoryMethodName extends ValidFactoryName,
|
|
44
|
+
Representation,
|
|
45
|
+
Props extends {},
|
|
46
|
+
StaticContext,
|
|
47
|
+
> =
|
|
48
|
+
| {
|
|
49
|
+
type: 'declarationSite'
|
|
50
|
+
factoryMethodName: FactoryMethodName
|
|
51
|
+
}
|
|
52
|
+
| {
|
|
53
|
+
type: 'useSite'
|
|
54
|
+
factory: UnconstrainedLeafRepresentationFactory<Props, Representation, StaticContext>
|
|
55
|
+
ComponentType?: ElementType<Props>
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { Leaf }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type DeclarationSiteNodeRepresentationFactory<
|
|
2
|
+
Props extends {},
|
|
3
|
+
ReducedChildrenRepresentation,
|
|
4
|
+
Representation,
|
|
5
|
+
StaticContext,
|
|
6
|
+
> = (
|
|
7
|
+
props: Props,
|
|
8
|
+
reducedChildrenRepresentation: ReducedChildrenRepresentation,
|
|
9
|
+
staticContext: StaticContext,
|
|
10
|
+
) => Representation
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type RepresentationFactorySite = 'declarationSite' | 'useSite'
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ReactElement, ReactText } from 'react'
|
|
2
|
+
|
|
3
|
+
export type UnconstrainedLeafRepresentationFactory<Props extends {}, Representation, StaticContext> = (
|
|
4
|
+
node: ReactText | ReactElement<Props, any> | boolean | null | undefined | {},
|
|
5
|
+
staticContext: StaticContext,
|
|
6
|
+
) => Representation
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactElement } from 'react'
|
|
2
|
+
|
|
3
|
+
export type UseSiteBranchNodeRepresentationFactory<
|
|
4
|
+
Props extends {},
|
|
5
|
+
ChildrenRepresentation,
|
|
6
|
+
Representation,
|
|
7
|
+
StaticContext,
|
|
8
|
+
> = (
|
|
9
|
+
node: ReactElement<Props, any>,
|
|
10
|
+
childrenRepresentation: ChildrenRepresentation,
|
|
11
|
+
staticContext: StaticContext,
|
|
12
|
+
) => Representation
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ValidFactoryName = string | number
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './ChildrenRepresentationReducer'
|
|
2
|
+
export * from './ConstrainedLeafRepresentationFactory'
|
|
3
|
+
export * from './DeclarationSiteNodeRepresentationFactory'
|
|
4
|
+
export * from './RepresentationFactorySite'
|
|
5
|
+
export * from './StaticContextFactory'
|
|
6
|
+
export * from './SyntheticChildrenFactory'
|
|
7
|
+
export * from './UnconstrainedLeafRepresentationFactory'
|
|
8
|
+
export * from './UseSiteBranchNodeRepresentationFactory'
|
|
9
|
+
export * from './ValidFactoryName'
|