@wq/form-web 3.0.0-alpha.0
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/AutoForm.js +24 -0
- package/README.md +10 -0
- package/components/Checkbox.js +30 -0
- package/components/DateTime.js +14 -0
- package/components/DeleteForm.js +56 -0
- package/components/Draw.js +78 -0
- package/components/Fieldset.js +32 -0
- package/components/FieldsetArray.js +30 -0
- package/components/File.js +77 -0
- package/components/FileArray.js +132 -0
- package/components/FlatFieldset.js +30 -0
- package/components/FormError.js +19 -0
- package/components/FormRoot.js +32 -0
- package/components/GeoHelpIcon.js +42 -0
- package/components/HelperText.js +28 -0
- package/components/Hidden.js +24 -0
- package/components/IconSubmitButton.js +20 -0
- package/components/Image.js +10 -0
- package/components/Input.js +28 -0
- package/components/Radio.js +53 -0
- package/components/Select.js +191 -0
- package/components/SubmitButton.js +36 -0
- package/components/Toggle.js +52 -0
- package/components/index.js +50 -0
- package/index.js +3 -0
- package/package.json +47 -0
- package/src/AutoForm.js +17 -0
- package/src/components/Checkbox.js +28 -0
- package/src/components/DateTime.js +13 -0
- package/src/components/DeleteForm.js +52 -0
- package/src/components/Draw.js +82 -0
- package/src/components/Fieldset.js +24 -0
- package/src/components/FieldsetArray.js +27 -0
- package/src/components/File.js +73 -0
- package/src/components/FileArray.js +129 -0
- package/src/components/FlatFieldset.js +26 -0
- package/src/components/FormError.js +18 -0
- package/src/components/FormRoot.js +27 -0
- package/src/components/GeoHelpIcon.js +52 -0
- package/src/components/HelperText.js +28 -0
- package/src/components/Hidden.js +21 -0
- package/src/components/IconSubmitButton.js +18 -0
- package/src/components/Image.js +9 -0
- package/src/components/Input.js +30 -0
- package/src/components/Radio.js +38 -0
- package/src/components/Select.js +158 -0
- package/src/components/SubmitButton.js +38 -0
- package/src/components/Toggle.js +35 -0
- package/src/components/index.js +52 -0
- package/src/index.js +3 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useRef, useEffect } from "react";
|
|
2
|
+
import { useComponents, withWQ, createFallbackComponent } from "@wq/react";
|
|
3
|
+
import MapboxDraw from "@mapbox/mapbox-gl-draw";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
const DrawFallback = {
|
|
7
|
+
components: {
|
|
8
|
+
useControl: createFallbackComponent(
|
|
9
|
+
"useControl",
|
|
10
|
+
"@wq/map-gl",
|
|
11
|
+
"MapProvider",
|
|
12
|
+
),
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function Draw({ type, required, data, setData }) {
|
|
17
|
+
const types = type === "all" ? ["point", "line_string", "polygon"] : [type],
|
|
18
|
+
controls = {},
|
|
19
|
+
ref = useRef();
|
|
20
|
+
|
|
21
|
+
types.forEach((type) => (controls[type] = true));
|
|
22
|
+
|
|
23
|
+
if (!required) {
|
|
24
|
+
controls.trash = true;
|
|
25
|
+
}
|
|
26
|
+
const { useControl } = useComponents();
|
|
27
|
+
const draw = useControl(
|
|
28
|
+
() => {
|
|
29
|
+
const { classes } = MapboxDraw.constants;
|
|
30
|
+
for (const [key, value] of Object.entries(classes)) {
|
|
31
|
+
if (value.startsWith("mapboxgl-")) {
|
|
32
|
+
classes[key] = value.replace("mapboxgl-", "maplibregl-");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return new MapboxDraw({
|
|
36
|
+
displayControlsDefault: false,
|
|
37
|
+
controls,
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
({ map }) => {
|
|
41
|
+
map.on("draw.create", handleChange);
|
|
42
|
+
map.on("draw.delete", handleChange);
|
|
43
|
+
map.on("draw.update", handleChange);
|
|
44
|
+
map.on("draw.combine", handleChange);
|
|
45
|
+
map.on("draw.uncombine", handleChange);
|
|
46
|
+
},
|
|
47
|
+
({ map }) => {
|
|
48
|
+
map.off("draw.create", handleChange);
|
|
49
|
+
map.off("draw.delete", handleChange);
|
|
50
|
+
map.off("draw.update", handleChange);
|
|
51
|
+
map.off("draw.combine", handleChange);
|
|
52
|
+
map.off("draw.uncombine", handleChange);
|
|
53
|
+
},
|
|
54
|
+
{ position: "top-right" },
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
ref.current = { draw };
|
|
59
|
+
}, [draw]);
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (draw && data) {
|
|
63
|
+
draw.set(data);
|
|
64
|
+
}
|
|
65
|
+
}, [draw, data]);
|
|
66
|
+
|
|
67
|
+
function handleChange() {
|
|
68
|
+
const { draw } = ref.current;
|
|
69
|
+
setData(draw.getAll());
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Draw.propTypes = {
|
|
76
|
+
type: PropTypes.string,
|
|
77
|
+
required: PropTypes.boolean,
|
|
78
|
+
data: PropTypes.object,
|
|
79
|
+
setData: PropTypes.func,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export default withWQ(Draw, { fallback: DrawFallback });
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Card, Typography, CardContent } from "@mui/material";
|
|
3
|
+
import { withWQ } from "@wq/react";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
function Fieldset({ label, children }) {
|
|
7
|
+
return (
|
|
8
|
+
<Card sx={{ mb: 2 }}>
|
|
9
|
+
<CardContent>
|
|
10
|
+
{label && (
|
|
11
|
+
<Typography color="textSecondary">{label}</Typography>
|
|
12
|
+
)}
|
|
13
|
+
{children}
|
|
14
|
+
</CardContent>
|
|
15
|
+
</Card>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Fieldset.propTypes = {
|
|
20
|
+
label: PropTypes.string,
|
|
21
|
+
children: PropTypes.node,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default withWQ(Fieldset);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useComponents, withWQ, createFallbackComponents } from "@wq/react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
|
|
5
|
+
const FieldsetArrayFallback = {
|
|
6
|
+
components: createFallbackComponents(["View", "Button"], "@wq/material"),
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function FieldsetArray({ label, children, addRow }) {
|
|
10
|
+
const { View, Button } = useComponents();
|
|
11
|
+
return (
|
|
12
|
+
<View>
|
|
13
|
+
{children}
|
|
14
|
+
{addRow && (
|
|
15
|
+
<Button onClick={() => addRow()}>{`Add ${label}`}</Button>
|
|
16
|
+
)}
|
|
17
|
+
</View>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
FieldsetArray.propTypes = {
|
|
22
|
+
label: PropTypes.string,
|
|
23
|
+
children: PropTypes.node,
|
|
24
|
+
addRow: PropTypes.func,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default withWQ(FieldsetArray, { fallback: FieldsetArrayFallback });
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useMemo, useCallback, useRef } from "react";
|
|
2
|
+
import { withWQ } from "@wq/react";
|
|
3
|
+
import { useField } from "formik";
|
|
4
|
+
import { DropzoneArea } from "mui2-file-dropzone";
|
|
5
|
+
import { InputLabel } from "@mui/material";
|
|
6
|
+
import HelperText from "./HelperText.js";
|
|
7
|
+
import PropTypes from "prop-types";
|
|
8
|
+
|
|
9
|
+
function File({ name, accept, hint, label }) {
|
|
10
|
+
const [, { initialValue }, { setValue }] = useField(name),
|
|
11
|
+
loadedRef = useRef(null);
|
|
12
|
+
|
|
13
|
+
const initialFiles = useMemo(() => {
|
|
14
|
+
if (!initialValue || initialValue === "__clear__") {
|
|
15
|
+
return [];
|
|
16
|
+
} else if (initialValue.type && initialValue.body) {
|
|
17
|
+
return [initialValue.body];
|
|
18
|
+
} else if (typeof initialValue === "string") {
|
|
19
|
+
return [initialValue];
|
|
20
|
+
}
|
|
21
|
+
}, [initialValue]),
|
|
22
|
+
acceptedFiles = useMemo(
|
|
23
|
+
() => (accept ? accept.split(",") : null),
|
|
24
|
+
[accept],
|
|
25
|
+
),
|
|
26
|
+
setFile = useCallback(
|
|
27
|
+
(files) => {
|
|
28
|
+
if (!loadedRef.current) {
|
|
29
|
+
// initialFiles loaded
|
|
30
|
+
loadedRef.current = files && files.length ? files[0] : true;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (files && files.length) {
|
|
34
|
+
if (files[0] !== loadedRef.current) {
|
|
35
|
+
const { name, type } = files[0];
|
|
36
|
+
setValue({
|
|
37
|
+
name,
|
|
38
|
+
type,
|
|
39
|
+
body: files[0],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
} else if (initialValue) {
|
|
43
|
+
setValue("__clear__");
|
|
44
|
+
} else {
|
|
45
|
+
setValue(null);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
[initialValue],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<>
|
|
53
|
+
<InputLabel shrink>{label}</InputLabel>
|
|
54
|
+
<DropzoneArea
|
|
55
|
+
initialFiles={initialFiles}
|
|
56
|
+
acceptedFiles={acceptedFiles}
|
|
57
|
+
onChange={setFile}
|
|
58
|
+
filesLimit={1}
|
|
59
|
+
maxFileSize={100000000}
|
|
60
|
+
/>
|
|
61
|
+
<HelperText name={name} hint={hint} />
|
|
62
|
+
</>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
File.propTypes = {
|
|
67
|
+
name: PropTypes.string,
|
|
68
|
+
accept: PropTypes.string,
|
|
69
|
+
label: PropTypes.string,
|
|
70
|
+
hint: PropTypes.string,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default withWQ(File);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import React, { useMemo, useCallback, useRef } from "react";
|
|
2
|
+
import { useComponents, withWQ } from "@wq/react";
|
|
3
|
+
import { useField } from "formik";
|
|
4
|
+
import { DropzoneArea } from "mui2-file-dropzone";
|
|
5
|
+
import Fieldset from "./Fieldset.js";
|
|
6
|
+
import HelperText from "./HelperText.js";
|
|
7
|
+
import PropTypes from "prop-types";
|
|
8
|
+
|
|
9
|
+
const FileArrayFallback = {
|
|
10
|
+
components: {
|
|
11
|
+
Fieldset,
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function FileArray({ name, label, subform, hint, maxRows }) {
|
|
16
|
+
const [, { initialValue = [] }, { setValue }] = useField(name),
|
|
17
|
+
fileField = subform.find(
|
|
18
|
+
(field) => field.type === "file" || field.type === "image",
|
|
19
|
+
) || {
|
|
20
|
+
name: "file",
|
|
21
|
+
type: "file",
|
|
22
|
+
},
|
|
23
|
+
accept = fileField.type === "image" ? "image/*" : null,
|
|
24
|
+
loadedRef = useRef(null),
|
|
25
|
+
{ Fieldset } = useComponents();
|
|
26
|
+
|
|
27
|
+
const initialFiles = useMemo(() => {
|
|
28
|
+
if (!initialValue || initialValue.length === 0) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
return initialValue
|
|
32
|
+
.filter((row) => {
|
|
33
|
+
if (
|
|
34
|
+
!row[fileField.name] ||
|
|
35
|
+
row[fileField.name] === "__clear__"
|
|
36
|
+
) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
})
|
|
41
|
+
.map((row) => {
|
|
42
|
+
const value = row[fileField.name];
|
|
43
|
+
if (value.type && value.body) {
|
|
44
|
+
return value.body;
|
|
45
|
+
} else if (typeof value === "string") {
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}, [initialValue]),
|
|
50
|
+
acceptedFiles = useMemo(
|
|
51
|
+
() => (accept ? accept.split(",") : null),
|
|
52
|
+
[accept],
|
|
53
|
+
),
|
|
54
|
+
setFiles = useCallback(
|
|
55
|
+
(files) => {
|
|
56
|
+
if (!loadedRef.current) {
|
|
57
|
+
// initialFiles loaded
|
|
58
|
+
let fileIndex = 0;
|
|
59
|
+
loadedRef.current = initialValue.map((row) => {
|
|
60
|
+
let file;
|
|
61
|
+
if (
|
|
62
|
+
row[fileField.name] &&
|
|
63
|
+
row[fileField.name] !== "__clear__"
|
|
64
|
+
) {
|
|
65
|
+
file = files[fileIndex];
|
|
66
|
+
fileIndex++;
|
|
67
|
+
}
|
|
68
|
+
return { row, file };
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const nextValue = files.map((file, i) => {
|
|
73
|
+
const { row, file: initialFile } = loadedRef.current[i] || {
|
|
74
|
+
row: {},
|
|
75
|
+
file: null,
|
|
76
|
+
};
|
|
77
|
+
if (initialFile === file) {
|
|
78
|
+
return row;
|
|
79
|
+
} else {
|
|
80
|
+
return {
|
|
81
|
+
...row,
|
|
82
|
+
[fileField.name]: {
|
|
83
|
+
name: file.name,
|
|
84
|
+
type: file.type,
|
|
85
|
+
body: file,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
if (initialValue && nextValue.length < initialValue.length) {
|
|
91
|
+
initialValue.slice(nextValue.length).forEach((row) => {
|
|
92
|
+
nextValue.push({
|
|
93
|
+
...row,
|
|
94
|
+
[fileField.name]: "__clear__",
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
setValue(nextValue);
|
|
99
|
+
},
|
|
100
|
+
[initialValue],
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<Fieldset label={label}>
|
|
105
|
+
<DropzoneArea
|
|
106
|
+
initialFiles={initialFiles}
|
|
107
|
+
acceptedFiles={acceptedFiles}
|
|
108
|
+
onChange={setFiles}
|
|
109
|
+
filesLimit={maxRows}
|
|
110
|
+
/>
|
|
111
|
+
<HelperText name={name} hint={hint} />
|
|
112
|
+
</Fieldset>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
FileArray.Fieldset = function EmptyFieldset() {
|
|
117
|
+
return null;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
FileArray.propTypes = {
|
|
121
|
+
name: PropTypes.string,
|
|
122
|
+
accept: PropTypes.string,
|
|
123
|
+
label: PropTypes.string,
|
|
124
|
+
subform: PropTypes.arrayOf(PropTypes.object),
|
|
125
|
+
hint: PropTypes.string,
|
|
126
|
+
maxRows: PropTypes.number,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export default withWQ(FileArray, { fallback: FileArrayFallback });
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useComponents, withWQ, createFallbackComponent } from "@wq/react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
|
|
5
|
+
const FlatFieldsetFallback = {
|
|
6
|
+
components: {
|
|
7
|
+
Typography: createFallbackComponent("Typography", "@wq/material"),
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function FlatFieldset({ label, children }) {
|
|
12
|
+
const { Typography } = useComponents();
|
|
13
|
+
return (
|
|
14
|
+
<>
|
|
15
|
+
<Typography color="textSecondary">{label}</Typography>
|
|
16
|
+
{children}
|
|
17
|
+
</>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
FlatFieldset.propTypes = {
|
|
22
|
+
label: PropTypes.string,
|
|
23
|
+
children: PropTypes.node,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default withWQ(FlatFieldset, { fallback: FlatFieldsetFallback });
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { withWQ } from "@wq/react";
|
|
3
|
+
import { useField } from "formik";
|
|
4
|
+
import { FormHelperText } from "@mui/material";
|
|
5
|
+
|
|
6
|
+
function FormError(props) {
|
|
7
|
+
const [, { error }] = useField("__other__");
|
|
8
|
+
if (!error) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return (
|
|
12
|
+
<FormHelperText error {...props}>
|
|
13
|
+
{error}
|
|
14
|
+
</FormHelperText>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default withWQ(FormError);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { withWQ } from "@wq/react";
|
|
3
|
+
import { Form } from "formik";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
function FormRoot({ children }) {
|
|
7
|
+
return (
|
|
8
|
+
<div style={{ flex: 1, display: "flex", justifyContent: "center" }}>
|
|
9
|
+
<Form
|
|
10
|
+
style={{
|
|
11
|
+
width: "100%",
|
|
12
|
+
maxWidth: "70em",
|
|
13
|
+
padding: "1em",
|
|
14
|
+
boxSizing: "border-box",
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
17
|
+
{children}
|
|
18
|
+
</Form>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
FormRoot.propTypes = {
|
|
24
|
+
children: PropTypes.node,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default withWQ(FormRoot);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { withWQ } from "@wq/react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
|
|
5
|
+
function GeoHelpIcon({ name, type }) {
|
|
6
|
+
const iconClass = getIconClass(name, type);
|
|
7
|
+
if (!iconClass) {
|
|
8
|
+
return `{${name}}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<span
|
|
13
|
+
className={iconClass}
|
|
14
|
+
style={{
|
|
15
|
+
display: "inline-block",
|
|
16
|
+
width: 18,
|
|
17
|
+
height: 18,
|
|
18
|
+
verticalAlign: "middle",
|
|
19
|
+
}}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
GeoHelpIcon.propTypes = {
|
|
25
|
+
name: PropTypes.string,
|
|
26
|
+
type: PropTypes.string,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default withWQ(GeoHelpIcon);
|
|
30
|
+
|
|
31
|
+
const SHAPES = ["point", "line", "polygon"],
|
|
32
|
+
ICONS = SHAPES.map((shape) => `${shape.toUpperCase()}_ICON`);
|
|
33
|
+
|
|
34
|
+
function getIconClass(iconName, drawType) {
|
|
35
|
+
let shape = null;
|
|
36
|
+
|
|
37
|
+
if (iconName === "TOOL_ICON") {
|
|
38
|
+
if (drawType === "line_string") {
|
|
39
|
+
shape = "line";
|
|
40
|
+
} else if (SHAPES.includes(drawType)) {
|
|
41
|
+
shape = drawType;
|
|
42
|
+
}
|
|
43
|
+
} else if (ICONS.includes(iconName)) {
|
|
44
|
+
shape = SHAPES[ICONS.indexOf(iconName)];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (shape) {
|
|
48
|
+
return `mapbox-gl-draw_${shape}`;
|
|
49
|
+
} else {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { withWQ } from "@wq/react";
|
|
3
|
+
import { useFormikContext, getIn } from "formik";
|
|
4
|
+
import { FormHelperText } from "@mui/material";
|
|
5
|
+
import PropTypes from "prop-types";
|
|
6
|
+
|
|
7
|
+
function HelperText({ name, hint }) {
|
|
8
|
+
const { errors, touched } = useFormikContext(),
|
|
9
|
+
error = getIn(errors, name),
|
|
10
|
+
showError = !!error && !!getIn(touched, name);
|
|
11
|
+
|
|
12
|
+
if (showError) {
|
|
13
|
+
hint = error;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!hint) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return <FormHelperText error={!!showError}>{hint}</FormHelperText>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
HelperText.propTypes = {
|
|
24
|
+
name: PropTypes.string,
|
|
25
|
+
hint: PropTypes.string,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default withWQ(HelperText);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { withWQ } from "@wq/react";
|
|
3
|
+
import { Field } from "formik";
|
|
4
|
+
import HelperText from "./HelperText.js";
|
|
5
|
+
import PropTypes from "prop-types";
|
|
6
|
+
|
|
7
|
+
function Hidden(props) {
|
|
8
|
+
return (
|
|
9
|
+
<>
|
|
10
|
+
<Field {...props} type="hidden" />
|
|
11
|
+
<HelperText name={props.name} hint={props.hint} />
|
|
12
|
+
</>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Hidden.propTypes = {
|
|
17
|
+
name: PropTypes.string,
|
|
18
|
+
hint: PropTypes.string,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default withWQ(Hidden);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useComponents, withWQ, createFallbackComponent } from "@wq/react";
|
|
3
|
+
import { useFormikContext } from "formik";
|
|
4
|
+
|
|
5
|
+
const IconSubmitButtonFallback = {
|
|
6
|
+
components: {
|
|
7
|
+
IconButton: createFallbackComponent("IconButton", "@wq/material"),
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function IconSubmitButton(props) {
|
|
12
|
+
const { IconButton } = useComponents(),
|
|
13
|
+
{ isSubmitting } = useFormikContext();
|
|
14
|
+
|
|
15
|
+
return <IconButton type="submit" disabled={isSubmitting} {...props} />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default withWQ(IconSubmitButton, { fallback: IconSubmitButtonFallback });
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { withWQ } from "@wq/react";
|
|
3
|
+
import { Field } from "formik";
|
|
4
|
+
import { TextField } from "formik-mui";
|
|
5
|
+
import { useHtmlInput } from "@wq/form-common";
|
|
6
|
+
import PropTypes from "prop-types";
|
|
7
|
+
|
|
8
|
+
function Input({ hint, inputProps, ...rest }) {
|
|
9
|
+
const { name, type, maxLength } = useHtmlInput(rest);
|
|
10
|
+
return (
|
|
11
|
+
<Field
|
|
12
|
+
name={name}
|
|
13
|
+
fullWidth
|
|
14
|
+
margin="dense"
|
|
15
|
+
component={TextField}
|
|
16
|
+
helperText={hint}
|
|
17
|
+
inputProps={{ maxLength, ...inputProps }}
|
|
18
|
+
{...rest}
|
|
19
|
+
type={type}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
Input.propTypes = {
|
|
25
|
+
name: PropTypes.string,
|
|
26
|
+
hint: PropTypes.string,
|
|
27
|
+
inputProps: PropTypes.object,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default withWQ(Input);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { withWQ } from "@wq/react";
|
|
3
|
+
import { Field } from "formik";
|
|
4
|
+
import { RadioGroup } from "formik-mui";
|
|
5
|
+
import {
|
|
6
|
+
FormControl,
|
|
7
|
+
FormLabel,
|
|
8
|
+
FormControlLabel,
|
|
9
|
+
Radio as MuiRadio,
|
|
10
|
+
} from "@mui/material";
|
|
11
|
+
import HelperText from "./HelperText.js";
|
|
12
|
+
import PropTypes from "prop-types";
|
|
13
|
+
|
|
14
|
+
function Radio({ choices, label, ...rest }) {
|
|
15
|
+
return (
|
|
16
|
+
<FormControl component="fieldset" fullWidth margin="dense">
|
|
17
|
+
<FormLabel component="legend">{label}</FormLabel>
|
|
18
|
+
<Field component={RadioGroup} {...rest}>
|
|
19
|
+
{choices.map(({ name, label }) => (
|
|
20
|
+
<FormControlLabel
|
|
21
|
+
key={name}
|
|
22
|
+
value={name}
|
|
23
|
+
label={label}
|
|
24
|
+
control={<MuiRadio />}
|
|
25
|
+
/>
|
|
26
|
+
))}
|
|
27
|
+
</Field>
|
|
28
|
+
<HelperText name={rest.name} hint={rest.hint} />
|
|
29
|
+
</FormControl>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Radio.propTypes = {
|
|
34
|
+
choices: PropTypes.arrayOf(PropTypes.object),
|
|
35
|
+
label: PropTypes.string,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default withWQ(Radio);
|