-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathReactiveField.tsx
106 lines (97 loc) · 2.99 KB
/
ReactiveField.tsx
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
import React, { Fragment, useContext } from 'react'
import { toJS } from '@formily/reactive'
import { observer } from '@formily/reactive-react'
import { isFn, FormPath } from '@formily/shared'
import { isVoidField, GeneralField, Form } from '@formily/core'
import { SchemaOptionsContext } from '../shared'
interface IReactiveFieldProps {
field: GeneralField
children?:
| ((field: GeneralField, form: Form) => React.ReactChild)
| React.ReactNode
}
const mergeChildren = (children: React.ReactNode, content: React.ReactNode) => {
if (!children && !content) return
return (
<Fragment>
{children}
{content}
</Fragment>
)
}
const renderChildren = (children: React.ReactNode, ...args: any[]) =>
isFn(children) ? children(...args) : children
const ReactiveInternal: React.FC<IReactiveFieldProps> = (props) => {
const options = useContext(SchemaOptionsContext)
if (!props.field) {
return <Fragment>{renderChildren(props.children)}</Fragment>
}
const field = props.field
const content = mergeChildren(
renderChildren(props.children, field, field.form),
field.content ?? field.component[1].children
)
if (field.display !== 'visible') return null
const renderDecorator = (children: React.ReactNode) => {
if (!field.decorator[0]) {
return <Fragment>{children}</Fragment>
}
const finalComponent =
FormPath.getIn(options?.components, field.decorator[0]) ??
field.decorator[0]
return React.createElement(
finalComponent,
toJS(field.decorator[1]),
children
)
}
const renderComponent = () => {
if (!field.component[0]) return content
const value = !isVoidField(field) ? field.value : undefined
const onChange = !isVoidField(field)
? (...args: any[]) => {
field.onInput(...args)
field.component[1]?.onChange?.(...args)
}
: field.component[1]?.onChange
const onFocus = !isVoidField(field)
? (...args: any[]) => {
field.onFocus(...args)
field.component[1]?.onFocus?.(...args)
}
: field.component[1]?.onFocus
const onBlur = !isVoidField(field)
? (...args: any[]) => {
field.onBlur(...args)
field.component[1]?.onBlur?.(...args)
}
: field.component[1]?.onBlur
const disabled = !isVoidField(field)
? field.pattern === 'disabled' || field.pattern === 'readPretty'
: undefined
const readOnly = !isVoidField(field)
? field.pattern === 'readOnly'
: undefined
const finalComponent =
FormPath.getIn(options?.components, field.component[0]) ??
field.component[0]
return React.createElement(
finalComponent,
{
disabled,
readOnly,
...toJS(field.component[1]),
value,
onChange,
onFocus,
onBlur,
},
content
)
}
return renderDecorator(renderComponent())
}
ReactiveInternal.displayName = 'ReactiveField'
export const ReactiveField = observer(ReactiveInternal, {
forwardRef: true,
})