@springmicro/forms 0.1.3 → 0.2.0-alpha.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 +4 -0
- package/dist/index.js +4567 -4761
- package/dist/index.umd.cjs +38 -38
- package/package.json +9 -3
- package/src/builder/bottom-drawer.tsx +429 -0
- package/src/builder/form-builder.tsx +256 -0
- package/src/builder/modal.tsx +39 -0
- package/src/builder/nodes/node-base.tsx +94 -0
- package/src/builder/nodes/node-child-helpers.tsx +273 -0
- package/src/builder/nodes/node-parent.tsx +187 -0
- package/src/builder/nodes/node-types/array-node.tsx +134 -0
- package/src/builder/nodes/node-types/date-node.tsx +60 -0
- package/src/builder/nodes/node-types/file-node.tsx +67 -0
- package/src/builder/nodes/node-types/integer-node.tsx +60 -0
- package/src/builder/nodes/node-types/object-node.tsx +67 -0
- package/src/builder/nodes/node-types/text-node.tsx +66 -0
- package/src/types/form-builder.ts +135 -0
- package/src/types/utils.type.ts +1 -0
- package/src/utils/form-builder.ts +424 -0
|
@@ -0,0 +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
|
+
}
|
|
@@ -0,0 +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
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChildNodeProps,
|
|
3
|
+
DateNode as DateNodeType,
|
|
4
|
+
FieldArrayType,
|
|
5
|
+
} from "../../../types/form-builder";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { FieldContainer, NodeCheckbox, NodeField } from "../node-child-helpers";
|
|
8
|
+
import { generateUpdateNodeByKeyLocal } from "../../../utils/form-builder";
|
|
9
|
+
|
|
10
|
+
export default function DateNode({
|
|
11
|
+
nodeState,
|
|
12
|
+
updateNode,
|
|
13
|
+
defaultFields,
|
|
14
|
+
defaultChecks,
|
|
15
|
+
}: ChildNodeProps) {
|
|
16
|
+
const [node, setNode] = nodeState;
|
|
17
|
+
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
updateNode(node);
|
|
20
|
+
}, [node]);
|
|
21
|
+
|
|
22
|
+
function isValid(key: string, value: string) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
27
|
+
|
|
28
|
+
const fields: FieldArrayType<DateNodeType> = [];
|
|
29
|
+
|
|
30
|
+
const checks: FieldArrayType<DateNodeType> = [];
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<>
|
|
34
|
+
<FieldContainer>
|
|
35
|
+
{defaultFields}
|
|
36
|
+
{fields.map((field) => (
|
|
37
|
+
<NodeField
|
|
38
|
+
key={field.prop}
|
|
39
|
+
field={field}
|
|
40
|
+
node={node}
|
|
41
|
+
update={updateNodeByKeyLocal}
|
|
42
|
+
{...field.props}
|
|
43
|
+
/>
|
|
44
|
+
))}
|
|
45
|
+
</FieldContainer>
|
|
46
|
+
<FieldContainer>
|
|
47
|
+
{defaultChecks}
|
|
48
|
+
{checks.map((check) => (
|
|
49
|
+
<NodeCheckbox
|
|
50
|
+
key={check.prop}
|
|
51
|
+
field={check}
|
|
52
|
+
node={node}
|
|
53
|
+
update={updateNodeByKeyLocal}
|
|
54
|
+
{...check.props}
|
|
55
|
+
/>
|
|
56
|
+
))}
|
|
57
|
+
</FieldContainer>
|
|
58
|
+
</>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChildNodeProps,
|
|
3
|
+
FieldArrayType,
|
|
4
|
+
FileNodeEmpty as FileNodeType,
|
|
5
|
+
} from "../../../types/form-builder";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { FieldContainer, NodeCheckbox, NodeField } from "../node-child-helpers";
|
|
8
|
+
import { generateUpdateNodeByKeyLocal } from "../../../utils/form-builder";
|
|
9
|
+
|
|
10
|
+
export default function FileNode({
|
|
11
|
+
nodeState,
|
|
12
|
+
updateNode,
|
|
13
|
+
defaultFields,
|
|
14
|
+
defaultChecks,
|
|
15
|
+
}: ChildNodeProps) {
|
|
16
|
+
const [node, setNode] = nodeState;
|
|
17
|
+
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
updateNode(node);
|
|
20
|
+
}, [node]);
|
|
21
|
+
|
|
22
|
+
function isValid(key: string, value: string) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
27
|
+
|
|
28
|
+
const fields: FieldArrayType<FileNodeType> = [
|
|
29
|
+
{
|
|
30
|
+
prop: "filetype",
|
|
31
|
+
tooltip: "Require a specific file type. Leave blank for any filetype.",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const checks: FieldArrayType<FileNodeType> = [
|
|
36
|
+
{ prop: "multiple", title: "Multiple Files" },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
<FieldContainer>
|
|
42
|
+
{defaultFields}
|
|
43
|
+
{fields.map((field) => (
|
|
44
|
+
<NodeField
|
|
45
|
+
key={field.prop}
|
|
46
|
+
field={field}
|
|
47
|
+
node={node}
|
|
48
|
+
update={updateNodeByKeyLocal}
|
|
49
|
+
{...field.props}
|
|
50
|
+
/>
|
|
51
|
+
))}
|
|
52
|
+
</FieldContainer>
|
|
53
|
+
<FieldContainer>
|
|
54
|
+
{defaultChecks}
|
|
55
|
+
{checks.map((check) => (
|
|
56
|
+
<NodeCheckbox
|
|
57
|
+
key={check.prop}
|
|
58
|
+
field={check}
|
|
59
|
+
node={node}
|
|
60
|
+
update={updateNodeByKeyLocal}
|
|
61
|
+
{...check.props}
|
|
62
|
+
/>
|
|
63
|
+
))}
|
|
64
|
+
</FieldContainer>
|
|
65
|
+
</>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChildNodeProps,
|
|
3
|
+
FieldArrayType,
|
|
4
|
+
IntegerNode as IntegerNodeType,
|
|
5
|
+
} from "../../../types/form-builder";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { FieldContainer, NodeCheckbox, NodeField } from "../node-child-helpers";
|
|
8
|
+
import { generateUpdateNodeByKeyLocal } from "../../../utils/form-builder";
|
|
9
|
+
|
|
10
|
+
export default function IntegerNode({
|
|
11
|
+
nodeState,
|
|
12
|
+
updateNode,
|
|
13
|
+
defaultFields,
|
|
14
|
+
defaultChecks,
|
|
15
|
+
}: ChildNodeProps) {
|
|
16
|
+
const [node, setNode] = nodeState;
|
|
17
|
+
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
updateNode(node);
|
|
20
|
+
}, [node]);
|
|
21
|
+
|
|
22
|
+
function isValid(key: string, value: string) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
27
|
+
|
|
28
|
+
const fields: FieldArrayType<IntegerNodeType> = [];
|
|
29
|
+
|
|
30
|
+
const checks: FieldArrayType<IntegerNodeType> = [];
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<>
|
|
34
|
+
<FieldContainer>
|
|
35
|
+
{defaultFields}
|
|
36
|
+
{fields.map((field) => (
|
|
37
|
+
<NodeField
|
|
38
|
+
key={field.prop}
|
|
39
|
+
field={field}
|
|
40
|
+
node={node}
|
|
41
|
+
update={updateNodeByKeyLocal}
|
|
42
|
+
{...field.props}
|
|
43
|
+
/>
|
|
44
|
+
))}
|
|
45
|
+
</FieldContainer>
|
|
46
|
+
<FieldContainer>
|
|
47
|
+
{defaultChecks}
|
|
48
|
+
{checks.map((check) => (
|
|
49
|
+
<NodeCheckbox
|
|
50
|
+
key={check.prop}
|
|
51
|
+
field={check}
|
|
52
|
+
node={node}
|
|
53
|
+
update={updateNodeByKeyLocal}
|
|
54
|
+
{...check.props}
|
|
55
|
+
/>
|
|
56
|
+
))}
|
|
57
|
+
</FieldContainer>
|
|
58
|
+
</>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChildNodeProps,
|
|
3
|
+
FieldArrayType,
|
|
4
|
+
ObjectNodeEmpty,
|
|
5
|
+
} from "../../../types/form-builder";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { FieldContainer, NodeCheckbox, NodeField } from "../node-child-helpers";
|
|
8
|
+
import { generateUpdateNodeByKeyLocal } from "../../../utils/form-builder";
|
|
9
|
+
import { Button } from "@mui/material";
|
|
10
|
+
|
|
11
|
+
export default function ObjectNode({
|
|
12
|
+
nodeState,
|
|
13
|
+
updateNode,
|
|
14
|
+
defaultFields,
|
|
15
|
+
defaultChecks,
|
|
16
|
+
updatePath,
|
|
17
|
+
}: ChildNodeProps) {
|
|
18
|
+
const [node, setNode] = nodeState;
|
|
19
|
+
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
updateNode(node);
|
|
22
|
+
}, [node]);
|
|
23
|
+
|
|
24
|
+
function isValid(key: string, value: string) {
|
|
25
|
+
const n = node as ObjectNodeEmpty;
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
30
|
+
|
|
31
|
+
const fields: FieldArrayType<ObjectNodeEmpty> = [];
|
|
32
|
+
|
|
33
|
+
const checks: FieldArrayType<ObjectNodeEmpty> = [];
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<FieldContainer>
|
|
38
|
+
{defaultFields}
|
|
39
|
+
{fields.map((field) => (
|
|
40
|
+
<NodeField
|
|
41
|
+
key={field.prop}
|
|
42
|
+
field={field}
|
|
43
|
+
node={node}
|
|
44
|
+
update={updateNodeByKeyLocal}
|
|
45
|
+
{...field.props}
|
|
46
|
+
/>
|
|
47
|
+
))}
|
|
48
|
+
</FieldContainer>
|
|
49
|
+
<FieldContainer>
|
|
50
|
+
{defaultChecks}
|
|
51
|
+
{checks.map((check) => (
|
|
52
|
+
<NodeCheckbox
|
|
53
|
+
key={check.prop}
|
|
54
|
+
field={check}
|
|
55
|
+
node={node}
|
|
56
|
+
update={updateNodeByKeyLocal}
|
|
57
|
+
{...check.props}
|
|
58
|
+
/>
|
|
59
|
+
))}
|
|
60
|
+
</FieldContainer>
|
|
61
|
+
|
|
62
|
+
<Button onClick={updatePath} variant="contained" fullWidth>
|
|
63
|
+
Open
|
|
64
|
+
</Button>
|
|
65
|
+
</>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChildNodeProps,
|
|
3
|
+
FieldArrayType,
|
|
4
|
+
TextNodeEmpty,
|
|
5
|
+
} from "../../../types/form-builder";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { FieldContainer, NodeCheckbox, NodeField } from "../node-child-helpers";
|
|
8
|
+
import { generateUpdateNodeByKeyLocal } from "../../../utils/form-builder";
|
|
9
|
+
|
|
10
|
+
export default function TextNode({
|
|
11
|
+
nodeState,
|
|
12
|
+
updateNode,
|
|
13
|
+
defaultFields,
|
|
14
|
+
defaultChecks,
|
|
15
|
+
}: ChildNodeProps) {
|
|
16
|
+
const [node, setNode] = nodeState;
|
|
17
|
+
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
updateNode(node);
|
|
20
|
+
}, [node]);
|
|
21
|
+
|
|
22
|
+
function isValid(key: string, value: string) {
|
|
23
|
+
const n = node as TextNodeEmpty;
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const updateNodeByKeyLocal = generateUpdateNodeByKeyLocal(isValid, setNode);
|
|
28
|
+
|
|
29
|
+
const fields: FieldArrayType<TextNodeEmpty> = [
|
|
30
|
+
{ prop: "default" },
|
|
31
|
+
{ prop: "format" },
|
|
32
|
+
{ prop: "minLength", props: { type: "number" } },
|
|
33
|
+
{ prop: "maxLength", props: { type: "number" } },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const checks: FieldArrayType<TextNodeEmpty> = [];
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<>
|
|
40
|
+
<FieldContainer>
|
|
41
|
+
{defaultFields}
|
|
42
|
+
{fields.map((field) => (
|
|
43
|
+
<NodeField
|
|
44
|
+
key={field.prop}
|
|
45
|
+
field={field}
|
|
46
|
+
node={node}
|
|
47
|
+
update={updateNodeByKeyLocal}
|
|
48
|
+
{...field.props}
|
|
49
|
+
/>
|
|
50
|
+
))}
|
|
51
|
+
</FieldContainer>
|
|
52
|
+
<FieldContainer>
|
|
53
|
+
{defaultChecks}
|
|
54
|
+
{checks.map((check) => (
|
|
55
|
+
<NodeCheckbox
|
|
56
|
+
key={check.prop}
|
|
57
|
+
field={check}
|
|
58
|
+
node={node}
|
|
59
|
+
update={updateNodeByKeyLocal}
|
|
60
|
+
{...check.props}
|
|
61
|
+
/>
|
|
62
|
+
))}
|
|
63
|
+
</FieldContainer>
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
}
|