@bsol-oss/react-datatable5 13.0.1-beta.26 → 13.0.1-beta.28
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/dist/index.d.ts +9 -24
- package/dist/index.js +40 -350
- package/dist/index.mjs +41 -351
- package/dist/types/components/Form/SchemaFormContext.d.ts +1 -22
- package/dist/types/components/Form/components/core/FormRoot.d.ts +2 -12
- package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +2 -2
- package/dist/types/components/Form/useForm.d.ts +4 -9
- package/package.json +4 -1
package/dist/index.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import { IoReload } from 'react-icons/io5';
|
|
|
21
21
|
import { useDebounce } from '@uidotdev/usehooks';
|
|
22
22
|
import { BsExclamationCircleFill, BsClock } from 'react-icons/bs';
|
|
23
23
|
import { HiColorSwatch } from 'react-icons/hi';
|
|
24
|
-
import { flexRender, makeStateUpdater, functionalUpdate, useReactTable,
|
|
24
|
+
import { flexRender, makeStateUpdater, functionalUpdate, useReactTable, getPaginationRowModel, getSortedRowModel, getFilteredRowModel, getCoreRowModel } from '@tanstack/react-table';
|
|
25
25
|
import { GrAscend, GrDescend } from 'react-icons/gr';
|
|
26
26
|
import axios from 'axios';
|
|
27
27
|
import { useFormContext, FormProvider, useForm as useForm$1 } from 'react-hook-form';
|
|
@@ -30,9 +30,7 @@ import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
|
30
30
|
import timezone from 'dayjs/plugin/timezone';
|
|
31
31
|
import utc from 'dayjs/plugin/utc';
|
|
32
32
|
import { TiDeleteOutline } from 'react-icons/ti';
|
|
33
|
-
import
|
|
34
|
-
import addFormats from 'ajv-formats';
|
|
35
|
-
import AjvErrors from 'ajv-errors';
|
|
33
|
+
import { ajvResolver } from '@hookform/resolvers/ajv';
|
|
36
34
|
import { rankItem } from '@tanstack/match-sorter-utils';
|
|
37
35
|
|
|
38
36
|
const DataTableContext = createContext({
|
|
@@ -1133,7 +1131,7 @@ function getElementFromPointWithoutHoneypot(client) {
|
|
|
1133
1131
|
var maxZIndex = 2147483647;
|
|
1134
1132
|
|
|
1135
1133
|
function ownKeys$2(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
1136
|
-
function _objectSpread$2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$2(Object(t),
|
|
1134
|
+
function _objectSpread$2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$2(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$2(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1137
1135
|
var honeyPotSize = 2;
|
|
1138
1136
|
var halfHoneyPotSize = honeyPotSize / 2;
|
|
1139
1137
|
|
|
@@ -2238,8 +2236,8 @@ function addAttribute(element, _ref) {
|
|
|
2238
2236
|
}
|
|
2239
2237
|
|
|
2240
2238
|
function ownKeys$1(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2241
|
-
function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$1(Object(t),
|
|
2242
|
-
function _createForOfIteratorHelper$1(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$1(r)) || e
|
|
2239
|
+
function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$1(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$1(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
2240
|
+
function _createForOfIteratorHelper$1(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$1(r)) || e) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: true } : { done: false, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = true, u = false; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = true, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
2243
2241
|
function _unsupportedIterableToArray$1(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$1(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$1(r, a) : void 0; } }
|
|
2244
2242
|
function _arrayLikeToArray$1(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
2245
2243
|
function copyReverse(array) {
|
|
@@ -2543,11 +2541,11 @@ function makeDropTarget(_ref) {
|
|
|
2543
2541
|
};
|
|
2544
2542
|
}
|
|
2545
2543
|
|
|
2546
|
-
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e
|
|
2544
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: true } : { done: false, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = true, u = false; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = true, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
2547
2545
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
2548
2546
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
2549
2547
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2550
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t),
|
|
2548
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
2551
2549
|
function makeMonitor() {
|
|
2552
2550
|
var registry = new Set();
|
|
2553
2551
|
var dragging = null;
|
|
@@ -4169,20 +4167,13 @@ const useDataTableServer = (props) => {
|
|
|
4169
4167
|
//@ts-expect-error TODO: find appropriate type
|
|
4170
4168
|
const SchemaFormContext = createContext({
|
|
4171
4169
|
schema: {},
|
|
4172
|
-
requestUrl: '',
|
|
4173
|
-
order: [],
|
|
4174
|
-
ignore: [],
|
|
4175
|
-
include: [],
|
|
4176
4170
|
onSubmit: async () => { },
|
|
4177
|
-
rowNumber: 0,
|
|
4178
|
-
requestOptions: {},
|
|
4179
4171
|
timezone: 'Asia/Hong_Kong',
|
|
4180
4172
|
displayConfig: {
|
|
4181
4173
|
showSubmitButton: true,
|
|
4182
4174
|
showResetButton: true,
|
|
4183
4175
|
showTitle: true,
|
|
4184
4176
|
},
|
|
4185
|
-
onFormSubmit: async () => { },
|
|
4186
4177
|
});
|
|
4187
4178
|
|
|
4188
4179
|
const useSchemaContext = () => {
|
|
@@ -4211,8 +4202,8 @@ const useFormLabel = (column, prefix = '', schema) => {
|
|
|
4211
4202
|
prefix,
|
|
4212
4203
|
schema: {
|
|
4213
4204
|
type: schema.type,
|
|
4214
|
-
|
|
4215
|
-
? Object.keys(schema.
|
|
4205
|
+
errorMessage: schema.errorMessage
|
|
4206
|
+
? Object.keys(schema.errorMessage)
|
|
4216
4207
|
: undefined,
|
|
4217
4208
|
},
|
|
4218
4209
|
});
|
|
@@ -4224,8 +4215,8 @@ const useFormLabel = (column, prefix = '', schema) => {
|
|
|
4224
4215
|
|
|
4225
4216
|
const ArrayRenderer = ({ schema, column, prefix, }) => {
|
|
4226
4217
|
const { gridRow, gridColumn = '1/span 12', required, items } = schema;
|
|
4227
|
-
|
|
4228
|
-
const { type } =
|
|
4218
|
+
const itemsSchema = Array.isArray(items) ? items[0] : items;
|
|
4219
|
+
const { type } = itemsSchema ?? {};
|
|
4229
4220
|
const colLabel = `${prefix}${column}`;
|
|
4230
4221
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4231
4222
|
const formI18n = useFormLabel(column, prefix, schema);
|
|
@@ -4237,8 +4228,10 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
|
|
|
4237
4228
|
_dark: 'colorPalette.800',
|
|
4238
4229
|
}, children: [jsx(Grid, { gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: jsx(SchemaRenderer, { column: `${index}`,
|
|
4239
4230
|
prefix: `${colLabel}.`,
|
|
4240
|
-
|
|
4241
|
-
|
|
4231
|
+
schema: {
|
|
4232
|
+
showLabel: false,
|
|
4233
|
+
...(Array.isArray(items) ? items[0] : items ?? {}),
|
|
4234
|
+
} }) }), jsx(Flex, { justifyContent: 'end', children: jsx(Button$1, { variant: 'ghost', onClick: () => {
|
|
4242
4235
|
setValue(colLabel, fields.filter((_, curIndex) => {
|
|
4243
4236
|
return curIndex !== index;
|
|
4244
4237
|
}));
|
|
@@ -5321,16 +5314,13 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
5321
5314
|
element: el,
|
|
5322
5315
|
onDragEnter: () => setIsDraggedOver(true),
|
|
5323
5316
|
onDragLeave: () => setIsDraggedOver(false),
|
|
5324
|
-
// canDrop: some(containsFiles, containsText),
|
|
5325
5317
|
onDrop: ({ source }) => {
|
|
5326
5318
|
const files = getFiles({ source });
|
|
5327
5319
|
const text = getText({ source });
|
|
5328
|
-
console.log(files, text, 'dfposa');
|
|
5329
5320
|
onDrop({ files, text });
|
|
5330
5321
|
},
|
|
5331
5322
|
});
|
|
5332
5323
|
}, [onDrop]);
|
|
5333
|
-
// const isDark = (location + location) % 2 === 1;
|
|
5334
5324
|
function getColor(isDraggedOver) {
|
|
5335
5325
|
if (isDraggedOver) {
|
|
5336
5326
|
return {
|
|
@@ -5340,7 +5330,6 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
5340
5330
|
},
|
|
5341
5331
|
};
|
|
5342
5332
|
}
|
|
5343
|
-
// return isDark ? "lightgrey" : "white";
|
|
5344
5333
|
return {
|
|
5345
5334
|
backgroundColor: undefined,
|
|
5346
5335
|
_dark: {
|
|
@@ -6223,11 +6212,9 @@ const ObjectInput = ({ schema, column, prefix }) => {
|
|
|
6223
6212
|
base: 'colorPalette.200',
|
|
6224
6213
|
_dark: 'colorPalette.800',
|
|
6225
6214
|
}, gap: "4", padding: '4', gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: Object.keys(properties ?? {}).map((key) => {
|
|
6226
|
-
return (
|
|
6227
|
-
// @ts-expect-error find suitable types
|
|
6228
|
-
jsx(ColumnRenderer, { column: `${key}`,
|
|
6215
|
+
return (jsx(ColumnRenderer, { column: `${key}`,
|
|
6229
6216
|
prefix: `${prefix}${column}.`,
|
|
6230
|
-
properties,
|
|
6217
|
+
properties: properties ?? {},
|
|
6231
6218
|
parentRequired: required }, `form-${colLabel}-${key}`));
|
|
6232
6219
|
}) })] }));
|
|
6233
6220
|
};
|
|
@@ -7969,7 +7956,8 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
|
7969
7956
|
}
|
|
7970
7957
|
if (variant === 'enum-picker') {
|
|
7971
7958
|
const { items, title } = colSchema;
|
|
7972
|
-
const
|
|
7959
|
+
const itemsSchema = Array.isArray(items) ? items[0] : items;
|
|
7960
|
+
const { enum: enumItems } = itemsSchema ?? {};
|
|
7973
7961
|
// Use renderDisplay from parent schema only
|
|
7974
7962
|
const renderDisplay = colSchema.renderDisplay;
|
|
7975
7963
|
const enumSchema = {
|
|
@@ -8006,15 +7994,15 @@ const ColumnRenderer = ({ column, properties, prefix, parentRequired, }) => {
|
|
|
8006
7994
|
};
|
|
8007
7995
|
|
|
8008
7996
|
const SubmitButton = () => {
|
|
8009
|
-
const {
|
|
7997
|
+
const { onSubmit, formButtonLabels } = useSchemaContext();
|
|
8010
7998
|
const methods = useFormContext();
|
|
8011
7999
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8012
|
-
const onValid = (data) => {
|
|
8000
|
+
const onValid = async (data) => {
|
|
8013
8001
|
// Validation is handled by react-hook-form
|
|
8014
8002
|
// This function will only be called if validation passes
|
|
8015
|
-
|
|
8016
|
-
|
|
8017
|
-
|
|
8003
|
+
if (onSubmit) {
|
|
8004
|
+
await onSubmit(data);
|
|
8005
|
+
}
|
|
8018
8006
|
};
|
|
8019
8007
|
return (jsx(Button$1, { onClick: () => {
|
|
8020
8008
|
methods.handleSubmit(onValid)();
|
|
@@ -8022,33 +8010,21 @@ const SubmitButton = () => {
|
|
|
8022
8010
|
};
|
|
8023
8011
|
|
|
8024
8012
|
const FormBody = () => {
|
|
8025
|
-
const { schema,
|
|
8013
|
+
const { schema, displayConfig, formButtonLabels } = useSchemaContext();
|
|
8026
8014
|
const { showSubmitButton, showResetButton } = displayConfig;
|
|
8027
8015
|
const methods = useFormContext();
|
|
8028
|
-
console.log(methods.formState.errors);
|
|
8016
|
+
console.log('errors', methods.formState.errors);
|
|
8029
8017
|
const { properties } = schema;
|
|
8030
|
-
const
|
|
8031
|
-
const included = include.length > 0 ? include : keys;
|
|
8032
|
-
const not_exist = included.filter((columnA) => !order.some((columnB) => columnA === columnB));
|
|
8033
|
-
const ordered = [...order, ...not_exist];
|
|
8034
|
-
const ignored = ordered.filter((column) => !ignore.some((shouldIgnore) => column === shouldIgnore));
|
|
8035
|
-
return ignored;
|
|
8036
|
-
};
|
|
8037
|
-
const ordered = renderColumns({
|
|
8038
|
-
order,
|
|
8039
|
-
keys: Object.keys(properties),
|
|
8040
|
-
ignore,
|
|
8041
|
-
include,
|
|
8042
|
-
});
|
|
8018
|
+
const ordered = Object.keys(properties);
|
|
8043
8019
|
return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8020
|
+
if (!properties) {
|
|
8021
|
+
console.error('properties is undefined when using FormBody', schema);
|
|
8022
|
+
return null;
|
|
8023
|
+
}
|
|
8024
|
+
return (jsx(ColumnRenderer, { properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
|
|
8049
8025
|
}) }), jsxs(Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
|
|
8050
8026
|
methods.reset();
|
|
8051
|
-
}, variant: 'subtle', children: formButtonLabels?.reset ?? 'Reset' })), showSubmitButton && jsx(SubmitButton, {})] })
|
|
8027
|
+
}, variant: 'subtle', children: formButtonLabels?.reset ?? 'Reset' })), showSubmitButton && jsx(SubmitButton, {})] })] }));
|
|
8052
8028
|
};
|
|
8053
8029
|
|
|
8054
8030
|
const FormTitle = () => {
|
|
@@ -8067,96 +8043,18 @@ const FormTitle = () => {
|
|
|
8067
8043
|
return jsx(Heading, { children: schema.title ?? 'Form' });
|
|
8068
8044
|
};
|
|
8069
8045
|
|
|
8070
|
-
const
|
|
8071
|
-
return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
|
|
8072
|
-
};
|
|
8073
|
-
|
|
8074
|
-
const FormRoot = ({ schema, idMap, setIdMap, form, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
|
|
8046
|
+
const FormRoot = ({ schema, idMap, setIdMap, form, children, onSubmit = undefined, displayConfig = {
|
|
8075
8047
|
showSubmitButton: true,
|
|
8076
8048
|
showResetButton: true,
|
|
8077
8049
|
showTitle: true,
|
|
8078
8050
|
}, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog = false, }) => {
|
|
8079
|
-
const [isSuccess, setIsSuccess] = useState(false);
|
|
8080
|
-
const [isError, setIsError] = useState(false);
|
|
8081
|
-
const [isSubmiting, setIsSubmiting] = useState(false);
|
|
8082
|
-
const [validatedData, setValidatedData] = useState();
|
|
8083
|
-
const [error, setError] = useState();
|
|
8084
|
-
const onBeforeSubmit = () => {
|
|
8085
|
-
setIsSubmiting(true);
|
|
8086
|
-
};
|
|
8087
|
-
const onAfterSubmit = () => {
|
|
8088
|
-
setIsSubmiting(false);
|
|
8089
|
-
};
|
|
8090
|
-
const onSubmitError = (error) => {
|
|
8091
|
-
setIsError(true);
|
|
8092
|
-
setError(error);
|
|
8093
|
-
};
|
|
8094
|
-
const onSubmitSuccess = () => {
|
|
8095
|
-
setIsSuccess(true);
|
|
8096
|
-
};
|
|
8097
|
-
const defaultOnSubmit = async (promise) => {
|
|
8098
|
-
try {
|
|
8099
|
-
console.log('onBeforeSubmit');
|
|
8100
|
-
onBeforeSubmit();
|
|
8101
|
-
await promise;
|
|
8102
|
-
console.log('onSubmitSuccess');
|
|
8103
|
-
onSubmitSuccess();
|
|
8104
|
-
}
|
|
8105
|
-
catch (error) {
|
|
8106
|
-
console.log('onSubmitError', error);
|
|
8107
|
-
onSubmitError(error);
|
|
8108
|
-
}
|
|
8109
|
-
finally {
|
|
8110
|
-
onAfterSubmit();
|
|
8111
|
-
}
|
|
8112
|
-
};
|
|
8113
|
-
const defaultSubmitPromise = (data) => {
|
|
8114
|
-
if (!requestOptions.url) {
|
|
8115
|
-
throw new Error('requestOptions.url is required when onSubmit is not provided');
|
|
8116
|
-
}
|
|
8117
|
-
const options = {
|
|
8118
|
-
method: 'POST',
|
|
8119
|
-
data: clearEmptyString(data),
|
|
8120
|
-
...requestOptions,
|
|
8121
|
-
};
|
|
8122
|
-
return axios.request(options);
|
|
8123
|
-
};
|
|
8124
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8125
|
-
const onFormSubmit = async (data) => {
|
|
8126
|
-
// Validation is handled by react-hook-form
|
|
8127
|
-
// This function will only be called if validation passes
|
|
8128
|
-
if (onSubmit === undefined) {
|
|
8129
|
-
await defaultOnSubmit(Promise.resolve(defaultSubmitPromise(data)));
|
|
8130
|
-
return;
|
|
8131
|
-
}
|
|
8132
|
-
await defaultOnSubmit(Promise.resolve(onSubmit(data)));
|
|
8133
|
-
};
|
|
8134
8051
|
return (jsx(SchemaFormContext.Provider, { value: {
|
|
8135
8052
|
schema,
|
|
8136
|
-
order,
|
|
8137
|
-
ignore,
|
|
8138
|
-
include,
|
|
8139
8053
|
// @ts-expect-error TODO: find appropriate types
|
|
8140
8054
|
onSubmit,
|
|
8141
|
-
rowNumber,
|
|
8142
8055
|
idMap,
|
|
8143
8056
|
setIdMap,
|
|
8144
|
-
requestOptions,
|
|
8145
|
-
isSuccess,
|
|
8146
|
-
setIsSuccess,
|
|
8147
|
-
isError,
|
|
8148
|
-
setIsError,
|
|
8149
|
-
isSubmiting,
|
|
8150
|
-
setIsSubmiting,
|
|
8151
|
-
validatedData,
|
|
8152
|
-
setValidatedData,
|
|
8153
|
-
error,
|
|
8154
|
-
setError,
|
|
8155
|
-
getUpdatedData,
|
|
8156
|
-
customErrorRenderer,
|
|
8157
|
-
customSuccessRenderer,
|
|
8158
8057
|
displayConfig,
|
|
8159
|
-
onFormSubmit,
|
|
8160
8058
|
dateTimePickerLabels,
|
|
8161
8059
|
idPickerLabels,
|
|
8162
8060
|
enumPickerLabels,
|
|
@@ -8172,223 +8070,15 @@ const DefaultForm = ({ formConfig, }) => {
|
|
|
8172
8070
|
return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
|
|
8173
8071
|
};
|
|
8174
8072
|
|
|
8175
|
-
|
|
8176
|
-
const ajv = new Ajv({
|
|
8177
|
-
strict: false,
|
|
8178
|
-
allErrors: true,
|
|
8179
|
-
});
|
|
8180
|
-
addFormats(ajv);
|
|
8181
|
-
AjvErrors(ajv); // Load ajv-errors plugin to process errorMessage format
|
|
8182
|
-
const validate = ajv.compile(schema);
|
|
8183
|
-
const validationResult = validate(data);
|
|
8184
|
-
const errors = validate.errors;
|
|
8185
|
-
return {
|
|
8186
|
-
isValid: validationResult,
|
|
8187
|
-
validate,
|
|
8188
|
-
errors,
|
|
8189
|
-
};
|
|
8190
|
-
};
|
|
8191
|
-
|
|
8192
|
-
/**
|
|
8193
|
-
* Gets the schema node for a given field path
|
|
8194
|
-
*/
|
|
8195
|
-
const getSchemaNodeForField = (schema, fieldPath) => {
|
|
8196
|
-
if (!fieldPath || fieldPath === '') {
|
|
8197
|
-
return schema;
|
|
8198
|
-
}
|
|
8199
|
-
const pathParts = fieldPath.split('.');
|
|
8200
|
-
let currentSchema = schema;
|
|
8201
|
-
for (const part of pathParts) {
|
|
8202
|
-
if (currentSchema &&
|
|
8203
|
-
currentSchema.properties &&
|
|
8204
|
-
currentSchema.properties[part] &&
|
|
8205
|
-
typeof currentSchema.properties[part] === 'object' &&
|
|
8206
|
-
currentSchema.properties[part] !== null) {
|
|
8207
|
-
currentSchema = currentSchema.properties[part];
|
|
8208
|
-
}
|
|
8209
|
-
else {
|
|
8210
|
-
return undefined;
|
|
8211
|
-
}
|
|
8212
|
-
}
|
|
8213
|
-
return currentSchema;
|
|
8214
|
-
};
|
|
8215
|
-
/**
|
|
8216
|
-
* Strips null, undefined, and empty string values from an object
|
|
8217
|
-
*/
|
|
8218
|
-
const stripEmptyValues = (obj) => {
|
|
8219
|
-
if (obj === null || obj === undefined) {
|
|
8220
|
-
return undefined;
|
|
8221
|
-
}
|
|
8222
|
-
if (typeof obj === 'string' && obj.trim() === '') {
|
|
8223
|
-
return undefined;
|
|
8224
|
-
}
|
|
8225
|
-
if (Array.isArray(obj)) {
|
|
8226
|
-
const filtered = obj
|
|
8227
|
-
.map(stripEmptyValues)
|
|
8228
|
-
.filter((item) => item !== undefined);
|
|
8229
|
-
return filtered.length > 0 ? filtered : undefined;
|
|
8230
|
-
}
|
|
8231
|
-
if (typeof obj === 'object' && obj !== null) {
|
|
8232
|
-
const result = {};
|
|
8233
|
-
let hasValues = false;
|
|
8234
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
8235
|
-
const cleanedValue = stripEmptyValues(value);
|
|
8236
|
-
if (cleanedValue !== undefined) {
|
|
8237
|
-
result[key] = cleanedValue;
|
|
8238
|
-
hasValues = true;
|
|
8239
|
-
}
|
|
8240
|
-
}
|
|
8241
|
-
return hasValues ? result : undefined;
|
|
8242
|
-
}
|
|
8243
|
-
return obj;
|
|
8244
|
-
};
|
|
8245
|
-
/**
|
|
8246
|
-
* Converts AJV error objects to react-hook-form field errors format
|
|
8247
|
-
*/
|
|
8248
|
-
const convertAjvErrorsToFieldErrors = (errors, schema) => {
|
|
8249
|
-
if (!errors || errors.length === 0) {
|
|
8250
|
-
return {};
|
|
8251
|
-
}
|
|
8252
|
-
const fieldErrors = {};
|
|
8253
|
-
errors.forEach((error) => {
|
|
8254
|
-
let fieldName = '';
|
|
8255
|
-
// Special handling for required keyword: map to the specific missing property
|
|
8256
|
-
if (error.keyword === 'required') {
|
|
8257
|
-
const basePath = (error.instancePath || '')
|
|
8258
|
-
.replace(/^\//, '')
|
|
8259
|
-
.replace(/\//g, '.');
|
|
8260
|
-
const missingProperty = error.params && error.params.missingProperty;
|
|
8261
|
-
if (missingProperty) {
|
|
8262
|
-
fieldName = basePath
|
|
8263
|
-
? `${basePath}.${missingProperty}`
|
|
8264
|
-
: missingProperty;
|
|
8265
|
-
}
|
|
8266
|
-
else {
|
|
8267
|
-
// Fallback to schemaPath conversion if missingProperty is unavailable
|
|
8268
|
-
fieldName = (error.schemaPath || '')
|
|
8269
|
-
.replace(/^#\//, '#.')
|
|
8270
|
-
.replace(/\//g, '.');
|
|
8271
|
-
}
|
|
8272
|
-
}
|
|
8273
|
-
else {
|
|
8274
|
-
const fieldPath = error.instancePath || error.schemaPath;
|
|
8275
|
-
if (fieldPath) {
|
|
8276
|
-
fieldName = fieldPath.replace(/^\//, '').replace(/\//g, '.');
|
|
8277
|
-
}
|
|
8278
|
-
}
|
|
8279
|
-
if (fieldName) {
|
|
8280
|
-
// Get the schema node for this field to check for custom error messages
|
|
8281
|
-
const fieldSchema = getSchemaNodeForField(schema, fieldName);
|
|
8282
|
-
const customMessage = fieldSchema?.errorMessages?.[error.keyword];
|
|
8283
|
-
// Debug log when error message is missing
|
|
8284
|
-
if (!customMessage) {
|
|
8285
|
-
console.debug(`[Form Validation] Missing error message for field '${fieldName}' with keyword '${error.keyword}'. Add errorMessages.${error.keyword} to schema for field '${fieldName}'`, {
|
|
8286
|
-
fieldName,
|
|
8287
|
-
keyword: error.keyword,
|
|
8288
|
-
instancePath: error.instancePath,
|
|
8289
|
-
schemaPath: error.schemaPath,
|
|
8290
|
-
params: error.params,
|
|
8291
|
-
fieldSchema: fieldSchema
|
|
8292
|
-
? {
|
|
8293
|
-
type: fieldSchema.type,
|
|
8294
|
-
errorMessages: fieldSchema
|
|
8295
|
-
.errorMessages,
|
|
8296
|
-
}
|
|
8297
|
-
: undefined,
|
|
8298
|
-
});
|
|
8299
|
-
}
|
|
8300
|
-
// Provide helpful fallback message if no custom message is provided
|
|
8301
|
-
const fallbackMessage = customMessage ||
|
|
8302
|
-
`Missing error message for ${error.keyword}. Add errorMessages.${error.keyword} to schema for field '${fieldName}'`;
|
|
8303
|
-
if (error.keyword === 'required') {
|
|
8304
|
-
// Required errors override any existing non-required errors for this field
|
|
8305
|
-
fieldErrors[fieldName] = {
|
|
8306
|
-
type: 'required',
|
|
8307
|
-
keyword: error.keyword,
|
|
8308
|
-
params: error.params,
|
|
8309
|
-
message: fallbackMessage,
|
|
8310
|
-
};
|
|
8311
|
-
}
|
|
8312
|
-
else {
|
|
8313
|
-
const existing = fieldErrors[fieldName];
|
|
8314
|
-
if (existing) {
|
|
8315
|
-
// Do not override required errors
|
|
8316
|
-
if (existing.type === 'required') {
|
|
8317
|
-
return;
|
|
8318
|
-
}
|
|
8319
|
-
// Combine messages if multiple errors for same field
|
|
8320
|
-
existing.message = existing.message
|
|
8321
|
-
? `${existing.message}; ${fallbackMessage}`
|
|
8322
|
-
: fallbackMessage;
|
|
8323
|
-
}
|
|
8324
|
-
else {
|
|
8325
|
-
fieldErrors[fieldName] = {
|
|
8326
|
-
type: error.keyword,
|
|
8327
|
-
keyword: error.keyword,
|
|
8328
|
-
params: error.params,
|
|
8329
|
-
message: fallbackMessage,
|
|
8330
|
-
};
|
|
8331
|
-
}
|
|
8332
|
-
}
|
|
8333
|
-
}
|
|
8334
|
-
});
|
|
8335
|
-
return fieldErrors;
|
|
8336
|
-
};
|
|
8337
|
-
/**
|
|
8338
|
-
* AJV resolver for react-hook-form
|
|
8339
|
-
* Integrates AJV validation with react-hook-form's validation system
|
|
8340
|
-
*/
|
|
8341
|
-
const ajvResolver = (schema) => {
|
|
8342
|
-
return async (values) => {
|
|
8343
|
-
try {
|
|
8344
|
-
// Strip empty values before validation
|
|
8345
|
-
const cleanedValues = stripEmptyValues(values);
|
|
8346
|
-
// Use empty object for validation if all values were stripped
|
|
8347
|
-
const valuesToValidate = cleanedValues === undefined ? {} : cleanedValues;
|
|
8348
|
-
const { isValid, errors } = validateData(valuesToValidate, schema);
|
|
8349
|
-
console.debug('AJV Validation Result:', {
|
|
8350
|
-
isValid,
|
|
8351
|
-
errors,
|
|
8352
|
-
cleanedValues,
|
|
8353
|
-
valuesToValidate,
|
|
8354
|
-
});
|
|
8355
|
-
if (isValid) {
|
|
8356
|
-
return {
|
|
8357
|
-
values: (cleanedValues || {}),
|
|
8358
|
-
errors: {},
|
|
8359
|
-
};
|
|
8360
|
-
}
|
|
8361
|
-
const fieldErrors = convertAjvErrorsToFieldErrors(errors, schema);
|
|
8362
|
-
console.debug('AJV Validation Failed:', {
|
|
8363
|
-
errors,
|
|
8364
|
-
fieldErrors,
|
|
8365
|
-
cleanedValues,
|
|
8366
|
-
valuesToValidate,
|
|
8367
|
-
});
|
|
8368
|
-
return {
|
|
8369
|
-
values: {},
|
|
8370
|
-
errors: fieldErrors,
|
|
8371
|
-
};
|
|
8372
|
-
}
|
|
8373
|
-
catch (error) {
|
|
8374
|
-
return {
|
|
8375
|
-
values: {},
|
|
8376
|
-
errors: {
|
|
8377
|
-
root: {
|
|
8378
|
-
type: 'validation',
|
|
8379
|
-
message: error instanceof Error ? error.message : 'Validation failed',
|
|
8380
|
-
},
|
|
8381
|
-
},
|
|
8382
|
-
};
|
|
8383
|
-
}
|
|
8384
|
-
};
|
|
8385
|
-
};
|
|
8386
|
-
|
|
8387
|
-
const useForm = ({ preLoadedValues, schema }) => {
|
|
8073
|
+
function useForm({ preLoadedValues, schema, }) {
|
|
8388
8074
|
const form = useForm$1({
|
|
8389
8075
|
values: preLoadedValues,
|
|
8390
8076
|
mode: 'onSubmit',
|
|
8391
|
-
resolver: schema
|
|
8077
|
+
resolver: schema
|
|
8078
|
+
? ajvResolver(schema, {
|
|
8079
|
+
strict: false,
|
|
8080
|
+
})
|
|
8081
|
+
: undefined,
|
|
8392
8082
|
reValidateMode: 'onChange',
|
|
8393
8083
|
});
|
|
8394
8084
|
const [idMap, setIdMap] = useState({});
|
|
@@ -8397,7 +8087,7 @@ const useForm = ({ preLoadedValues, schema }) => {
|
|
|
8397
8087
|
idMap,
|
|
8398
8088
|
setIdMap,
|
|
8399
8089
|
};
|
|
8400
|
-
}
|
|
8090
|
+
}
|
|
8401
8091
|
|
|
8402
8092
|
const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) => {
|
|
8403
8093
|
if (!selectable) {
|
|
@@ -1,38 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Dispatch, ReactNode, SetStateAction } from 'react';
|
|
1
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
3
2
|
import { FieldValues } from 'react-hook-form';
|
|
4
3
|
import { CustomJSONSchema7, DateTimePickerLabels, EnumPickerLabels, FilePickerLabels, FormButtonLabels, IdPickerLabels, TimePickerLabels } from './components/types/CustomJSONSchema7';
|
|
5
4
|
export interface SchemaFormContext<TData extends FieldValues> {
|
|
6
5
|
schema: CustomJSONSchema7;
|
|
7
|
-
requestUrl: string;
|
|
8
|
-
order: string[];
|
|
9
|
-
ignore: string[];
|
|
10
|
-
include: string[];
|
|
11
6
|
onSubmit?: (data: TData) => Promise<void>;
|
|
12
|
-
rowNumber?: number | string;
|
|
13
7
|
idMap: Record<string, object>;
|
|
14
8
|
setIdMap: Dispatch<SetStateAction<Record<string, object>>>;
|
|
15
|
-
requestOptions: AxiosRequestConfig;
|
|
16
|
-
isSuccess: boolean;
|
|
17
|
-
setIsSuccess: Dispatch<SetStateAction<boolean>>;
|
|
18
|
-
isError: boolean;
|
|
19
|
-
setIsError: Dispatch<SetStateAction<boolean>>;
|
|
20
|
-
isSubmiting: boolean;
|
|
21
|
-
setIsSubmiting: Dispatch<SetStateAction<boolean>>;
|
|
22
|
-
validatedData: TData | undefined;
|
|
23
|
-
setValidatedData: Dispatch<SetStateAction<TData>>;
|
|
24
|
-
error: unknown;
|
|
25
|
-
setError: Dispatch<SetStateAction<unknown>>;
|
|
26
|
-
getUpdatedData: () => TData | Promise<TData>;
|
|
27
|
-
customErrorRenderer?: (error: unknown) => ReactNode;
|
|
28
|
-
customSuccessRenderer?: (resetHandler: () => void | Promise<void>) => ReactNode;
|
|
29
9
|
timezone?: string;
|
|
30
10
|
displayConfig: {
|
|
31
11
|
showSubmitButton?: boolean;
|
|
32
12
|
showResetButton?: boolean;
|
|
33
13
|
showTitle?: boolean;
|
|
34
14
|
};
|
|
35
|
-
onFormSubmit: (data: TData) => Promise<void>;
|
|
36
15
|
dateTimePickerLabels?: DateTimePickerLabels;
|
|
37
16
|
idPickerLabels?: IdPickerLabels;
|
|
38
17
|
enumPickerLabels?: EnumPickerLabels;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AxiosRequestConfig } from 'axios';
|
|
2
1
|
import { JSONSchema7 } from 'json-schema';
|
|
3
2
|
import { Dispatch, ReactNode, SetStateAction } from 'react';
|
|
4
3
|
import { FieldValues, SubmitHandler, UseFormReturn } from 'react-hook-form';
|
|
@@ -30,20 +29,11 @@ export interface FormRootProps<TData extends FieldValues> {
|
|
|
30
29
|
* }
|
|
31
30
|
*/
|
|
32
31
|
schema: CustomJSONSchema7;
|
|
33
|
-
requestUrl?: string;
|
|
34
32
|
idMap: Record<string, object>;
|
|
35
33
|
setIdMap: Dispatch<SetStateAction<Record<string, object>>>;
|
|
36
|
-
form: UseFormReturn
|
|
34
|
+
form: UseFormReturn<TData, any, TData>;
|
|
37
35
|
children: ReactNode;
|
|
38
|
-
order?: string[];
|
|
39
|
-
ignore?: string[];
|
|
40
|
-
include?: string[];
|
|
41
36
|
onSubmit?: SubmitHandler<TData>;
|
|
42
|
-
rowNumber?: number | string;
|
|
43
|
-
requestOptions?: AxiosRequestConfig;
|
|
44
|
-
getUpdatedData?: () => TData | Promise<TData> | void;
|
|
45
|
-
customErrorRenderer?: (error: unknown) => ReactNode;
|
|
46
|
-
customSuccessRenderer?: (resetHandler: () => void | Promise<void>) => ReactNode;
|
|
47
37
|
displayConfig?: {
|
|
48
38
|
showSubmitButton?: boolean;
|
|
49
39
|
showResetButton?: boolean;
|
|
@@ -64,4 +54,4 @@ export interface CustomJSONSchema7Definition extends JSONSchema7 {
|
|
|
64
54
|
customQueryFn: any;
|
|
65
55
|
children: ReactNode;
|
|
66
56
|
}
|
|
67
|
-
export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, children,
|
|
57
|
+
export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, children, onSubmit, displayConfig, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, timePickerLabels, insideDialog, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -85,7 +85,7 @@ export interface CustomJSONSchema7 extends Omit<JSONSchema7, 'items' | 'addition
|
|
|
85
85
|
gridColumn?: string;
|
|
86
86
|
gridRow?: string;
|
|
87
87
|
customQueryFn?: CustomQueryFn;
|
|
88
|
-
variant?: 'custom-input' | 'id-picker' | 'text-area' | 'media-library-browser' | 'tag-picker' | 'file-picker' | 'date-range' | 'enum-picker';
|
|
88
|
+
variant?: 'custom-input' | 'id-picker' | 'text-area' | 'media-library-browser' | 'tag-picker' | 'file-picker' | 'date-range' | 'enum-picker' | 'radio';
|
|
89
89
|
renderDisplay?: (item: unknown) => ReactNode;
|
|
90
90
|
itemToValue?: (item: unknown) => string;
|
|
91
91
|
loadInitialValues?: (params: LoadInitialValuesParams) => Promise<LoadInitialValuesResult>;
|
|
@@ -108,7 +108,7 @@ export interface CustomJSONSchema7 extends Omit<JSONSchema7, 'items' | 'addition
|
|
|
108
108
|
showLabel?: boolean;
|
|
109
109
|
formatOptions?: Intl.NumberFormatOptions;
|
|
110
110
|
numberStorageType?: 'string' | 'number';
|
|
111
|
-
|
|
111
|
+
errorMessage?: Record<Partial<ValidationErrorType> | string, string | Record<string, string>>;
|
|
112
112
|
filePicker?: FilePickerProps;
|
|
113
113
|
tagPicker?: {
|
|
114
114
|
queryFn?: (params: {
|