@springmicro/forms 0.7.5 → 0.7.7

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.
@@ -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
+ }