@@ -2,7 +2,59 @@ import React, { useContext } from 'react';
2
2
import PropTypes from 'prop-types' ;
3
3
import RendererContext from '../renderer-context' ;
4
4
import Condition from '../condition' ;
5
- import FormSpy from '../form-spy' ;
5
+ import { memoize } from '../common/helpers' ;
6
+ import { Field } from 'react-final-form' ;
7
+
8
+ const mergeFunctionTrigger = ( fn , field ) => {
9
+ let internalTriggers = [ ] ;
10
+ const internalWhen = fn ( field ) ;
11
+ if ( Array . isArray ( internalWhen ) ) {
12
+ internalTriggers = [ ...internalWhen ] ;
13
+ } else {
14
+ internalTriggers . push ( internalWhen ) ;
15
+ }
16
+
17
+ return internalTriggers ;
18
+ } ;
19
+
20
+ const getConditionTriggers = memoize ( ( condition , field ) => {
21
+ let triggers = [ ] ;
22
+ if ( Array . isArray ( condition ) ) {
23
+ return condition . reduce ( ( acc , item ) => [ ...acc , ...getConditionTriggers ( item , field ) ] , [ ] ) ;
24
+ }
25
+
26
+ const { when, ...rest } = condition ;
27
+ const nestedKeys = [ 'and' , 'or' , 'sequence' ] ;
28
+ if ( typeof when === 'string' ) {
29
+ triggers = [ ...triggers , when ] ;
30
+ }
31
+
32
+ if ( typeof when === 'function' ) {
33
+ triggers = [ ...triggers , ...mergeFunctionTrigger ( when , field ) ] ;
34
+ }
35
+
36
+ if ( Array . isArray ( when ) ) {
37
+ when . forEach ( item => {
38
+ if ( typeof item === 'string' ) {
39
+ triggers = [ ...triggers , item ] ;
40
+ }
41
+
42
+ if ( typeof item === 'function' ) {
43
+ triggers = [ ...triggers , ...mergeFunctionTrigger ( item , field ) ] ;
44
+ }
45
+ } ) ;
46
+ }
47
+
48
+ nestedKeys . forEach ( key => {
49
+ if ( typeof rest [ key ] !== 'undefined' ) {
50
+ rest [ key ] . forEach ( item => {
51
+ triggers = [ ...triggers , ...getConditionTriggers ( item , field ) ] ;
52
+ } ) ;
53
+ }
54
+ } ) ;
55
+
56
+ return Array . from ( new Set ( triggers ) ) ;
57
+ } ) ;
6
58
7
59
const FormFieldHideWrapper = ( { hideField, children } ) => ( hideField ? < div hidden > { children } </ div > : children ) ;
8
60
@@ -15,18 +67,66 @@ FormFieldHideWrapper.defaultProps = {
15
67
hideField : false
16
68
} ;
17
69
18
- const FormConditionWrapper = ( { condition, children, field } ) =>
19
- condition ? (
20
- < FormSpy subscription = { { values : true } } >
21
- { ( { values } ) => (
22
- < Condition condition = { condition } values = { values } field = { field } >
23
- { children }
24
- </ Condition >
70
+ const ConditionTriggerWrapper = ( { condition, values, children, field} ) => (
71
+ < Condition condition = { condition } values = { values } field = { field } >
72
+ { children }
73
+ </ Condition >
74
+ ) ;
75
+
76
+ ConditionTriggerWrapper . propTypes = {
77
+ condition : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . array ] ) ,
78
+ children : PropTypes . node . isRequired ,
79
+ field : PropTypes . object ,
80
+ values : PropTypes . object . isRequired ,
81
+ } ;
82
+
83
+ const ConditionTriggerDetector = ( { values = { } , triggers = [ ] , children, condition, field } ) => {
84
+ const internalTriggers = [ ...triggers ] ;
85
+ if ( internalTriggers . length === 0 ) {
86
+ return (
87
+ < ConditionTriggerWrapper condition = { condition } values = { values } field = { field } >
88
+ { children }
89
+ </ ConditionTriggerWrapper >
90
+ ) ;
91
+ }
92
+
93
+ const name = internalTriggers . shift ( ) ;
94
+ return (
95
+ < Field name = { name } subscription = { { value : true } } >
96
+ { ( { input : { value} } ) => (
97
+ < ConditionTriggerDetector
98
+ triggers = { [ ...internalTriggers ] }
99
+ values = { { ...values , [ name ] : value } }
100
+ condition = { condition }
101
+ field = { field }
102
+ >
103
+ { children }
104
+ </ ConditionTriggerDetector >
25
105
) }
26
- </ FormSpy >
27
- ) : (
28
- children
106
+ </ Field >
107
+ ) ;
108
+ } ;
109
+
110
+ ConditionTriggerDetector . propTypes = {
111
+ values : PropTypes . object ,
112
+ triggers : PropTypes . arrayOf ( PropTypes . string ) ,
113
+ children : PropTypes . node ,
114
+ condition : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . array ] ) ,
115
+ field : PropTypes . object . isRequired
116
+ } ;
117
+
118
+ const FormConditionWrapper = ( { condition, children, field } ) => {
119
+ if ( condition ) {
120
+ const triggers = getConditionTriggers ( condition , field ) ;
121
+ return (
122
+ < ConditionTriggerDetector triggers = { triggers } condition = { condition } field = { field } >
123
+ { children }
124
+ </ ConditionTriggerDetector >
29
125
) ;
126
+ }
127
+
128
+ return children ;
129
+ } ;
30
130
31
131
FormConditionWrapper . propTypes = {
32
132
condition : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . array ] ) ,
@@ -111,6 +211,8 @@ SingleField.propTypes = {
111
211
resolveProps : PropTypes . func
112
212
} ;
113
213
114
- const renderForm = ( fields ) => fields . map ( ( field ) => ( Array . isArray ( field ) ? renderForm ( field ) : < SingleField key = { field . name } { ...field } /> ) ) ;
214
+ const renderForm = ( fields ) => {
215
+ return fields . map ( ( field ) => ( Array . isArray ( field ) ? renderForm ( field ) : < SingleField key = { field . name } { ...field } /> ) ) ;
216
+ } ;
115
217
116
218
export default renderForm ;
0 commit comments