@springmicro/forms 0.7.0 → 0.7.1
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/.eslintrc.cjs +22 -22
- package/README.md +11 -11
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -0
- package/dist/index.umd.cjs +0 -0
- package/package.json +3 -3
- package/src/builder/bottom-drawer.tsx +429 -429
- package/src/builder/form-builder.tsx +256 -256
- package/src/builder/modal.tsx +39 -39
- package/src/builder/nodes/node-base.tsx +94 -94
- package/src/builder/nodes/node-child-helpers.tsx +273 -273
- package/src/builder/nodes/node-parent.tsx +187 -187
- package/src/builder/nodes/node-types/array-node.tsx +134 -134
- package/src/builder/nodes/node-types/date-node.tsx +60 -60
- package/src/builder/nodes/node-types/file-node.tsx +67 -67
- package/src/builder/nodes/node-types/integer-node.tsx +60 -60
- package/src/builder/nodes/node-types/object-node.tsx +67 -67
- package/src/builder/nodes/node-types/text-node.tsx +66 -66
- package/src/fields/ArrayField.tsx +875 -875
- package/src/fields/BooleanField.tsx +110 -110
- package/src/fields/MultiSchemaField.tsx +236 -236
- package/src/fields/NullField.tsx +22 -22
- package/src/fields/NumberField.tsx +87 -87
- package/src/fields/ObjectField.tsx +338 -338
- package/src/fields/SchemaField.tsx +402 -402
- package/src/fields/StringField.tsx +67 -67
- package/src/fields/index.ts +24 -24
- package/src/index.tsx +26 -26
- package/src/interfaces/MessagesProps.interface.ts +5 -5
- package/src/interfaces/Option.interface.ts +4 -4
- package/src/styles/select.styles.ts +28 -28
- package/src/templates/ArrayFieldDescriptionTemplate.tsx +42 -42
- package/src/templates/ArrayFieldItemTemplate.tsx +78 -78
- package/src/templates/ArrayFieldTemplate.tsx +90 -90
- package/src/templates/ArrayFieldTitleTemplate.tsx +44 -44
- package/src/templates/BaseInputTemplate.tsx +94 -94
- package/src/templates/ButtonTemplates/AddButton.tsx +29 -29
- package/src/templates/ButtonTemplates/IconButton.tsx +49 -49
- package/src/templates/ButtonTemplates/SubmitButton.tsx +29 -29
- package/src/templates/ButtonTemplates/index.ts +16 -16
- package/src/templates/DescriptionField.tsx +29 -29
- package/src/templates/ErrorList.tsx +25 -25
- package/src/templates/FieldTemplate/FieldTemplate.tsx +39 -39
- package/src/templates/FieldTemplate/Label.tsx +29 -29
- package/src/templates/FieldTemplate/WrapIfAdditional.tsx +85 -85
- package/src/templates/FieldTemplate/index.ts +3 -3
- package/src/templates/ObjectFieldTemplate.tsx +79 -79
- package/src/templates/TitleField.tsx +20 -20
- package/src/templates/UnsupportedField.tsx +29 -29
- package/src/templates/index.ts +32 -32
- package/src/types/Message.type.ts +6 -6
- package/src/types/RawMessage.type.ts +15 -15
- package/src/types/form-builder.ts +135 -135
- package/src/types/utils.type.ts +1 -1
- package/src/utils/form-builder.ts +424 -424
- package/src/utils/processSelectValue.ts +50 -50
- package/src/widgets/AltDateTimeWidget.tsx +17 -17
- package/src/widgets/AltDateWidget.tsx +216 -216
- package/src/widgets/CheckboxWidget.tsx +80 -80
- package/src/widgets/CheckboxesWidget.tsx +74 -74
- package/src/widgets/ColorWidget.tsx +26 -26
- package/src/widgets/DateTimeWidget.tsx +28 -28
- package/src/widgets/DateWidget.tsx +36 -36
- package/src/widgets/EmailWidget.tsx +19 -19
- package/src/widgets/FileWidget.tsx +144 -144
- package/src/widgets/HiddenWidget.tsx +22 -22
- package/src/widgets/PasswordWidget.tsx +20 -20
- package/src/widgets/RadioWidget.tsx +87 -87
- package/src/widgets/RangeWidget.tsx +24 -24
- package/src/widgets/SelectWidget.tsx +99 -99
- package/src/widgets/TextWidget.tsx +19 -19
- package/src/widgets/TextareaWidget.tsx +64 -64
- package/src/widgets/URLWidget.tsx +19 -19
- package/src/widgets/UpDownWidget.tsx +20 -20
- package/src/widgets/index.ts +43 -43
- package/tsconfig.json +24 -24
- package/tsconfig.node.json +10 -10
- package/vite.config.ts +25 -25
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
import NodeBase from "./node-base";
|
|
2
|
-
import {
|
|
3
|
-
BaseNode,
|
|
4
|
-
ChildNodeProps,
|
|
5
|
-
EditingStateType,
|
|
6
|
-
FieldArrayType,
|
|
7
|
-
FormNodeKeys,
|
|
8
|
-
FormNodeType,
|
|
9
|
-
} from "../../types/form-builder";
|
|
10
|
-
import { UseStateType } from "../../types/utils.type";
|
|
11
|
-
import {
|
|
12
|
-
NodeAccordian,
|
|
13
|
-
NodeCheckbox,
|
|
14
|
-
NodeChildBase,
|
|
15
|
-
NodeField,
|
|
16
|
-
NodeTitle,
|
|
17
|
-
} from "./node-child-helpers";
|
|
18
|
-
import {
|
|
19
|
-
baseValidation,
|
|
20
|
-
formatPropName,
|
|
21
|
-
generateUpdateNodeByKeyLocal,
|
|
22
|
-
} from "../../utils/form-builder";
|
|
23
|
-
import React from "react";
|
|
24
|
-
|
|
25
|
-
import TextFieldsIcon from "@mui/icons-material/TextFields";
|
|
26
|
-
import TextNode from "./node-types/text-node";
|
|
27
|
-
import AttachFileIcon from "@mui/icons-material/AttachFile";
|
|
28
|
-
import FileNode from "./node-types/file-node";
|
|
29
|
-
import NumbersIcon from "@mui/icons-material/Numbers";
|
|
30
|
-
import IntegerNode from "./node-types/integer-node";
|
|
31
|
-
import ListIcon from "@mui/icons-material/List";
|
|
32
|
-
import ArrayNode from "./node-types/array-node";
|
|
33
|
-
import ViewInArIcon from "@mui/icons-material/ViewInAr";
|
|
34
|
-
import ObjectNode from "./node-types/object-node";
|
|
35
|
-
import DateRangeIcon from "@mui/icons-material/DateRange";
|
|
36
|
-
import DateNode from "./node-types/date-node";
|
|
37
|
-
|
|
38
|
-
export type FormNodeProps = {
|
|
39
|
-
nodesState: UseStateType<FormNodeType[]>;
|
|
40
|
-
node: FormNodeType;
|
|
41
|
-
index: number;
|
|
42
|
-
editingState: UseStateType<EditingStateType>;
|
|
43
|
-
updatePath: () => void;
|
|
44
|
-
deleteNode: () => void;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const nodeComponents: {
|
|
48
|
-
[key in FormNodeKeys]: FormNodeType extends { type: infer T }
|
|
49
|
-
? T extends key
|
|
50
|
-
? {
|
|
51
|
-
icon: React.ComponentType<any>;
|
|
52
|
-
component: React.ComponentType<ChildNodeProps>;
|
|
53
|
-
}
|
|
54
|
-
: never
|
|
55
|
-
: never;
|
|
56
|
-
} = {
|
|
57
|
-
string: {
|
|
58
|
-
icon: TextFieldsIcon,
|
|
59
|
-
component: TextNode,
|
|
60
|
-
},
|
|
61
|
-
file: {
|
|
62
|
-
icon: AttachFileIcon,
|
|
63
|
-
component: FileNode,
|
|
64
|
-
},
|
|
65
|
-
integer: {
|
|
66
|
-
icon: NumbersIcon,
|
|
67
|
-
component: IntegerNode,
|
|
68
|
-
},
|
|
69
|
-
date: {
|
|
70
|
-
icon: DateRangeIcon,
|
|
71
|
-
component: DateNode,
|
|
72
|
-
},
|
|
73
|
-
array: {
|
|
74
|
-
icon: ListIcon,
|
|
75
|
-
component: ArrayNode,
|
|
76
|
-
},
|
|
77
|
-
object: {
|
|
78
|
-
icon: ViewInArIcon,
|
|
79
|
-
component: ObjectNode,
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export default function NodeParent({
|
|
84
|
-
nodesState,
|
|
85
|
-
node: _initNode,
|
|
86
|
-
index,
|
|
87
|
-
editingState,
|
|
88
|
-
updatePath,
|
|
89
|
-
deleteNode,
|
|
90
|
-
}: FormNodeProps) {
|
|
91
|
-
const nodeState = React.useState<FormNodeType>(_initNode);
|
|
92
|
-
const [node, setNode] = nodeState;
|
|
93
|
-
const [editing, setEditing] = editingState;
|
|
94
|
-
const editingThisNode = editing === node.nodeId;
|
|
95
|
-
|
|
96
|
-
function isValid(key: string, value: string) {
|
|
97
|
-
if (!baseValidation(key, value, node)) return false;
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
102
|
-
|
|
103
|
-
const Component = nodeComponents[node.type].component;
|
|
104
|
-
|
|
105
|
-
React.useEffect(() => {
|
|
106
|
-
// ! Minimal testing has happened. If there are saving issues, this if statement is likely the cause.
|
|
107
|
-
if (nodesState[0][index] === node) return; // Prevents autosave from running when switching paths.
|
|
108
|
-
|
|
109
|
-
nodesState[1]((_nodes) => {
|
|
110
|
-
const nodes = [..._nodes];
|
|
111
|
-
nodes[index] = node;
|
|
112
|
-
return nodes;
|
|
113
|
-
});
|
|
114
|
-
}, [node]);
|
|
115
|
-
|
|
116
|
-
function updateNode(newNode: FormNodeType) {
|
|
117
|
-
setNode(newNode);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<NodeBase
|
|
122
|
-
nodeId={node.nodeId}
|
|
123
|
-
index={index}
|
|
124
|
-
editingState={editingState}
|
|
125
|
-
icon={nodeComponents[node.type].icon}
|
|
126
|
-
>
|
|
127
|
-
<NodeChildBase>
|
|
128
|
-
<NodeTitle
|
|
129
|
-
isPropname={!node.title}
|
|
130
|
-
isEditing={editingThisNode}
|
|
131
|
-
onClick={() => {
|
|
132
|
-
setEditing(false);
|
|
133
|
-
}}
|
|
134
|
-
>
|
|
135
|
-
{node.title ?? node.propertyName}
|
|
136
|
-
</NodeTitle>
|
|
137
|
-
|
|
138
|
-
<NodeAccordian
|
|
139
|
-
open={editingThisNode}
|
|
140
|
-
close={() => {
|
|
141
|
-
setEditing(false);
|
|
142
|
-
}}
|
|
143
|
-
deleteNode={deleteNode}
|
|
144
|
-
>
|
|
145
|
-
<Component
|
|
146
|
-
nodeState={[node, setNode]}
|
|
147
|
-
updateNode={updateNode}
|
|
148
|
-
updatePath={updatePath}
|
|
149
|
-
defaultFields={(
|
|
150
|
-
[
|
|
151
|
-
{
|
|
152
|
-
prop: "propertyName",
|
|
153
|
-
tooltip:
|
|
154
|
-
"The json key the value will be assinged to. In the case of a duplicate key, '-x' x being a number will be added to the end until it's resolved.",
|
|
155
|
-
props: {
|
|
156
|
-
helperText: node.propertyName
|
|
157
|
-
? undefined
|
|
158
|
-
: 'Property name: "' + formatPropName(node.title!) + '"',
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
{ prop: "title" },
|
|
162
|
-
{ prop: "description" },
|
|
163
|
-
] as FieldArrayType<BaseNode>
|
|
164
|
-
).map((field) => (
|
|
165
|
-
<NodeField
|
|
166
|
-
key={field.prop}
|
|
167
|
-
field={field}
|
|
168
|
-
node={node}
|
|
169
|
-
update={updateNodeByKeyLocal}
|
|
170
|
-
/>
|
|
171
|
-
))}
|
|
172
|
-
defaultChecks={(
|
|
173
|
-
[{ prop: "required" }] as FieldArrayType<BaseNode>
|
|
174
|
-
).map((check) => (
|
|
175
|
-
<NodeCheckbox
|
|
176
|
-
key={check.prop}
|
|
177
|
-
field={check}
|
|
178
|
-
node={node}
|
|
179
|
-
update={updateNodeByKeyLocal}
|
|
180
|
-
/>
|
|
181
|
-
))}
|
|
182
|
-
/>
|
|
183
|
-
</NodeAccordian>
|
|
184
|
-
</NodeChildBase>
|
|
185
|
-
</NodeBase>
|
|
186
|
-
);
|
|
187
|
-
}
|
|
1
|
+
import NodeBase from "./node-base";
|
|
2
|
+
import {
|
|
3
|
+
BaseNode,
|
|
4
|
+
ChildNodeProps,
|
|
5
|
+
EditingStateType,
|
|
6
|
+
FieldArrayType,
|
|
7
|
+
FormNodeKeys,
|
|
8
|
+
FormNodeType,
|
|
9
|
+
} from "../../types/form-builder";
|
|
10
|
+
import { UseStateType } from "../../types/utils.type";
|
|
11
|
+
import {
|
|
12
|
+
NodeAccordian,
|
|
13
|
+
NodeCheckbox,
|
|
14
|
+
NodeChildBase,
|
|
15
|
+
NodeField,
|
|
16
|
+
NodeTitle,
|
|
17
|
+
} from "./node-child-helpers";
|
|
18
|
+
import {
|
|
19
|
+
baseValidation,
|
|
20
|
+
formatPropName,
|
|
21
|
+
generateUpdateNodeByKeyLocal,
|
|
22
|
+
} from "../../utils/form-builder";
|
|
23
|
+
import React from "react";
|
|
24
|
+
|
|
25
|
+
import TextFieldsIcon from "@mui/icons-material/TextFields";
|
|
26
|
+
import TextNode from "./node-types/text-node";
|
|
27
|
+
import AttachFileIcon from "@mui/icons-material/AttachFile";
|
|
28
|
+
import FileNode from "./node-types/file-node";
|
|
29
|
+
import NumbersIcon from "@mui/icons-material/Numbers";
|
|
30
|
+
import IntegerNode from "./node-types/integer-node";
|
|
31
|
+
import ListIcon from "@mui/icons-material/List";
|
|
32
|
+
import ArrayNode from "./node-types/array-node";
|
|
33
|
+
import ViewInArIcon from "@mui/icons-material/ViewInAr";
|
|
34
|
+
import ObjectNode from "./node-types/object-node";
|
|
35
|
+
import DateRangeIcon from "@mui/icons-material/DateRange";
|
|
36
|
+
import DateNode from "./node-types/date-node";
|
|
37
|
+
|
|
38
|
+
export type FormNodeProps = {
|
|
39
|
+
nodesState: UseStateType<FormNodeType[]>;
|
|
40
|
+
node: FormNodeType;
|
|
41
|
+
index: number;
|
|
42
|
+
editingState: UseStateType<EditingStateType>;
|
|
43
|
+
updatePath: () => void;
|
|
44
|
+
deleteNode: () => void;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const nodeComponents: {
|
|
48
|
+
[key in FormNodeKeys]: FormNodeType extends { type: infer T }
|
|
49
|
+
? T extends key
|
|
50
|
+
? {
|
|
51
|
+
icon: React.ComponentType<any>;
|
|
52
|
+
component: React.ComponentType<ChildNodeProps>;
|
|
53
|
+
}
|
|
54
|
+
: never
|
|
55
|
+
: never;
|
|
56
|
+
} = {
|
|
57
|
+
string: {
|
|
58
|
+
icon: TextFieldsIcon,
|
|
59
|
+
component: TextNode,
|
|
60
|
+
},
|
|
61
|
+
file: {
|
|
62
|
+
icon: AttachFileIcon,
|
|
63
|
+
component: FileNode,
|
|
64
|
+
},
|
|
65
|
+
integer: {
|
|
66
|
+
icon: NumbersIcon,
|
|
67
|
+
component: IntegerNode,
|
|
68
|
+
},
|
|
69
|
+
date: {
|
|
70
|
+
icon: DateRangeIcon,
|
|
71
|
+
component: DateNode,
|
|
72
|
+
},
|
|
73
|
+
array: {
|
|
74
|
+
icon: ListIcon,
|
|
75
|
+
component: ArrayNode,
|
|
76
|
+
},
|
|
77
|
+
object: {
|
|
78
|
+
icon: ViewInArIcon,
|
|
79
|
+
component: ObjectNode,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default function NodeParent({
|
|
84
|
+
nodesState,
|
|
85
|
+
node: _initNode,
|
|
86
|
+
index,
|
|
87
|
+
editingState,
|
|
88
|
+
updatePath,
|
|
89
|
+
deleteNode,
|
|
90
|
+
}: FormNodeProps) {
|
|
91
|
+
const nodeState = React.useState<FormNodeType>(_initNode);
|
|
92
|
+
const [node, setNode] = nodeState;
|
|
93
|
+
const [editing, setEditing] = editingState;
|
|
94
|
+
const editingThisNode = editing === node.nodeId;
|
|
95
|
+
|
|
96
|
+
function isValid(key: string, value: string) {
|
|
97
|
+
if (!baseValidation(key, value, node)) return false;
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
102
|
+
|
|
103
|
+
const Component = nodeComponents[node.type].component;
|
|
104
|
+
|
|
105
|
+
React.useEffect(() => {
|
|
106
|
+
// ! Minimal testing has happened. If there are saving issues, this if statement is likely the cause.
|
|
107
|
+
if (nodesState[0][index] === node) return; // Prevents autosave from running when switching paths.
|
|
108
|
+
|
|
109
|
+
nodesState[1]((_nodes) => {
|
|
110
|
+
const nodes = [..._nodes];
|
|
111
|
+
nodes[index] = node;
|
|
112
|
+
return nodes;
|
|
113
|
+
});
|
|
114
|
+
}, [node]);
|
|
115
|
+
|
|
116
|
+
function updateNode(newNode: FormNodeType) {
|
|
117
|
+
setNode(newNode);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<NodeBase
|
|
122
|
+
nodeId={node.nodeId}
|
|
123
|
+
index={index}
|
|
124
|
+
editingState={editingState}
|
|
125
|
+
icon={nodeComponents[node.type].icon}
|
|
126
|
+
>
|
|
127
|
+
<NodeChildBase>
|
|
128
|
+
<NodeTitle
|
|
129
|
+
isPropname={!node.title}
|
|
130
|
+
isEditing={editingThisNode}
|
|
131
|
+
onClick={() => {
|
|
132
|
+
setEditing(false);
|
|
133
|
+
}}
|
|
134
|
+
>
|
|
135
|
+
{node.title ?? node.propertyName}
|
|
136
|
+
</NodeTitle>
|
|
137
|
+
|
|
138
|
+
<NodeAccordian
|
|
139
|
+
open={editingThisNode}
|
|
140
|
+
close={() => {
|
|
141
|
+
setEditing(false);
|
|
142
|
+
}}
|
|
143
|
+
deleteNode={deleteNode}
|
|
144
|
+
>
|
|
145
|
+
<Component
|
|
146
|
+
nodeState={[node, setNode]}
|
|
147
|
+
updateNode={updateNode}
|
|
148
|
+
updatePath={updatePath}
|
|
149
|
+
defaultFields={(
|
|
150
|
+
[
|
|
151
|
+
{
|
|
152
|
+
prop: "propertyName",
|
|
153
|
+
tooltip:
|
|
154
|
+
"The json key the value will be assinged to. In the case of a duplicate key, '-x' x being a number will be added to the end until it's resolved.",
|
|
155
|
+
props: {
|
|
156
|
+
helperText: node.propertyName
|
|
157
|
+
? undefined
|
|
158
|
+
: 'Property name: "' + formatPropName(node.title!) + '"',
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{ prop: "title" },
|
|
162
|
+
{ prop: "description" },
|
|
163
|
+
] as FieldArrayType<BaseNode>
|
|
164
|
+
).map((field) => (
|
|
165
|
+
<NodeField
|
|
166
|
+
key={field.prop}
|
|
167
|
+
field={field}
|
|
168
|
+
node={node}
|
|
169
|
+
update={updateNodeByKeyLocal}
|
|
170
|
+
/>
|
|
171
|
+
))}
|
|
172
|
+
defaultChecks={(
|
|
173
|
+
[{ prop: "required" }] as FieldArrayType<BaseNode>
|
|
174
|
+
).map((check) => (
|
|
175
|
+
<NodeCheckbox
|
|
176
|
+
key={check.prop}
|
|
177
|
+
field={check}
|
|
178
|
+
node={node}
|
|
179
|
+
update={updateNodeByKeyLocal}
|
|
180
|
+
/>
|
|
181
|
+
))}
|
|
182
|
+
/>
|
|
183
|
+
</NodeAccordian>
|
|
184
|
+
</NodeChildBase>
|
|
185
|
+
</NodeBase>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
@@ -1,134 +1,134 @@
|
|
|
1
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
-
import { nodeComponents } from "../node-parent";
|
|
3
|
-
import { UseStateType } from "../../../types/utils.type";
|
|
4
|
-
import {
|
|
5
|
-
ArrayNodeEmpty,
|
|
6
|
-
ArrayNode as ArrayNodeType,
|
|
7
|
-
ChildNodeProps,
|
|
8
|
-
FieldArrayType,
|
|
9
|
-
} from "../../../types/form-builder";
|
|
10
|
-
import React from "react";
|
|
11
|
-
import {
|
|
12
|
-
FieldContainer,
|
|
13
|
-
NodeCheckbox,
|
|
14
|
-
NodeField,
|
|
15
|
-
textfieldStyle,
|
|
16
|
-
} from "../node-child-helpers";
|
|
17
|
-
import {
|
|
18
|
-
formatTitle,
|
|
19
|
-
generateUpdateNodeByKeyLocal,
|
|
20
|
-
} from "../../../utils/form-builder";
|
|
21
|
-
import { Box, MenuItem, TextField } from "@mui/material";
|
|
22
|
-
|
|
23
|
-
const defaultEmptyNodes = {
|
|
24
|
-
string: { type: "string" },
|
|
25
|
-
integer: { type: "integer" },
|
|
26
|
-
date: { type: "date" },
|
|
27
|
-
// TODO
|
|
28
|
-
// ? The node works but serializtion does not.
|
|
29
|
-
// array: { type: "array", child: { type: "string" } },
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export default function ArrayNode({
|
|
33
|
-
nodeState,
|
|
34
|
-
updateNode,
|
|
35
|
-
defaultFields,
|
|
36
|
-
defaultChecks,
|
|
37
|
-
}: ChildNodeProps) {
|
|
38
|
-
const [node, setNode] = nodeState;
|
|
39
|
-
|
|
40
|
-
// @ts-ignore
|
|
41
|
-
if (!node.child) {
|
|
42
|
-
return <></>;
|
|
43
|
-
}
|
|
44
|
-
React.useEffect(() => {
|
|
45
|
-
updateNode(node);
|
|
46
|
-
}, [node]);
|
|
47
|
-
|
|
48
|
-
function isValid(key: string, value: string) {
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
53
|
-
|
|
54
|
-
const fields: FieldArrayType<ArrayNodeType> = [];
|
|
55
|
-
|
|
56
|
-
const checks: FieldArrayType<ArrayNodeType> = [];
|
|
57
|
-
|
|
58
|
-
return (
|
|
59
|
-
<>
|
|
60
|
-
<FieldContainer>
|
|
61
|
-
{defaultFields}
|
|
62
|
-
{fields.map((field) => (
|
|
63
|
-
<NodeField
|
|
64
|
-
key={field.prop}
|
|
65
|
-
field={field}
|
|
66
|
-
node={node}
|
|
67
|
-
update={updateNodeByKeyLocal}
|
|
68
|
-
{...field.props}
|
|
69
|
-
/>
|
|
70
|
-
))}
|
|
71
|
-
</FieldContainer>
|
|
72
|
-
<FieldContainer>
|
|
73
|
-
{defaultChecks}
|
|
74
|
-
{checks.map((check) => (
|
|
75
|
-
<NodeCheckbox
|
|
76
|
-
key={check.prop}
|
|
77
|
-
field={check}
|
|
78
|
-
node={node}
|
|
79
|
-
update={updateNodeByKeyLocal}
|
|
80
|
-
{...check.props}
|
|
81
|
-
/>
|
|
82
|
-
))}
|
|
83
|
-
</FieldContainer>
|
|
84
|
-
<ArrayChildContainer
|
|
85
|
-
nodeState={nodeState as UseStateType<ArrayNodeType>}
|
|
86
|
-
/>
|
|
87
|
-
</>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function ArrayChildContainer({
|
|
92
|
-
nodeState,
|
|
93
|
-
}: {
|
|
94
|
-
nodeState: UseStateType<ArrayNodeType>;
|
|
95
|
-
}) {
|
|
96
|
-
const [_n, set_Node] = nodeState;
|
|
97
|
-
const [node, setNode] = React.useState(_n);
|
|
98
|
-
const [nodeChild, setNodeChild] = React.useState(node.child);
|
|
99
|
-
if (!node.child) return <></>;
|
|
100
|
-
React.useEffect(() => {
|
|
101
|
-
setNode(_n);
|
|
102
|
-
setNodeChild(_n.child);
|
|
103
|
-
}, [_n]);
|
|
104
|
-
|
|
105
|
-
React.useEffect(() => {
|
|
106
|
-
set_Node((n) => ({ ...n, child: nodeChild }));
|
|
107
|
-
}, [nodeChild]);
|
|
108
|
-
|
|
109
|
-
const Component = nodeComponents[nodeChild.type].component;
|
|
110
|
-
|
|
111
|
-
return (
|
|
112
|
-
<Box
|
|
113
|
-
sx={{
|
|
114
|
-
borderTop: "2px solid #aaa",
|
|
115
|
-
borderLeft: "2px solid #aaa",
|
|
116
|
-
pt: 1,
|
|
117
|
-
pl: 2,
|
|
118
|
-
borderTopLeftRadius: 6,
|
|
119
|
-
}}
|
|
120
|
-
>
|
|
121
|
-
<h3>Array Child ({nodeChild.type})</h3>
|
|
122
|
-
<Box sx={{ pt: 2, display: "flex", gap: 1, flexDirection: "column" }}>
|
|
123
|
-
<Component
|
|
124
|
-
//@ts-ignore
|
|
125
|
-
nodeState={[nodeChild, setNodeChild]}
|
|
126
|
-
//@ts-ignore
|
|
127
|
-
updateNode={setNodeChild}
|
|
128
|
-
defaultFields={[]}
|
|
129
|
-
defaultChecks={[]}
|
|
130
|
-
/>
|
|
131
|
-
</Box>
|
|
132
|
-
</Box>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
+
import { nodeComponents } from "../node-parent";
|
|
3
|
+
import { UseStateType } from "../../../types/utils.type";
|
|
4
|
+
import {
|
|
5
|
+
ArrayNodeEmpty,
|
|
6
|
+
ArrayNode as ArrayNodeType,
|
|
7
|
+
ChildNodeProps,
|
|
8
|
+
FieldArrayType,
|
|
9
|
+
} from "../../../types/form-builder";
|
|
10
|
+
import React from "react";
|
|
11
|
+
import {
|
|
12
|
+
FieldContainer,
|
|
13
|
+
NodeCheckbox,
|
|
14
|
+
NodeField,
|
|
15
|
+
textfieldStyle,
|
|
16
|
+
} from "../node-child-helpers";
|
|
17
|
+
import {
|
|
18
|
+
formatTitle,
|
|
19
|
+
generateUpdateNodeByKeyLocal,
|
|
20
|
+
} from "../../../utils/form-builder";
|
|
21
|
+
import { Box, MenuItem, TextField } from "@mui/material";
|
|
22
|
+
|
|
23
|
+
const defaultEmptyNodes = {
|
|
24
|
+
string: { type: "string" },
|
|
25
|
+
integer: { type: "integer" },
|
|
26
|
+
date: { type: "date" },
|
|
27
|
+
// TODO
|
|
28
|
+
// ? The node works but serializtion does not.
|
|
29
|
+
// array: { type: "array", child: { type: "string" } },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default function ArrayNode({
|
|
33
|
+
nodeState,
|
|
34
|
+
updateNode,
|
|
35
|
+
defaultFields,
|
|
36
|
+
defaultChecks,
|
|
37
|
+
}: ChildNodeProps) {
|
|
38
|
+
const [node, setNode] = nodeState;
|
|
39
|
+
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
if (!node.child) {
|
|
42
|
+
return <></>;
|
|
43
|
+
}
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
updateNode(node);
|
|
46
|
+
}, [node]);
|
|
47
|
+
|
|
48
|
+
function isValid(key: string, value: string) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
53
|
+
|
|
54
|
+
const fields: FieldArrayType<ArrayNodeType> = [];
|
|
55
|
+
|
|
56
|
+
const checks: FieldArrayType<ArrayNodeType> = [];
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<>
|
|
60
|
+
<FieldContainer>
|
|
61
|
+
{defaultFields}
|
|
62
|
+
{fields.map((field) => (
|
|
63
|
+
<NodeField
|
|
64
|
+
key={field.prop}
|
|
65
|
+
field={field}
|
|
66
|
+
node={node}
|
|
67
|
+
update={updateNodeByKeyLocal}
|
|
68
|
+
{...field.props}
|
|
69
|
+
/>
|
|
70
|
+
))}
|
|
71
|
+
</FieldContainer>
|
|
72
|
+
<FieldContainer>
|
|
73
|
+
{defaultChecks}
|
|
74
|
+
{checks.map((check) => (
|
|
75
|
+
<NodeCheckbox
|
|
76
|
+
key={check.prop}
|
|
77
|
+
field={check}
|
|
78
|
+
node={node}
|
|
79
|
+
update={updateNodeByKeyLocal}
|
|
80
|
+
{...check.props}
|
|
81
|
+
/>
|
|
82
|
+
))}
|
|
83
|
+
</FieldContainer>
|
|
84
|
+
<ArrayChildContainer
|
|
85
|
+
nodeState={nodeState as UseStateType<ArrayNodeType>}
|
|
86
|
+
/>
|
|
87
|
+
</>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function ArrayChildContainer({
|
|
92
|
+
nodeState,
|
|
93
|
+
}: {
|
|
94
|
+
nodeState: UseStateType<ArrayNodeType>;
|
|
95
|
+
}) {
|
|
96
|
+
const [_n, set_Node] = nodeState;
|
|
97
|
+
const [node, setNode] = React.useState(_n);
|
|
98
|
+
const [nodeChild, setNodeChild] = React.useState(node.child);
|
|
99
|
+
if (!node.child) return <></>;
|
|
100
|
+
React.useEffect(() => {
|
|
101
|
+
setNode(_n);
|
|
102
|
+
setNodeChild(_n.child);
|
|
103
|
+
}, [_n]);
|
|
104
|
+
|
|
105
|
+
React.useEffect(() => {
|
|
106
|
+
set_Node((n) => ({ ...n, child: nodeChild }));
|
|
107
|
+
}, [nodeChild]);
|
|
108
|
+
|
|
109
|
+
const Component = nodeComponents[nodeChild.type].component;
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<Box
|
|
113
|
+
sx={{
|
|
114
|
+
borderTop: "2px solid #aaa",
|
|
115
|
+
borderLeft: "2px solid #aaa",
|
|
116
|
+
pt: 1,
|
|
117
|
+
pl: 2,
|
|
118
|
+
borderTopLeftRadius: 6,
|
|
119
|
+
}}
|
|
120
|
+
>
|
|
121
|
+
<h3>Array Child ({nodeChild.type})</h3>
|
|
122
|
+
<Box sx={{ pt: 2, display: "flex", gap: 1, flexDirection: "column" }}>
|
|
123
|
+
<Component
|
|
124
|
+
//@ts-ignore
|
|
125
|
+
nodeState={[nodeChild, setNodeChild]}
|
|
126
|
+
//@ts-ignore
|
|
127
|
+
updateNode={setNodeChild}
|
|
128
|
+
defaultFields={[]}
|
|
129
|
+
defaultChecks={[]}
|
|
130
|
+
/>
|
|
131
|
+
</Box>
|
|
132
|
+
</Box>
|
|
133
|
+
);
|
|
134
|
+
}
|