@nolwenture/formik-jsonschema-form 1.0.11 → 1.2.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/README.md +7 -2
- package/dist/cjs/Form/fields/AnyField/AnyField.js +4 -1
- package/dist/cjs/Form/fields/DateField/DateField.js +6 -3
- package/dist/cjs/Form/fields/DateField/DateInput.js +113 -0
- package/dist/cjs/Form/fields/DateField/dateParsing.js +68 -0
- package/dist/cjs/Form/fields/DateField/index.js +4 -0
- package/dist/cjs/Form/fields/DateField/styledComponents.js +43 -0
- package/dist/cjs/Form/fields/FileUploadField/FileUploadField.js +1 -1
- package/dist/cjs/Form/fields/ObjectField/ObjectField.js +38 -7
- package/dist/cjs/Form/fields/ObjectField/ObjectFieldSection.js +2 -2
- package/dist/cjs/Form/fields/ObjectField/styledComponents.js +2 -1
- package/dist/cjs/Form/hooks/useSetDefault.js +8 -6
- package/dist/cjs/Form/templates/CollapsibleObjectFieldTemplate/CollapsibleObjectFieldTemplate.js +1 -1
- package/dist/cjs/utils/getHiddenProperties.js +11 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/cjs/utils/orderAdditionalProperties.js +6 -40
- package/dist/esm/Form/fields/AnyField/AnyField.js +5 -2
- package/dist/esm/Form/fields/DateField/DateField.js +6 -3
- package/dist/esm/Form/fields/DateField/DateInput.js +109 -0
- package/dist/esm/Form/fields/DateField/dateParsing.js +62 -0
- package/dist/esm/Form/fields/DateField/index.js +1 -0
- package/dist/esm/Form/fields/DateField/styledComponents.js +39 -1
- package/dist/esm/Form/fields/FileUploadField/FileUploadField.js +1 -1
- package/dist/esm/Form/fields/ObjectField/ObjectField.js +39 -8
- package/dist/esm/Form/fields/ObjectField/ObjectFieldSection.js +2 -2
- package/dist/esm/Form/fields/ObjectField/styledComponents.js +1 -0
- package/dist/esm/Form/hooks/useSetDefault.js +8 -6
- package/dist/esm/Form/templates/CollapsibleObjectFieldTemplate/CollapsibleObjectFieldTemplate.js +1 -1
- package/dist/esm/utils/getHiddenProperties.js +7 -0
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/orderAdditionalProperties.js +6 -40
- package/dist/types/Form/components/index.d.ts +1 -0
- package/dist/types/Form/fields/DateField/DateInput.d.ts +17 -0
- package/dist/types/Form/fields/DateField/dateParsing.d.ts +9 -0
- package/dist/types/Form/fields/DateField/index.d.ts +1 -0
- package/dist/types/Form/fields/DateField/styledComponents.d.ts +5 -1
- package/dist/types/Form/fields/ObjectField/index.d.ts +1 -0
- package/dist/types/Form/fields/ObjectField/styledComponents.d.ts +1 -0
- package/dist/types/Form/fields/index.d.ts +1 -0
- package/dist/types/utils/getHiddenProperties.d.ts +2 -0
- package/dist/types/utils/index.d.ts +1 -0
- package/dist/types/utils/orderAdditionalProperties.d.ts +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -491,7 +491,7 @@ const uiSchema = {
|
|
|
491
491
|
There are alternative fields available for certain types.
|
|
492
492
|
For `type: "string"` there is `DateField`, `TextAreaField` and partly `MultipleChoiceField`.
|
|
493
493
|
|
|
494
|
-
`DateField`
|
|
494
|
+
`DateField` stores ISO (YYYY-MM-DD), displays in the browser's language by default (or uiSchema["ui:props"].locale if provided), accepts pasted dates in many formats (e.g. 1.2.2025, 01/02/2025, 2025-01-01), includes a native calendar picker, and respects min/max (ISO).
|
|
495
495
|
|
|
496
496
|
```tsx
|
|
497
497
|
const schema = {
|
|
@@ -501,7 +501,12 @@ const schema = {
|
|
|
501
501
|
};
|
|
502
502
|
|
|
503
503
|
const uiSchema = {
|
|
504
|
-
date: {
|
|
504
|
+
date: {
|
|
505
|
+
"ui:field": "DateField",
|
|
506
|
+
"ui:props": {
|
|
507
|
+
locale: "fi"
|
|
508
|
+
},
|
|
509
|
+
}
|
|
505
510
|
};
|
|
506
511
|
```
|
|
507
512
|
|
|
@@ -12,6 +12,9 @@ const AnyField = (props) => {
|
|
|
12
12
|
const { name, schema, uiSchema } = props;
|
|
13
13
|
const [{ value }] = (0, formik_1.useField)(name);
|
|
14
14
|
const [type, setType] = (0, react_1.useState)(value !== undefined ? (0, utils_1.guessType)(value) : "string");
|
|
15
|
+
const {
|
|
16
|
+
//TODO: This is not right
|
|
17
|
+
props: { wrapper: wrapperProps = {} } = {}, } = (0, react_1.useMemo)(() => (0, utils_1.extractUiSchema)(uiSchema), [uiSchema]);
|
|
15
18
|
const enrichedSchema = (0, react_1.useMemo)(() => {
|
|
16
19
|
switch (type) {
|
|
17
20
|
case "object":
|
|
@@ -22,6 +25,6 @@ const AnyField = (props) => {
|
|
|
22
25
|
return { ...(schema || {}), type };
|
|
23
26
|
}
|
|
24
27
|
}, [type, schema]);
|
|
25
|
-
return ((0, jsx_runtime_1.jsxs)(styledComponents_1.AnyFieldWrapper, { children: [(0, jsx_runtime_1.jsx)("select", { value: type, onChange: (event) => setType(event.target.value), children: Object.keys(constants_1.COMPONENT_TYPES).map((type) => ((0, jsx_runtime_1.jsx)("option", { value: type, children: type }, type))) }), (0, jsx_runtime_1.jsx)(SchemaField_1.SchemaField, { name: name, schema: enrichedSchema, uiSchema: uiSchema })] }));
|
|
28
|
+
return ((0, jsx_runtime_1.jsxs)(styledComponents_1.AnyFieldWrapper, { ...wrapperProps, children: [(0, jsx_runtime_1.jsx)("select", { value: type, onChange: (event) => setType(event.target.value), children: Object.keys(constants_1.COMPONENT_TYPES).map((type) => ((0, jsx_runtime_1.jsx)("option", { value: type, children: type }, type))) }), (0, jsx_runtime_1.jsx)(SchemaField_1.SchemaField, { name: name, schema: enrichedSchema, uiSchema: uiSchema })] }));
|
|
26
29
|
};
|
|
27
30
|
exports.AnyField = AnyField;
|
|
@@ -7,14 +7,17 @@ const utils_1 = require("../../../utils");
|
|
|
7
7
|
const hooks_1 = require("../../hooks");
|
|
8
8
|
const FormRegistry_1 = require("../../FormRegistry");
|
|
9
9
|
const common_1 = require("../../styles/common");
|
|
10
|
+
const DateInput_1 = require("./DateInput");
|
|
10
11
|
const DateField = (props) => {
|
|
11
|
-
const { templates
|
|
12
|
+
const { templates } = (0, react_1.useContext)(FormRegistry_1.FormRegistry);
|
|
12
13
|
(0, hooks_1.useSetDefault)(props);
|
|
13
|
-
const { name, uiSchema } = props;
|
|
14
|
+
const { name, uiSchema, schema } = props;
|
|
14
15
|
const { props: inputProps } = (0, react_1.useMemo)(() => (0, utils_1.extractUiSchema)(uiSchema), [uiSchema]);
|
|
15
16
|
const SelectedFieldTemplate = (props.uiSchema?.["ui:template"] &&
|
|
16
17
|
templates[props.uiSchema?.["ui:template"]]) ??
|
|
17
18
|
templates.FieldTemplate;
|
|
18
|
-
|
|
19
|
+
const { label, placeholder, min, max, locale, helpText, disabled, errorMessages } = inputProps || {};
|
|
20
|
+
const readOnly = schema.readOnly === true;
|
|
21
|
+
return ((0, jsx_runtime_1.jsx)(SelectedFieldTemplate, { ...props, "data-fjsf-string": name, children: (0, jsx_runtime_1.jsx)(common_1.CommonFieldWrapper, { children: (0, jsx_runtime_1.jsx)(DateInput_1.DateInput, { name: name, label: label, placeholder: placeholder, min: min, max: max, locale: locale, helpText: helpText, disabled: disabled, readOnly: readOnly, errorMessages: errorMessages }) }) }));
|
|
19
22
|
};
|
|
20
23
|
exports.DateField = DateField;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DateInput = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const formik_1 = require("formik");
|
|
7
|
+
const styledComponents_1 = require("./styledComponents");
|
|
8
|
+
const dateParsing_1 = require("./dateParsing");
|
|
9
|
+
const fa_1 = require("react-icons/fa");
|
|
10
|
+
const FormRegistry_1 = require("../../FormRegistry");
|
|
11
|
+
const DateInput = ({ name, label, placeholder, min, max, locale, helpText, disabled, readOnly, errorMessages, }) => {
|
|
12
|
+
const { formLocalization } = (0, react_1.useContext)(FormRegistry_1.FormRegistry);
|
|
13
|
+
const effectiveLocale = locale ?? formLocalization?.fields?.DateField?.locale ?? navigator.language;
|
|
14
|
+
const firstDatePart = new Intl.DateTimeFormat(effectiveLocale)
|
|
15
|
+
.formatToParts(new Date(Date.UTC(2000, 0, 2)))
|
|
16
|
+
.find(p => p.type === "day" || p.type === "month" || p.type === "year");
|
|
17
|
+
const preferOrder = firstDatePart?.type === "month" ? "MDY" : "DMY";
|
|
18
|
+
const { setFieldTouched } = (0, formik_1.useFormikContext)();
|
|
19
|
+
const [field, meta, helpers] = (0, formik_1.useField)(name);
|
|
20
|
+
const { value } = field;
|
|
21
|
+
const { setValue, setError } = helpers;
|
|
22
|
+
const nativeRef = (0, react_1.useRef)(null);
|
|
23
|
+
const formatForDisplay = (0, react_1.useCallback)((iso) => {
|
|
24
|
+
if (!iso)
|
|
25
|
+
return "";
|
|
26
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(iso)) {
|
|
27
|
+
if (iso === "now") {
|
|
28
|
+
const today = new Date();
|
|
29
|
+
return new Intl.DateTimeFormat(effectiveLocale, { timeZone: "UTC" })
|
|
30
|
+
.format(new Date(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate())));
|
|
31
|
+
}
|
|
32
|
+
return "";
|
|
33
|
+
}
|
|
34
|
+
const dt = new Date(`${iso}T00:00:00Z`);
|
|
35
|
+
if (Number.isNaN(dt.getTime()))
|
|
36
|
+
return "";
|
|
37
|
+
return new Intl.DateTimeFormat(effectiveLocale, { timeZone: "UTC" }).format(dt);
|
|
38
|
+
}, [effectiveLocale]);
|
|
39
|
+
const [displayValue, setDisplayValue] = (0, react_1.useState)(formatForDisplay(value));
|
|
40
|
+
(0, react_1.useEffect)(() => {
|
|
41
|
+
if (!value)
|
|
42
|
+
return setDisplayValue("");
|
|
43
|
+
setDisplayValue(formatForDisplay(value));
|
|
44
|
+
}, [value, formatForDisplay]);
|
|
45
|
+
const hasExternalError = !!meta.error && meta.touched;
|
|
46
|
+
const withinBounds = (0, react_1.useCallback)((iso) => {
|
|
47
|
+
if (min && iso < min)
|
|
48
|
+
return false;
|
|
49
|
+
if (max && iso > max)
|
|
50
|
+
return false;
|
|
51
|
+
return true;
|
|
52
|
+
}, [min, max]);
|
|
53
|
+
const outOfRangeMessage = (0, react_1.useCallback)(() => {
|
|
54
|
+
const fallback = (min && max && `Date must be between ${min} and ${max}.`) ||
|
|
55
|
+
"Date is out of range.";
|
|
56
|
+
const raw = errorMessages?.outOfRange;
|
|
57
|
+
if (typeof raw === "function") {
|
|
58
|
+
return raw({ min, max });
|
|
59
|
+
}
|
|
60
|
+
const s = typeof raw === "string" ? raw : fallback;
|
|
61
|
+
return s.replace(/\{min\}/g, min ?? "").replace(/\{max\}/g, max ?? "");
|
|
62
|
+
}, [errorMessages, min, max]);
|
|
63
|
+
const invalidMessage = errorMessages?.invalid ?? "Enter a valid date";
|
|
64
|
+
const onValueChange = (0, react_1.useCallback)((isoDate) => {
|
|
65
|
+
setFieldTouched(name, true, false);
|
|
66
|
+
if (!withinBounds(isoDate)) {
|
|
67
|
+
setError(outOfRangeMessage());
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
setError(undefined);
|
|
71
|
+
setValue(isoDate);
|
|
72
|
+
}, [name, setFieldTouched, setValue, setError, withinBounds, outOfRangeMessage]);
|
|
73
|
+
const openPicker = () => {
|
|
74
|
+
const el = nativeRef.current;
|
|
75
|
+
if (!el || disabled || readOnly)
|
|
76
|
+
return;
|
|
77
|
+
try {
|
|
78
|
+
if (typeof el.showPicker === "function")
|
|
79
|
+
el.showPicker();
|
|
80
|
+
else {
|
|
81
|
+
el.focus();
|
|
82
|
+
el.click();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
el.focus();
|
|
87
|
+
el.click();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const handleParseOrError = (0, react_1.useCallback)((raw) => {
|
|
91
|
+
if (readOnly || disabled)
|
|
92
|
+
return;
|
|
93
|
+
const newDate = (0, dateParsing_1.parseDateString)(raw, preferOrder);
|
|
94
|
+
setFieldTouched(name, true, false);
|
|
95
|
+
if (newDate) {
|
|
96
|
+
onValueChange((0, dateParsing_1.toIsoDateString)(newDate));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
setError(invalidMessage);
|
|
100
|
+
}
|
|
101
|
+
}, [disabled, readOnly, preferOrder, name, onValueChange, setError, setFieldTouched, invalidMessage]);
|
|
102
|
+
const handlePaste = (e) => {
|
|
103
|
+
if (readOnly || disabled)
|
|
104
|
+
return;
|
|
105
|
+
e.preventDefault();
|
|
106
|
+
const text = e.clipboardData.getData("text")?.trim();
|
|
107
|
+
handleParseOrError(text ?? "");
|
|
108
|
+
};
|
|
109
|
+
return ((0, jsx_runtime_1.jsxs)(styledComponents_1.Wrapper, { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: `${name}-display`, children: label }), (0, jsx_runtime_1.jsxs)(styledComponents_1.Row, { children: [(0, jsx_runtime_1.jsx)(styledComponents_1.DisplayInput, { id: `${name}-display`, type: "text", placeholder: placeholder, autoComplete: "off", inputMode: "numeric", "aria-describedby": helpText ? `${name}-help` : undefined, "aria-invalid": hasExternalError, value: displayValue, onChange: (e) => setDisplayValue(e.target.value), onBlur: (e) => handleParseOrError(e.target.value), onPaste: handlePaste, disabled: disabled || readOnly, readOnly: readOnly }), !readOnly && ((0, jsx_runtime_1.jsx)(styledComponents_1.HiddenNative, { ref: nativeRef, id: `${name}-native`, type: "date", min: min, max: max, value: value ?? "", onChange: (e) => {
|
|
110
|
+
onValueChange(e.target.value);
|
|
111
|
+
}, tabIndex: -1, "aria-hidden": "true" })), (0, jsx_runtime_1.jsx)(styledComponents_1.PickerButton, { type: "button", onClick: openPicker, "aria-label": "Date picker", title: "Date picker", disabled: disabled || readOnly, children: (0, jsx_runtime_1.jsx)(fa_1.FaCalendar, {}) })] })] }));
|
|
112
|
+
};
|
|
113
|
+
exports.DateInput = DateInput;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toIsoDateString = toIsoDateString;
|
|
4
|
+
exports.isValidYMD = isValidYMD;
|
|
5
|
+
exports.ymdToDate = ymdToDate;
|
|
6
|
+
exports.parseDateString = parseDateString;
|
|
7
|
+
function toIsoDateString(date) {
|
|
8
|
+
return date.toISOString().slice(0, 10);
|
|
9
|
+
}
|
|
10
|
+
function isValidYMD(y, m, d) {
|
|
11
|
+
if (!y || !m || !d)
|
|
12
|
+
return false;
|
|
13
|
+
const dt = new Date(Date.UTC(y, m - 1, d));
|
|
14
|
+
return (dt.getUTCFullYear() === y &&
|
|
15
|
+
dt.getUTCMonth() === m - 1 &&
|
|
16
|
+
dt.getUTCDate() === d);
|
|
17
|
+
}
|
|
18
|
+
function ymdToDate({ y, m, d, }) {
|
|
19
|
+
if (!isValidYMD(y, m, d))
|
|
20
|
+
return undefined;
|
|
21
|
+
return new Date(Date.UTC(y, m - 1, d));
|
|
22
|
+
}
|
|
23
|
+
function parseDateString(input, preferOrder) {
|
|
24
|
+
const s = input.trim();
|
|
25
|
+
if (!s)
|
|
26
|
+
return undefined;
|
|
27
|
+
let m = s.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/) ||
|
|
28
|
+
s.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/);
|
|
29
|
+
if (m) {
|
|
30
|
+
const y = +m[1], mo = +m[2], d = +m[3];
|
|
31
|
+
return ymdToDate({ y, m: mo, d });
|
|
32
|
+
}
|
|
33
|
+
m = s.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/);
|
|
34
|
+
if (m) {
|
|
35
|
+
const d = +m[1], mo = +m[2], y = +m[3];
|
|
36
|
+
return ymdToDate({ y, m: mo, d });
|
|
37
|
+
}
|
|
38
|
+
m = s.match(/^(\d{1,2})\.(\d{1,2})\.(\d{2})$/);
|
|
39
|
+
if (m) {
|
|
40
|
+
const d = +m[1], mo = +m[2], y = 2000 + +m[3];
|
|
41
|
+
return ymdToDate({ y, m: mo, d });
|
|
42
|
+
}
|
|
43
|
+
m = s.match(/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/);
|
|
44
|
+
if (m) {
|
|
45
|
+
const a = +m[1], b = +m[2], y = +m[3] < 100 ? 2000 + +m[3] : +m[3];
|
|
46
|
+
const dmy = ymdToDate({ y, m: b, d: a });
|
|
47
|
+
const mdy = ymdToDate({ y, m: a, d: b });
|
|
48
|
+
if (dmy && !mdy)
|
|
49
|
+
return dmy;
|
|
50
|
+
if (!dmy && mdy)
|
|
51
|
+
return mdy;
|
|
52
|
+
if (dmy && mdy)
|
|
53
|
+
return preferOrder === "MDY" ? mdy : dmy;
|
|
54
|
+
}
|
|
55
|
+
const tryPatterns = [
|
|
56
|
+
/^(\d{1,2})-(\d{1,2})-(\d{4})$/,
|
|
57
|
+
/^(\d{1,2}) (\d{1,2}) (\d{4})$/,
|
|
58
|
+
];
|
|
59
|
+
for (const r of tryPatterns) {
|
|
60
|
+
const mm = s.match(r);
|
|
61
|
+
if (mm) {
|
|
62
|
+
const d = +mm[1], mo = +mm[2], y = +mm[3];
|
|
63
|
+
if (isValidYMD(y, mo, d))
|
|
64
|
+
return ymdToDate({ y, m: mo, d });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
@@ -32,7 +32,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
36
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
exports.fields = exports.components = void 0;
|
|
37
40
|
exports.components = __importStar(require("./styledComponents"));
|
|
38
41
|
exports.fields = __importStar(require("./DateField"));
|
|
42
|
+
__exportStar(require("./DateInput"), exports);
|
|
@@ -1,2 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PickerButton = exports.HiddenNative = exports.DisplayInput = exports.Row = exports.Wrapper = void 0;
|
|
7
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
8
|
+
exports.Wrapper = styled_components_1.default.div `
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
max-width: 360px;
|
|
12
|
+
`;
|
|
13
|
+
exports.Row = styled_components_1.default.div `
|
|
14
|
+
position: relative;
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
`;
|
|
18
|
+
exports.DisplayInput = styled_components_1.default.input `
|
|
19
|
+
flex: 1;
|
|
20
|
+
`;
|
|
21
|
+
exports.HiddenNative = styled_components_1.default.input `
|
|
22
|
+
position: absolute;
|
|
23
|
+
opacity: 0;
|
|
24
|
+
pointer-events: none;
|
|
25
|
+
width: 0;
|
|
26
|
+
height: 0;
|
|
27
|
+
`;
|
|
28
|
+
exports.PickerButton = styled_components_1.default.button `
|
|
29
|
+
position: relative;
|
|
30
|
+
left: -40px;
|
|
31
|
+
border: none;
|
|
32
|
+
background: inherit;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
font: inherit;
|
|
35
|
+
&:focus {
|
|
36
|
+
box-shadow: none;;
|
|
37
|
+
}
|
|
38
|
+
&:disabled {
|
|
39
|
+
cursor: not-allowed;
|
|
40
|
+
opacity: 0.6;
|
|
41
|
+
}
|
|
42
|
+
svg {
|
|
43
|
+
display: flex;
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
@@ -64,6 +64,6 @@ const FileUploadField = (props) => {
|
|
|
64
64
|
const SelectedFieldTemplate = (props.uiSchema?.["ui:template"] &&
|
|
65
65
|
templates[props.uiSchema?.["ui:template"]]) ??
|
|
66
66
|
templates.FieldTemplate;
|
|
67
|
-
return ((0, jsx_runtime_1.jsx)(SelectedFieldTemplate, { ...props, "data-fjsf-object": name, children: (0, jsx_runtime_1.jsx)(FileUploadFieldInput, { ...inputProps, name: name, value: value, handleRemoveFile: handleRemoveFile, uploadedFile: uploadedFile, setFieldValue: setFieldValue, handleFileUpload: handleFileUpload, uploadProgress: uploadProgress, removeButton: uiSchema["ui:removeButton"], uploadButtonText: uiSchema["ui:uploadButtonText"], infoText: uiSchema["ui:infoText"], hideRemoveButton: inputProps?.removeButton
|
|
67
|
+
return ((0, jsx_runtime_1.jsx)(SelectedFieldTemplate, { ...props, "data-fjsf-object": name, children: (0, jsx_runtime_1.jsx)(FileUploadFieldInput, { ...inputProps, name: name, value: value, handleRemoveFile: handleRemoveFile, uploadedFile: uploadedFile, setFieldValue: setFieldValue, handleFileUpload: handleFileUpload, uploadProgress: uploadProgress, removeButton: uiSchema["ui:removeButton"], uploadButtonText: uiSchema["ui:uploadButtonText"], infoText: uiSchema["ui:infoText"], hideRemoveButton: inputProps?.removeButton?.hidden }) }));
|
|
68
68
|
};
|
|
69
69
|
exports.FileUploadField = FileUploadField;
|
|
@@ -35,10 +35,11 @@ const ObjectField = (props) => {
|
|
|
35
35
|
}
|
|
36
36
|
}, [valuesToRemove]);
|
|
37
37
|
const propertyKeys = (0, react_1.useMemo)(() => Object.keys(properties || {}), [properties]);
|
|
38
|
-
const
|
|
39
|
-
const orderedProperties = (0, utils_1.orderByUiSchema)(uiSchema?.["ui:order"],
|
|
40
|
-
const
|
|
41
|
-
const
|
|
38
|
+
const additionalPropertyKeys = (0, react_1.useMemo)(() => Object.keys(value || {}).filter((key) => !propertyKeys.includes(key)), [value, propertyKeys]);
|
|
39
|
+
const orderedProperties = (0, utils_1.orderByUiSchema)(uiSchema?.["ui:order"], propertyKeys);
|
|
40
|
+
const hiddenProperties = (0, utils_1.getHiddenProperties)(uiSchema?.["ui:order"], propertyKeys);
|
|
41
|
+
const orderedAdditionalProperties = (0, utils_1.orderAdditionalProperties)(uiSchema?.["ui:order"], additionalPropertyKeys);
|
|
42
|
+
const hiddenAdditionalProperties = (0, utils_1.getHiddenProperties)(uiSchema?.["ui:order"], additionalPropertyKeys);
|
|
42
43
|
const getObjectFieldButton = ({ purpose, onClick, uiSchema, }) => {
|
|
43
44
|
switch (purpose) {
|
|
44
45
|
case types_1.ObjectFieldButtonPurpose.ADD:
|
|
@@ -58,6 +59,7 @@ const ObjectField = (props) => {
|
|
|
58
59
|
(props.uiSchema?.["ui:options"]?.isCollapsible
|
|
59
60
|
? templates.CollapsibleObjectFieldTemplate
|
|
60
61
|
: templates.ObjectFieldTemplate);
|
|
62
|
+
const showAdditionalProperties = !hideUnmarkedAdditionalProperties || !!additionalProperties;
|
|
61
63
|
return ((0, jsx_runtime_1.jsx)(styledComponents_1.ObjectFieldWrapper, { children: (0, jsx_runtime_1.jsxs)(SelectedObjectFieldTemplate, { ...props, "data-fjsf-object": name || "ROOT", "data-fjsf-level": !name ? 0 : name.split(".").length, children: [orderedProperties
|
|
62
64
|
.map((child) => {
|
|
63
65
|
if (typeof child === "string") {
|
|
@@ -76,10 +78,28 @@ const ObjectField = (props) => {
|
|
|
76
78
|
}) }, fields.join("_")));
|
|
77
79
|
}
|
|
78
80
|
})
|
|
79
|
-
.filter((x) => x), (
|
|
80
|
-
|
|
81
|
+
.filter((x) => x), hiddenProperties.map((child) => {
|
|
82
|
+
const childSchema = properties?.[child];
|
|
83
|
+
if (!childSchema)
|
|
84
|
+
return undefined;
|
|
85
|
+
const childUiSchema = uiSchema?.[child];
|
|
86
|
+
return ((0, jsx_runtime_1.jsx)(SchemaField, { required: required?.includes(child), name: name ? [name, child].join(".") : child, schema: prepareChildSchema(childSchema, schema), uiSchema: {
|
|
87
|
+
...childUiSchema,
|
|
88
|
+
props: {
|
|
89
|
+
...childUiSchema?.props,
|
|
90
|
+
wrapper: {
|
|
91
|
+
...childUiSchema?.props?.wrapper,
|
|
92
|
+
style: {
|
|
93
|
+
...childUiSchema?.props?.wrapper?.style,
|
|
94
|
+
display: "none",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
}, style: { display: "none" } }, child));
|
|
99
|
+
}), showAdditionalProperties &&
|
|
100
|
+
orderedAdditionalProperties.map((childName) => {
|
|
81
101
|
let correctUiSchema = uiSchema?.[childName];
|
|
82
|
-
if (uiSchema
|
|
102
|
+
if (uiSchema?.properties?.["ui:order"] !== undefined &&
|
|
83
103
|
uiSchema?.[childName]?.["ui:order"] === undefined) {
|
|
84
104
|
correctUiSchema = {
|
|
85
105
|
...correctUiSchema,
|
|
@@ -94,6 +114,17 @@ const ObjectField = (props) => {
|
|
|
94
114
|
},
|
|
95
115
|
uiSchema: uiSchema,
|
|
96
116
|
}) })] }, childName));
|
|
117
|
+
}), showAdditionalProperties &&
|
|
118
|
+
hiddenAdditionalProperties.map((childName) => {
|
|
119
|
+
let correctUiSchema = uiSchema?.[childName];
|
|
120
|
+
if (uiSchema.properties?.["ui:order"] !== undefined &&
|
|
121
|
+
uiSchema?.[childName]?.["ui:order"] === undefined) {
|
|
122
|
+
correctUiSchema = {
|
|
123
|
+
...correctUiSchema,
|
|
124
|
+
"ui:order": uiSchema.properties?.["ui:order"],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return ((0, jsx_runtime_1.jsx)(ObjectFieldItem, { style: { display: "none" }, children: (0, jsx_runtime_1.jsx)(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema: correctUiSchema }, childName) }, childName));
|
|
97
128
|
}), additionalProperties &&
|
|
98
129
|
getObjectFieldButton({
|
|
99
130
|
purpose: types_1.ObjectFieldButtonPurpose.ADD,
|
|
@@ -7,11 +7,11 @@ const FormRegistry_1 = require("../../FormRegistry");
|
|
|
7
7
|
const styledComponents_1 = require("./styledComponents");
|
|
8
8
|
const ObjectFieldSection = ({ title, collapsible, children, }) => {
|
|
9
9
|
const [collapsed, setCollapsed] = (0, react_1.useState)(collapsible);
|
|
10
|
-
const { components: { ObjectFieldSectionWrapper, ObjectFieldSectionTitle }, } = (0, react_1.useContext)(FormRegistry_1.FormRegistry);
|
|
10
|
+
const { components: { ObjectFieldSectionWrapper, ObjectFieldSectionTitle, ObjectFieldSectionChildrenWrapper, }, } = (0, react_1.useContext)(FormRegistry_1.FormRegistry);
|
|
11
11
|
return ((0, jsx_runtime_1.jsxs)(ObjectFieldSectionWrapper, { children: [(0, jsx_runtime_1.jsxs)(ObjectFieldSectionTitle, { onClick: () => {
|
|
12
12
|
if (collapsible) {
|
|
13
13
|
setCollapsed((currentState) => !currentState);
|
|
14
14
|
}
|
|
15
|
-
}, children: [title, (0, jsx_runtime_1.jsx)(styledComponents_1.IconWrapper, { children: collapsible && (collapsed ? "▸" : "▾") })] }),
|
|
15
|
+
}, children: [title, (0, jsx_runtime_1.jsx)(styledComponents_1.IconWrapper, { children: collapsible && (collapsed ? "▸" : "▾") })] }), (0, jsx_runtime_1.jsx)(ObjectFieldSectionChildrenWrapper, { style: collapsed ? { display: "none" } : undefined, children: children })] }));
|
|
16
16
|
};
|
|
17
17
|
exports.ObjectFieldSection = ObjectFieldSection;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ObjectFieldSectionTitle = exports.ObjectFieldSectionWrapper = exports.ObjectFieldAddButton = exports.ObjectFieldRemoveButton = exports.ObjectFieldDownButton = exports.ObjectFieldUpButton = exports.ObjectFieldButton = exports.ObjectFieldItemButtons = exports.ObjectFieldItem = exports.ObjectFieldWrapper = exports.IconWrapper = void 0;
|
|
3
|
+
exports.ObjectFieldSectionChildrenWrapper = exports.ObjectFieldSectionTitle = exports.ObjectFieldSectionWrapper = exports.ObjectFieldAddButton = exports.ObjectFieldRemoveButton = exports.ObjectFieldDownButton = exports.ObjectFieldUpButton = exports.ObjectFieldButton = exports.ObjectFieldItemButtons = exports.ObjectFieldItem = exports.ObjectFieldWrapper = exports.IconWrapper = void 0;
|
|
4
4
|
const styled_components_1 = require("styled-components");
|
|
5
5
|
const common_1 = require("../../styles/common");
|
|
6
6
|
const component_library_1 = require("@nolwenture/component-library");
|
|
@@ -38,3 +38,4 @@ exports.ObjectFieldSectionTitle = styled_components_1.styled.legend `
|
|
|
38
38
|
margin: 0;
|
|
39
39
|
justify-content: space-between;
|
|
40
40
|
`;
|
|
41
|
+
exports.ObjectFieldSectionChildrenWrapper = styled_components_1.styled.div ``;
|
|
@@ -10,13 +10,15 @@ const useSetDefault = (props) => {
|
|
|
10
10
|
const [{ value }, , { setValue }] = (0, formik_1.useField)(props.name);
|
|
11
11
|
(0, react_1.useEffect)(() => {
|
|
12
12
|
let newValue = value;
|
|
13
|
-
if (value === "now" && props.schema.format === "date") {
|
|
14
|
-
const today = new Date().toISOString().split("T")[0];
|
|
15
|
-
newValue = today;
|
|
16
|
-
}
|
|
17
13
|
if (!newValue) {
|
|
18
14
|
if (props.schema.default !== undefined) {
|
|
19
|
-
|
|
15
|
+
if (props.schema.format === "date" && props.schema.default === "now") {
|
|
16
|
+
const today = new Date().toISOString().split("T")[0];
|
|
17
|
+
newValue = today;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
newValue = props.schema.default;
|
|
21
|
+
}
|
|
20
22
|
}
|
|
21
23
|
else if (props.forceDefaultValue) {
|
|
22
24
|
newValue = (0, utils_1.getDefaultValueForType)(props.schema.type);
|
|
@@ -25,6 +27,6 @@ const useSetDefault = (props) => {
|
|
|
25
27
|
if (newValue && newValue !== value) {
|
|
26
28
|
setValue(newValue);
|
|
27
29
|
}
|
|
28
|
-
}, [
|
|
30
|
+
}, []);
|
|
29
31
|
};
|
|
30
32
|
exports.useSetDefault = useSetDefault;
|
package/dist/cjs/Form/templates/CollapsibleObjectFieldTemplate/CollapsibleObjectFieldTemplate.js
CHANGED
|
@@ -36,6 +36,6 @@ const CollapsibleObjectFieldTemplate = (props) => {
|
|
|
36
36
|
const hide = collapsed;
|
|
37
37
|
return ((0, jsx_runtime_1.jsxs)(Wrapper, { ...mergedWrapperProps, children: [(0, jsx_runtime_1.jsxs)(TitleInfoWrapper, { children: [title && ((0, jsx_runtime_1.jsx)(Toggle, { onClick: () => setCollapsed(!collapsed),
|
|
38
38
|
//ariaExpanded={!hide}
|
|
39
|
-
ariaLabel: ariaLabel ?? name, children: (0, jsx_runtime_1.jsxs)(Title, { ...titleProps, htmlFor: name, children: [title, props?.required && (0, jsx_runtime_1.jsx)(RequiredIndicator, {}), (0, jsx_runtime_1.jsx)(Icon, { children: hide ? collapsedIcon ?? "▸" : openIcon ?? "▾" })] }) })), info && (0, jsx_runtime_1.jsx)(Info, { ...info })] }), description && ((0, jsx_runtime_1.jsx)(Description, { ...descriptionProps, children: description })),
|
|
39
|
+
ariaLabel: ariaLabel ?? name, children: (0, jsx_runtime_1.jsxs)(Title, { ...titleProps, htmlFor: name, children: [title, props?.required && (0, jsx_runtime_1.jsx)(RequiredIndicator, {}), (0, jsx_runtime_1.jsx)(Icon, { children: hide ? collapsedIcon ?? "▸" : openIcon ?? "▾" })] }) })), info && (0, jsx_runtime_1.jsx)(Info, { ...info })] }), description && ((0, jsx_runtime_1.jsx)(Description, { ...descriptionProps, children: description })), (0, jsx_runtime_1.jsx)(ChildrenWrapper, { style: hide ? { display: "none" } : undefined, children: children }), help && (0, jsx_runtime_1.jsx)(Help, { ...helpProps, children: help })] }));
|
|
40
40
|
};
|
|
41
41
|
exports.CollapsibleObjectFieldTemplate = CollapsibleObjectFieldTemplate;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getHiddenProperties = void 0;
|
|
4
|
+
const getHiddenProperties = (order, properties) => {
|
|
5
|
+
if (!order || order.includes("*")) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const propertiesInOrder = order.flatMap((entry) => typeof entry === "string" ? entry : entry.fields);
|
|
9
|
+
return properties.filter((key) => !propertiesInOrder.includes(key));
|
|
10
|
+
};
|
|
11
|
+
exports.getHiddenProperties = getHiddenProperties;
|
package/dist/cjs/utils/index.js
CHANGED
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./deepOverlap"), exports);
|
|
18
18
|
__exportStar(require("./extractUiSchema"), exports);
|
|
19
19
|
__exportStar(require("./getEnums"), exports);
|
|
20
|
+
__exportStar(require("./getHiddenProperties"), exports);
|
|
20
21
|
__exportStar(require("./getTitleAndDescription"), exports);
|
|
21
22
|
__exportStar(require("./getTypes"), exports);
|
|
22
23
|
__exportStar(require("./mergeSchemas"), exports);
|
|
@@ -1,46 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.orderAdditionalProperties = orderAdditionalProperties;
|
|
4
|
+
const orderByUiSchema_1 = require("./orderByUiSchema");
|
|
4
5
|
function orderAdditionalProperties(uiOrderArray, valuesArray) {
|
|
5
|
-
if (uiOrderArray.length === 0)
|
|
6
|
+
if (!uiOrderArray || uiOrderArray.length === 0)
|
|
6
7
|
return valuesArray;
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
finalArray = filteredValues(uiOrderArray);
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
const uiOrderArrayWithoutAsterisk = uiOrderArray.filter((item) => item !== "*");
|
|
15
|
-
if (uiOrderArray.length === 1) {
|
|
16
|
-
finalArray = valuesArray;
|
|
17
|
-
}
|
|
18
|
-
else if (uiOrderArray.indexOf("*") === 0) {
|
|
19
|
-
// wildcard is first element
|
|
20
|
-
const individualValues = valuesArray.filter((element) => !uiOrderArrayWithoutAsterisk.includes(element));
|
|
21
|
-
const commonValues = filteredValues(uiOrderArrayWithoutAsterisk);
|
|
22
|
-
finalArray = [...individualValues, ...commonValues];
|
|
23
|
-
}
|
|
24
|
-
else if (uiOrderArray.indexOf("*") === uiOrderArray.length - 1) {
|
|
25
|
-
// wildcard is final element
|
|
26
|
-
const individualValues = valuesArray.filter((element) => !uiOrderArrayWithoutAsterisk.includes(element));
|
|
27
|
-
const commonValues = filteredValues(uiOrderArrayWithoutAsterisk);
|
|
28
|
-
finalArray = [...commonValues, ...individualValues];
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
// wildcard is somewhere in the middle
|
|
32
|
-
const indexForUnspecified = uiOrderArray.indexOf("*");
|
|
33
|
-
const definedBefore = uiOrderArray.slice(0, indexForUnspecified);
|
|
34
|
-
const definedAfter = uiOrderArray.slice(indexForUnspecified + 1);
|
|
35
|
-
const commonBeforeValues = filteredValues(definedBefore);
|
|
36
|
-
const commonAfterValues = filteredValues(definedAfter);
|
|
37
|
-
const individualValues = valuesArray.filter((element) => ![...commonBeforeValues, ...commonAfterValues].includes(element));
|
|
38
|
-
finalArray = [
|
|
39
|
-
...commonBeforeValues,
|
|
40
|
-
...individualValues,
|
|
41
|
-
...commonAfterValues,
|
|
42
|
-
];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return finalArray;
|
|
8
|
+
const additionalPropertiesOrder = uiOrderArray
|
|
9
|
+
.flatMap((entry) => (typeof entry === "string" ? entry : entry.fields))
|
|
10
|
+
.filter((item) => valuesArray.includes(item) || item === "*");
|
|
11
|
+
return (0, orderByUiSchema_1.orderByUiSchema)(additionalPropertiesOrder, valuesArray);
|
|
46
12
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo, useState } from "react";
|
|
3
3
|
import { useField } from "formik";
|
|
4
|
-
import { guessType } from "../../../utils";
|
|
4
|
+
import { extractUiSchema, guessType } from "../../../utils";
|
|
5
5
|
import { COMPONENT_TYPES } from "../../../common/constants";
|
|
6
6
|
import { SchemaField } from "../SchemaField/SchemaField";
|
|
7
7
|
import { AnyFieldWrapper } from "./styledComponents";
|
|
@@ -9,6 +9,9 @@ export const AnyField = (props) => {
|
|
|
9
9
|
const { name, schema, uiSchema } = props;
|
|
10
10
|
const [{ value }] = useField(name);
|
|
11
11
|
const [type, setType] = useState(value !== undefined ? guessType(value) : "string");
|
|
12
|
+
const {
|
|
13
|
+
//TODO: This is not right
|
|
14
|
+
props: { wrapper: wrapperProps = {} } = {}, } = useMemo(() => extractUiSchema(uiSchema), [uiSchema]);
|
|
12
15
|
const enrichedSchema = useMemo(() => {
|
|
13
16
|
switch (type) {
|
|
14
17
|
case "object":
|
|
@@ -19,5 +22,5 @@ export const AnyField = (props) => {
|
|
|
19
22
|
return { ...(schema || {}), type };
|
|
20
23
|
}
|
|
21
24
|
}, [type, schema]);
|
|
22
|
-
return (_jsxs(AnyFieldWrapper, { children: [_jsx("select", { value: type, onChange: (event) => setType(event.target.value), children: Object.keys(COMPONENT_TYPES).map((type) => (_jsx("option", { value: type, children: type }, type))) }), _jsx(SchemaField, { name: name, schema: enrichedSchema, uiSchema: uiSchema })] }));
|
|
25
|
+
return (_jsxs(AnyFieldWrapper, { ...wrapperProps, children: [_jsx("select", { value: type, onChange: (event) => setType(event.target.value), children: Object.keys(COMPONENT_TYPES).map((type) => (_jsx("option", { value: type, children: type }, type))) }), _jsx(SchemaField, { name: name, schema: enrichedSchema, uiSchema: uiSchema })] }));
|
|
23
26
|
};
|
|
@@ -4,13 +4,16 @@ import { extractUiSchema } from "../../../utils";
|
|
|
4
4
|
import { useSetDefault } from "../../hooks";
|
|
5
5
|
import { FormRegistry } from "../../FormRegistry";
|
|
6
6
|
import { CommonFieldWrapper as DateFieldWrapper } from "../../styles/common";
|
|
7
|
+
import { DateInput } from "./DateInput";
|
|
7
8
|
export const DateField = (props) => {
|
|
8
|
-
const { templates
|
|
9
|
+
const { templates } = useContext(FormRegistry);
|
|
9
10
|
useSetDefault(props);
|
|
10
|
-
const { name, uiSchema } = props;
|
|
11
|
+
const { name, uiSchema, schema } = props;
|
|
11
12
|
const { props: inputProps } = useMemo(() => extractUiSchema(uiSchema), [uiSchema]);
|
|
12
13
|
const SelectedFieldTemplate = (props.uiSchema?.["ui:template"] &&
|
|
13
14
|
templates[props.uiSchema?.["ui:template"]]) ??
|
|
14
15
|
templates.FieldTemplate;
|
|
15
|
-
|
|
16
|
+
const { label, placeholder, min, max, locale, helpText, disabled, errorMessages } = inputProps || {};
|
|
17
|
+
const readOnly = schema.readOnly === true;
|
|
18
|
+
return (_jsx(SelectedFieldTemplate, { ...props, "data-fjsf-string": name, children: _jsx(DateFieldWrapper, { children: _jsx(DateInput, { name: name, label: label, placeholder: placeholder, min: min, max: max, locale: locale, helpText: helpText, disabled: disabled, readOnly: readOnly, errorMessages: errorMessages }) }) }));
|
|
16
19
|
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useContext, useEffect, useRef, useState, } from "react";
|
|
3
|
+
import { useField, useFormikContext } from "formik";
|
|
4
|
+
import { Wrapper, Row, DisplayInput, HiddenNative, PickerButton, } from "./styledComponents";
|
|
5
|
+
import { parseDateString, toIsoDateString } from "./dateParsing";
|
|
6
|
+
import { FaCalendar } from "react-icons/fa";
|
|
7
|
+
import { FormRegistry } from "../../FormRegistry";
|
|
8
|
+
export const DateInput = ({ name, label, placeholder, min, max, locale, helpText, disabled, readOnly, errorMessages, }) => {
|
|
9
|
+
const { formLocalization } = useContext(FormRegistry);
|
|
10
|
+
const effectiveLocale = locale ?? formLocalization?.fields?.DateField?.locale ?? navigator.language;
|
|
11
|
+
const firstDatePart = new Intl.DateTimeFormat(effectiveLocale)
|
|
12
|
+
.formatToParts(new Date(Date.UTC(2000, 0, 2)))
|
|
13
|
+
.find(p => p.type === "day" || p.type === "month" || p.type === "year");
|
|
14
|
+
const preferOrder = firstDatePart?.type === "month" ? "MDY" : "DMY";
|
|
15
|
+
const { setFieldTouched } = useFormikContext();
|
|
16
|
+
const [field, meta, helpers] = useField(name);
|
|
17
|
+
const { value } = field;
|
|
18
|
+
const { setValue, setError } = helpers;
|
|
19
|
+
const nativeRef = useRef(null);
|
|
20
|
+
const formatForDisplay = useCallback((iso) => {
|
|
21
|
+
if (!iso)
|
|
22
|
+
return "";
|
|
23
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(iso)) {
|
|
24
|
+
if (iso === "now") {
|
|
25
|
+
const today = new Date();
|
|
26
|
+
return new Intl.DateTimeFormat(effectiveLocale, { timeZone: "UTC" })
|
|
27
|
+
.format(new Date(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate())));
|
|
28
|
+
}
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
const dt = new Date(`${iso}T00:00:00Z`);
|
|
32
|
+
if (Number.isNaN(dt.getTime()))
|
|
33
|
+
return "";
|
|
34
|
+
return new Intl.DateTimeFormat(effectiveLocale, { timeZone: "UTC" }).format(dt);
|
|
35
|
+
}, [effectiveLocale]);
|
|
36
|
+
const [displayValue, setDisplayValue] = useState(formatForDisplay(value));
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!value)
|
|
39
|
+
return setDisplayValue("");
|
|
40
|
+
setDisplayValue(formatForDisplay(value));
|
|
41
|
+
}, [value, formatForDisplay]);
|
|
42
|
+
const hasExternalError = !!meta.error && meta.touched;
|
|
43
|
+
const withinBounds = useCallback((iso) => {
|
|
44
|
+
if (min && iso < min)
|
|
45
|
+
return false;
|
|
46
|
+
if (max && iso > max)
|
|
47
|
+
return false;
|
|
48
|
+
return true;
|
|
49
|
+
}, [min, max]);
|
|
50
|
+
const outOfRangeMessage = useCallback(() => {
|
|
51
|
+
const fallback = (min && max && `Date must be between ${min} and ${max}.`) ||
|
|
52
|
+
"Date is out of range.";
|
|
53
|
+
const raw = errorMessages?.outOfRange;
|
|
54
|
+
if (typeof raw === "function") {
|
|
55
|
+
return raw({ min, max });
|
|
56
|
+
}
|
|
57
|
+
const s = typeof raw === "string" ? raw : fallback;
|
|
58
|
+
return s.replace(/\{min\}/g, min ?? "").replace(/\{max\}/g, max ?? "");
|
|
59
|
+
}, [errorMessages, min, max]);
|
|
60
|
+
const invalidMessage = errorMessages?.invalid ?? "Enter a valid date";
|
|
61
|
+
const onValueChange = useCallback((isoDate) => {
|
|
62
|
+
setFieldTouched(name, true, false);
|
|
63
|
+
if (!withinBounds(isoDate)) {
|
|
64
|
+
setError(outOfRangeMessage());
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
setError(undefined);
|
|
68
|
+
setValue(isoDate);
|
|
69
|
+
}, [name, setFieldTouched, setValue, setError, withinBounds, outOfRangeMessage]);
|
|
70
|
+
const openPicker = () => {
|
|
71
|
+
const el = nativeRef.current;
|
|
72
|
+
if (!el || disabled || readOnly)
|
|
73
|
+
return;
|
|
74
|
+
try {
|
|
75
|
+
if (typeof el.showPicker === "function")
|
|
76
|
+
el.showPicker();
|
|
77
|
+
else {
|
|
78
|
+
el.focus();
|
|
79
|
+
el.click();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
el.focus();
|
|
84
|
+
el.click();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const handleParseOrError = useCallback((raw) => {
|
|
88
|
+
if (readOnly || disabled)
|
|
89
|
+
return;
|
|
90
|
+
const newDate = parseDateString(raw, preferOrder);
|
|
91
|
+
setFieldTouched(name, true, false);
|
|
92
|
+
if (newDate) {
|
|
93
|
+
onValueChange(toIsoDateString(newDate));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
setError(invalidMessage);
|
|
97
|
+
}
|
|
98
|
+
}, [disabled, readOnly, preferOrder, name, onValueChange, setError, setFieldTouched, invalidMessage]);
|
|
99
|
+
const handlePaste = (e) => {
|
|
100
|
+
if (readOnly || disabled)
|
|
101
|
+
return;
|
|
102
|
+
e.preventDefault();
|
|
103
|
+
const text = e.clipboardData.getData("text")?.trim();
|
|
104
|
+
handleParseOrError(text ?? "");
|
|
105
|
+
};
|
|
106
|
+
return (_jsxs(Wrapper, { children: [_jsx("label", { htmlFor: `${name}-display`, children: label }), _jsxs(Row, { children: [_jsx(DisplayInput, { id: `${name}-display`, type: "text", placeholder: placeholder, autoComplete: "off", inputMode: "numeric", "aria-describedby": helpText ? `${name}-help` : undefined, "aria-invalid": hasExternalError, value: displayValue, onChange: (e) => setDisplayValue(e.target.value), onBlur: (e) => handleParseOrError(e.target.value), onPaste: handlePaste, disabled: disabled || readOnly, readOnly: readOnly }), !readOnly && (_jsx(HiddenNative, { ref: nativeRef, id: `${name}-native`, type: "date", min: min, max: max, value: value ?? "", onChange: (e) => {
|
|
107
|
+
onValueChange(e.target.value);
|
|
108
|
+
}, tabIndex: -1, "aria-hidden": "true" })), _jsx(PickerButton, { type: "button", onClick: openPicker, "aria-label": "Date picker", title: "Date picker", disabled: disabled || readOnly, children: _jsx(FaCalendar, {}) })] })] }));
|
|
109
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export function toIsoDateString(date) {
|
|
2
|
+
return date.toISOString().slice(0, 10);
|
|
3
|
+
}
|
|
4
|
+
export function isValidYMD(y, m, d) {
|
|
5
|
+
if (!y || !m || !d)
|
|
6
|
+
return false;
|
|
7
|
+
const dt = new Date(Date.UTC(y, m - 1, d));
|
|
8
|
+
return (dt.getUTCFullYear() === y &&
|
|
9
|
+
dt.getUTCMonth() === m - 1 &&
|
|
10
|
+
dt.getUTCDate() === d);
|
|
11
|
+
}
|
|
12
|
+
export function ymdToDate({ y, m, d, }) {
|
|
13
|
+
if (!isValidYMD(y, m, d))
|
|
14
|
+
return undefined;
|
|
15
|
+
return new Date(Date.UTC(y, m - 1, d));
|
|
16
|
+
}
|
|
17
|
+
export function parseDateString(input, preferOrder) {
|
|
18
|
+
const s = input.trim();
|
|
19
|
+
if (!s)
|
|
20
|
+
return undefined;
|
|
21
|
+
let m = s.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/) ||
|
|
22
|
+
s.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/);
|
|
23
|
+
if (m) {
|
|
24
|
+
const y = +m[1], mo = +m[2], d = +m[3];
|
|
25
|
+
return ymdToDate({ y, m: mo, d });
|
|
26
|
+
}
|
|
27
|
+
m = s.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/);
|
|
28
|
+
if (m) {
|
|
29
|
+
const d = +m[1], mo = +m[2], y = +m[3];
|
|
30
|
+
return ymdToDate({ y, m: mo, d });
|
|
31
|
+
}
|
|
32
|
+
m = s.match(/^(\d{1,2})\.(\d{1,2})\.(\d{2})$/);
|
|
33
|
+
if (m) {
|
|
34
|
+
const d = +m[1], mo = +m[2], y = 2000 + +m[3];
|
|
35
|
+
return ymdToDate({ y, m: mo, d });
|
|
36
|
+
}
|
|
37
|
+
m = s.match(/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/);
|
|
38
|
+
if (m) {
|
|
39
|
+
const a = +m[1], b = +m[2], y = +m[3] < 100 ? 2000 + +m[3] : +m[3];
|
|
40
|
+
const dmy = ymdToDate({ y, m: b, d: a });
|
|
41
|
+
const mdy = ymdToDate({ y, m: a, d: b });
|
|
42
|
+
if (dmy && !mdy)
|
|
43
|
+
return dmy;
|
|
44
|
+
if (!dmy && mdy)
|
|
45
|
+
return mdy;
|
|
46
|
+
if (dmy && mdy)
|
|
47
|
+
return preferOrder === "MDY" ? mdy : dmy;
|
|
48
|
+
}
|
|
49
|
+
const tryPatterns = [
|
|
50
|
+
/^(\d{1,2})-(\d{1,2})-(\d{4})$/,
|
|
51
|
+
/^(\d{1,2}) (\d{1,2}) (\d{4})$/,
|
|
52
|
+
];
|
|
53
|
+
for (const r of tryPatterns) {
|
|
54
|
+
const mm = s.match(r);
|
|
55
|
+
if (mm) {
|
|
56
|
+
const d = +mm[1], mo = +mm[2], y = +mm[3];
|
|
57
|
+
if (isValidYMD(y, mo, d))
|
|
58
|
+
return ymdToDate({ y, m: mo, d });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
@@ -1 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
export const Wrapper = styled.div `
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
max-width: 360px;
|
|
6
|
+
`;
|
|
7
|
+
export const Row = styled.div `
|
|
8
|
+
position: relative;
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
`;
|
|
12
|
+
export const DisplayInput = styled.input `
|
|
13
|
+
flex: 1;
|
|
14
|
+
`;
|
|
15
|
+
export const HiddenNative = styled.input `
|
|
16
|
+
position: absolute;
|
|
17
|
+
opacity: 0;
|
|
18
|
+
pointer-events: none;
|
|
19
|
+
width: 0;
|
|
20
|
+
height: 0;
|
|
21
|
+
`;
|
|
22
|
+
export const PickerButton = styled.button `
|
|
23
|
+
position: relative;
|
|
24
|
+
left: -40px;
|
|
25
|
+
border: none;
|
|
26
|
+
background: inherit;
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
font: inherit;
|
|
29
|
+
&:focus {
|
|
30
|
+
box-shadow: none;;
|
|
31
|
+
}
|
|
32
|
+
&:disabled {
|
|
33
|
+
cursor: not-allowed;
|
|
34
|
+
opacity: 0.6;
|
|
35
|
+
}
|
|
36
|
+
svg {
|
|
37
|
+
display: flex;
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
@@ -61,5 +61,5 @@ export const FileUploadField = (props) => {
|
|
|
61
61
|
const SelectedFieldTemplate = (props.uiSchema?.["ui:template"] &&
|
|
62
62
|
templates[props.uiSchema?.["ui:template"]]) ??
|
|
63
63
|
templates.FieldTemplate;
|
|
64
|
-
return (_jsx(SelectedFieldTemplate, { ...props, "data-fjsf-object": name, children: _jsx(FileUploadFieldInput, { ...inputProps, name: name, value: value, handleRemoveFile: handleRemoveFile, uploadedFile: uploadedFile, setFieldValue: setFieldValue, handleFileUpload: handleFileUpload, uploadProgress: uploadProgress, removeButton: uiSchema["ui:removeButton"], uploadButtonText: uiSchema["ui:uploadButtonText"], infoText: uiSchema["ui:infoText"], hideRemoveButton: inputProps?.removeButton
|
|
64
|
+
return (_jsx(SelectedFieldTemplate, { ...props, "data-fjsf-object": name, children: _jsx(FileUploadFieldInput, { ...inputProps, name: name, value: value, handleRemoveFile: handleRemoveFile, uploadedFile: uploadedFile, setFieldValue: setFieldValue, handleFileUpload: handleFileUpload, uploadProgress: uploadProgress, removeButton: uiSchema["ui:removeButton"], uploadButtonText: uiSchema["ui:uploadButtonText"], infoText: uiSchema["ui:infoText"], hideRemoveButton: inputProps?.removeButton?.hidden }) }));
|
|
65
65
|
};
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useField, useFormikContext } from "formik";
|
|
3
3
|
import { useContext, useEffect, useMemo } from "react";
|
|
4
4
|
import { ObjectFieldWrapper } from "./styledComponents";
|
|
5
|
-
import { orderAdditionalProperties, orderByUiSchema, resolveSchema, } from "../../../utils";
|
|
5
|
+
import { getHiddenProperties, orderAdditionalProperties, orderByUiSchema, resolveSchema, } from "../../../utils";
|
|
6
6
|
import { useSetDefault } from "../../hooks";
|
|
7
7
|
import { FormRegistry } from "../../FormRegistry";
|
|
8
8
|
import { ObjectFieldButtonPurpose } from "./types";
|
|
@@ -32,10 +32,11 @@ export const ObjectField = (props) => {
|
|
|
32
32
|
}
|
|
33
33
|
}, [valuesToRemove]);
|
|
34
34
|
const propertyKeys = useMemo(() => Object.keys(properties || {}), [properties]);
|
|
35
|
-
const
|
|
36
|
-
const orderedProperties = orderByUiSchema(uiSchema?.["ui:order"],
|
|
37
|
-
const
|
|
38
|
-
const
|
|
35
|
+
const additionalPropertyKeys = useMemo(() => Object.keys(value || {}).filter((key) => !propertyKeys.includes(key)), [value, propertyKeys]);
|
|
36
|
+
const orderedProperties = orderByUiSchema(uiSchema?.["ui:order"], propertyKeys);
|
|
37
|
+
const hiddenProperties = getHiddenProperties(uiSchema?.["ui:order"], propertyKeys);
|
|
38
|
+
const orderedAdditionalProperties = orderAdditionalProperties(uiSchema?.["ui:order"], additionalPropertyKeys);
|
|
39
|
+
const hiddenAdditionalProperties = getHiddenProperties(uiSchema?.["ui:order"], additionalPropertyKeys);
|
|
39
40
|
const getObjectFieldButton = ({ purpose, onClick, uiSchema, }) => {
|
|
40
41
|
switch (purpose) {
|
|
41
42
|
case ObjectFieldButtonPurpose.ADD:
|
|
@@ -55,6 +56,7 @@ export const ObjectField = (props) => {
|
|
|
55
56
|
(props.uiSchema?.["ui:options"]?.isCollapsible
|
|
56
57
|
? templates.CollapsibleObjectFieldTemplate
|
|
57
58
|
: templates.ObjectFieldTemplate);
|
|
59
|
+
const showAdditionalProperties = !hideUnmarkedAdditionalProperties || !!additionalProperties;
|
|
58
60
|
return (_jsx(ObjectFieldWrapper, { children: _jsxs(SelectedObjectFieldTemplate, { ...props, "data-fjsf-object": name || "ROOT", "data-fjsf-level": !name ? 0 : name.split(".").length, children: [orderedProperties
|
|
59
61
|
.map((child) => {
|
|
60
62
|
if (typeof child === "string") {
|
|
@@ -73,10 +75,28 @@ export const ObjectField = (props) => {
|
|
|
73
75
|
}) }, fields.join("_")));
|
|
74
76
|
}
|
|
75
77
|
})
|
|
76
|
-
.filter((x) => x), (
|
|
77
|
-
|
|
78
|
+
.filter((x) => x), hiddenProperties.map((child) => {
|
|
79
|
+
const childSchema = properties?.[child];
|
|
80
|
+
if (!childSchema)
|
|
81
|
+
return undefined;
|
|
82
|
+
const childUiSchema = uiSchema?.[child];
|
|
83
|
+
return (_jsx(SchemaField, { required: required?.includes(child), name: name ? [name, child].join(".") : child, schema: prepareChildSchema(childSchema, schema), uiSchema: {
|
|
84
|
+
...childUiSchema,
|
|
85
|
+
props: {
|
|
86
|
+
...childUiSchema?.props,
|
|
87
|
+
wrapper: {
|
|
88
|
+
...childUiSchema?.props?.wrapper,
|
|
89
|
+
style: {
|
|
90
|
+
...childUiSchema?.props?.wrapper?.style,
|
|
91
|
+
display: "none",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
}, style: { display: "none" } }, child));
|
|
96
|
+
}), showAdditionalProperties &&
|
|
97
|
+
orderedAdditionalProperties.map((childName) => {
|
|
78
98
|
let correctUiSchema = uiSchema?.[childName];
|
|
79
|
-
if (uiSchema
|
|
99
|
+
if (uiSchema?.properties?.["ui:order"] !== undefined &&
|
|
80
100
|
uiSchema?.[childName]?.["ui:order"] === undefined) {
|
|
81
101
|
correctUiSchema = {
|
|
82
102
|
...correctUiSchema,
|
|
@@ -91,6 +111,17 @@ export const ObjectField = (props) => {
|
|
|
91
111
|
},
|
|
92
112
|
uiSchema: uiSchema,
|
|
93
113
|
}) })] }, childName));
|
|
114
|
+
}), showAdditionalProperties &&
|
|
115
|
+
hiddenAdditionalProperties.map((childName) => {
|
|
116
|
+
let correctUiSchema = uiSchema?.[childName];
|
|
117
|
+
if (uiSchema.properties?.["ui:order"] !== undefined &&
|
|
118
|
+
uiSchema?.[childName]?.["ui:order"] === undefined) {
|
|
119
|
+
correctUiSchema = {
|
|
120
|
+
...correctUiSchema,
|
|
121
|
+
"ui:order": uiSchema.properties?.["ui:order"],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return (_jsx(ObjectFieldItem, { style: { display: "none" }, children: _jsx(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema: correctUiSchema }, childName) }, childName));
|
|
94
125
|
}), additionalProperties &&
|
|
95
126
|
getObjectFieldButton({
|
|
96
127
|
purpose: ObjectFieldButtonPurpose.ADD,
|
|
@@ -4,10 +4,10 @@ import { FormRegistry } from "../../FormRegistry";
|
|
|
4
4
|
import { IconWrapper } from "./styledComponents";
|
|
5
5
|
export const ObjectFieldSection = ({ title, collapsible, children, }) => {
|
|
6
6
|
const [collapsed, setCollapsed] = useState(collapsible);
|
|
7
|
-
const { components: { ObjectFieldSectionWrapper, ObjectFieldSectionTitle }, } = useContext(FormRegistry);
|
|
7
|
+
const { components: { ObjectFieldSectionWrapper, ObjectFieldSectionTitle, ObjectFieldSectionChildrenWrapper, }, } = useContext(FormRegistry);
|
|
8
8
|
return (_jsxs(ObjectFieldSectionWrapper, { children: [_jsxs(ObjectFieldSectionTitle, { onClick: () => {
|
|
9
9
|
if (collapsible) {
|
|
10
10
|
setCollapsed((currentState) => !currentState);
|
|
11
11
|
}
|
|
12
|
-
}, children: [title, _jsx(IconWrapper, { children: collapsible && (collapsed ? "▸" : "▾") })] }),
|
|
12
|
+
}, children: [title, _jsx(IconWrapper, { children: collapsible && (collapsed ? "▸" : "▾") })] }), _jsx(ObjectFieldSectionChildrenWrapper, { style: collapsed ? { display: "none" } : undefined, children: children })] }));
|
|
13
13
|
};
|
|
@@ -7,13 +7,15 @@ export const useSetDefault = (props) => {
|
|
|
7
7
|
const [{ value }, , { setValue }] = useField(props.name);
|
|
8
8
|
useEffect(() => {
|
|
9
9
|
let newValue = value;
|
|
10
|
-
if (value === "now" && props.schema.format === "date") {
|
|
11
|
-
const today = new Date().toISOString().split("T")[0];
|
|
12
|
-
newValue = today;
|
|
13
|
-
}
|
|
14
10
|
if (!newValue) {
|
|
15
11
|
if (props.schema.default !== undefined) {
|
|
16
|
-
|
|
12
|
+
if (props.schema.format === "date" && props.schema.default === "now") {
|
|
13
|
+
const today = new Date().toISOString().split("T")[0];
|
|
14
|
+
newValue = today;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
newValue = props.schema.default;
|
|
18
|
+
}
|
|
17
19
|
}
|
|
18
20
|
else if (props.forceDefaultValue) {
|
|
19
21
|
newValue = getDefaultValueForType(props.schema.type);
|
|
@@ -22,5 +24,5 @@ export const useSetDefault = (props) => {
|
|
|
22
24
|
if (newValue && newValue !== value) {
|
|
23
25
|
setValue(newValue);
|
|
24
26
|
}
|
|
25
|
-
}, [
|
|
27
|
+
}, []);
|
|
26
28
|
};
|
package/dist/esm/Form/templates/CollapsibleObjectFieldTemplate/CollapsibleObjectFieldTemplate.js
CHANGED
|
@@ -33,5 +33,5 @@ export const CollapsibleObjectFieldTemplate = (props) => {
|
|
|
33
33
|
const hide = collapsed;
|
|
34
34
|
return (_jsxs(Wrapper, { ...mergedWrapperProps, children: [_jsxs(TitleInfoWrapper, { children: [title && (_jsx(Toggle, { onClick: () => setCollapsed(!collapsed),
|
|
35
35
|
//ariaExpanded={!hide}
|
|
36
|
-
ariaLabel: ariaLabel ?? name, children: _jsxs(Title, { ...titleProps, htmlFor: name, children: [title, props?.required && _jsx(RequiredIndicator, {}), _jsx(Icon, { children: hide ? collapsedIcon ?? "▸" : openIcon ?? "▾" })] }) })), info && _jsx(Info, { ...info })] }), description && (_jsx(Description, { ...descriptionProps, children: description })),
|
|
36
|
+
ariaLabel: ariaLabel ?? name, children: _jsxs(Title, { ...titleProps, htmlFor: name, children: [title, props?.required && _jsx(RequiredIndicator, {}), _jsx(Icon, { children: hide ? collapsedIcon ?? "▸" : openIcon ?? "▾" })] }) })), info && _jsx(Info, { ...info })] }), description && (_jsx(Description, { ...descriptionProps, children: description })), _jsx(ChildrenWrapper, { style: hide ? { display: "none" } : undefined, children: children }), help && _jsx(Help, { ...helpProps, children: help })] }));
|
|
37
37
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const getHiddenProperties = (order, properties) => {
|
|
2
|
+
if (!order || order.includes("*")) {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
const propertiesInOrder = order.flatMap((entry) => typeof entry === "string" ? entry : entry.fields);
|
|
6
|
+
return properties.filter((key) => !propertiesInOrder.includes(key));
|
|
7
|
+
};
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -1,43 +1,9 @@
|
|
|
1
|
+
import { orderByUiSchema } from "./orderByUiSchema";
|
|
1
2
|
export function orderAdditionalProperties(uiOrderArray, valuesArray) {
|
|
2
|
-
if (uiOrderArray.length === 0)
|
|
3
|
+
if (!uiOrderArray || uiOrderArray.length === 0)
|
|
3
4
|
return valuesArray;
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
finalArray = filteredValues(uiOrderArray);
|
|
9
|
-
}
|
|
10
|
-
else {
|
|
11
|
-
const uiOrderArrayWithoutAsterisk = uiOrderArray.filter((item) => item !== "*");
|
|
12
|
-
if (uiOrderArray.length === 1) {
|
|
13
|
-
finalArray = valuesArray;
|
|
14
|
-
}
|
|
15
|
-
else if (uiOrderArray.indexOf("*") === 0) {
|
|
16
|
-
// wildcard is first element
|
|
17
|
-
const individualValues = valuesArray.filter((element) => !uiOrderArrayWithoutAsterisk.includes(element));
|
|
18
|
-
const commonValues = filteredValues(uiOrderArrayWithoutAsterisk);
|
|
19
|
-
finalArray = [...individualValues, ...commonValues];
|
|
20
|
-
}
|
|
21
|
-
else if (uiOrderArray.indexOf("*") === uiOrderArray.length - 1) {
|
|
22
|
-
// wildcard is final element
|
|
23
|
-
const individualValues = valuesArray.filter((element) => !uiOrderArrayWithoutAsterisk.includes(element));
|
|
24
|
-
const commonValues = filteredValues(uiOrderArrayWithoutAsterisk);
|
|
25
|
-
finalArray = [...commonValues, ...individualValues];
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
// wildcard is somewhere in the middle
|
|
29
|
-
const indexForUnspecified = uiOrderArray.indexOf("*");
|
|
30
|
-
const definedBefore = uiOrderArray.slice(0, indexForUnspecified);
|
|
31
|
-
const definedAfter = uiOrderArray.slice(indexForUnspecified + 1);
|
|
32
|
-
const commonBeforeValues = filteredValues(definedBefore);
|
|
33
|
-
const commonAfterValues = filteredValues(definedAfter);
|
|
34
|
-
const individualValues = valuesArray.filter((element) => ![...commonBeforeValues, ...commonAfterValues].includes(element));
|
|
35
|
-
finalArray = [
|
|
36
|
-
...commonBeforeValues,
|
|
37
|
-
...individualValues,
|
|
38
|
-
...commonAfterValues,
|
|
39
|
-
];
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return finalArray;
|
|
5
|
+
const additionalPropertiesOrder = uiOrderArray
|
|
6
|
+
.flatMap((entry) => (typeof entry === "string" ? entry : entry.fields))
|
|
7
|
+
.filter((item) => valuesArray.includes(item) || item === "*");
|
|
8
|
+
return orderByUiSchema(additionalPropertiesOrder, valuesArray);
|
|
43
9
|
}
|
|
@@ -168,6 +168,7 @@ export declare const components: {
|
|
|
168
168
|
ObjectFieldAddButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<Readonly<import("@nolwenture/component-library").ButtonProps>, never>, never>> & string;
|
|
169
169
|
ObjectFieldSectionWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").FieldsetHTMLAttributes<HTMLFieldSetElement>, HTMLFieldSetElement>, never>> & string;
|
|
170
170
|
ObjectFieldSectionTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLLegendElement>, HTMLLegendElement>, never>> & string;
|
|
171
|
+
ObjectFieldSectionChildrenWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
171
172
|
MultipleChoiceFieldInput: ({ inputProps, name, className, enums, style, value, form, }: import("../fields/MultipleChoiceField").MultipleChoiceFieldInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
172
173
|
MultipleChoiceFieldContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<Omit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>, "ref"> & {
|
|
173
174
|
ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type DateInputProps = {
|
|
3
|
+
name: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
min?: string;
|
|
7
|
+
max?: string;
|
|
8
|
+
locale?: string;
|
|
9
|
+
helpText?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
readOnly?: boolean;
|
|
12
|
+
errorMessages?: {
|
|
13
|
+
invalid?: string;
|
|
14
|
+
outOfRange?: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export declare const DateInput: React.FC<DateInputProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type PreferOrder = "DMY" | "MDY";
|
|
2
|
+
export declare function toIsoDateString(date: Date): string;
|
|
3
|
+
export declare function isValidYMD(y: number, m: number, d: number): boolean;
|
|
4
|
+
export declare function ymdToDate({ y, m, d, }: {
|
|
5
|
+
y: number;
|
|
6
|
+
m: number;
|
|
7
|
+
d: number;
|
|
8
|
+
}): Date | undefined;
|
|
9
|
+
export declare function parseDateString(input: string, preferOrder: PreferOrder): Date | undefined;
|
|
@@ -1 +1,5 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const Wrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
2
|
+
export declare const Row: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
3
|
+
export declare const DisplayInput: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, never>> & string;
|
|
4
|
+
export declare const HiddenNative: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, never>> & string;
|
|
5
|
+
export declare const PickerButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
@@ -14,6 +14,7 @@ declare const components: {
|
|
|
14
14
|
ObjectFieldAddButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<Readonly<import("@nolwenture/component-library").ButtonProps>, never>, never>> & string;
|
|
15
15
|
ObjectFieldSectionWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").FieldsetHTMLAttributes<HTMLFieldSetElement>, HTMLFieldSetElement>, never>> & string;
|
|
16
16
|
ObjectFieldSectionTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLLegendElement>, HTMLLegendElement>, never>> & string;
|
|
17
|
+
ObjectFieldSectionChildrenWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
17
18
|
};
|
|
18
19
|
export { components };
|
|
19
20
|
export type * from "./types";
|
|
@@ -12,3 +12,4 @@ export declare const ObjectFieldRemoveButton: import("styled-components/dist/typ
|
|
|
12
12
|
export declare const ObjectFieldAddButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<Readonly<import("@nolwenture/component-library").ButtonProps>, never>, never>> & string;
|
|
13
13
|
export declare const ObjectFieldSectionWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").FieldsetHTMLAttributes<HTMLFieldSetElement>, HTMLFieldSetElement>, never>> & string;
|
|
14
14
|
export declare const ObjectFieldSectionTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLLegendElement>, HTMLLegendElement>, never>> & string;
|
|
15
|
+
export declare const ObjectFieldSectionChildrenWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
@@ -89,6 +89,7 @@ export declare const fieldComponents: {
|
|
|
89
89
|
ObjectFieldAddButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<Readonly<import("@nolwenture/component-library").ButtonProps>, never>, never>> & string;
|
|
90
90
|
ObjectFieldSectionWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").FieldsetHTMLAttributes<HTMLFieldSetElement>, HTMLFieldSetElement>, never>> & string;
|
|
91
91
|
ObjectFieldSectionTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLLegendElement>, HTMLLegendElement>, never>> & string;
|
|
92
|
+
ObjectFieldSectionChildrenWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
92
93
|
MultipleChoiceFieldInput: ({ inputProps, name, className, enums, style, value, form, }: MultipleChoiceField.MultipleChoiceFieldInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
93
94
|
MultipleChoiceFieldContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<Omit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>, "ref"> & {
|
|
94
95
|
ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { UiSchema } from "../common/types";
|
|
2
|
+
export declare function orderAdditionalProperties(uiOrderArray: UiSchema["ui:order"], valuesArray: string[]): string[];
|