@bsol-oss/react-datatable5 12.0.0-beta.63 → 12.0.0-beta.65
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 +11 -6
- package/dist/index.js +51 -42
- package/dist/index.mjs +52 -43
- package/dist/types/components/DataTable/DataTableServer.d.ts +4 -4
- package/dist/types/components/Form/SchemaFormContext.d.ts +5 -0
- package/dist/types/components/Form/components/core/DefaultForm.d.ts +1 -1
- package/dist/types/components/Form/components/core/FormRoot.d.ts +6 -1
- package/dist/types/components/Form/utils/validateData.d.ts +9 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -253,7 +253,7 @@ interface DataResponse<T = unknown> extends Result<T> {
|
|
|
253
253
|
}
|
|
254
254
|
declare const useDataTableServer: <TData>({ url, default: { sorting: defaultSorting, pagination: defaultPagination, rowSelection: defaultRowSelection, columnFilters: defaultColumnFilters, columnOrder: defaultColumnOrder, columnVisibility: defaultColumnVisibility, globalFilter: defaultGlobalFilter, density: defaultDensity, }, keyPrefix, }: UseDataTableServerProps) => UseDataTableServerReturn<TData>;
|
|
255
255
|
|
|
256
|
-
interface DataTableServerProps<TData
|
|
256
|
+
interface DataTableServerProps<TData = unknown> {
|
|
257
257
|
children: ReactNode | ReactNode[];
|
|
258
258
|
/**
|
|
259
259
|
* Column definitions for the table.
|
|
@@ -282,10 +282,10 @@ interface DataTableServerProps<TData extends DataResponse = DataResponse<unknown
|
|
|
282
282
|
setColumnOrder: OnChangeFn<ColumnOrderState>;
|
|
283
283
|
setDensity: OnChangeFn<DensityState>;
|
|
284
284
|
setColumnVisibility: OnChangeFn<VisibilityState>;
|
|
285
|
-
query: UseQueryResult<TData
|
|
285
|
+
query: UseQueryResult<DataResponse<TData>>;
|
|
286
286
|
url: string;
|
|
287
287
|
translate: UseTranslationResponse<any, any>;
|
|
288
|
-
tableLabel
|
|
288
|
+
tableLabel?: DataTableLabel;
|
|
289
289
|
}
|
|
290
290
|
/**
|
|
291
291
|
* DataTableServer will create a context to hold all values to
|
|
@@ -298,7 +298,7 @@ interface DataTableServerProps<TData extends DataResponse = DataResponse<unknown
|
|
|
298
298
|
*
|
|
299
299
|
* @link https://tanstack.com/table/latest/docs/guide/column-defs
|
|
300
300
|
*/
|
|
301
|
-
declare function DataTableServer<TData
|
|
301
|
+
declare function DataTableServer<TData = unknown>({ columns, enableRowSelection, enableMultiRowSelection, enableSubRowSelection, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel, }: DataTableServerProps<TData>): react_jsx_runtime.JSX.Element;
|
|
302
302
|
|
|
303
303
|
interface TableControlsProps {
|
|
304
304
|
totalText?: string;
|
|
@@ -547,6 +547,11 @@ interface FormRootProps<TData extends FieldValues> {
|
|
|
547
547
|
requestOptions?: AxiosRequestConfig;
|
|
548
548
|
getUpdatedData?: () => TData | Promise<TData> | void;
|
|
549
549
|
customErrorRenderer?: (error: unknown) => ReactNode;
|
|
550
|
+
displayConfig?: {
|
|
551
|
+
showSubmitButton?: boolean;
|
|
552
|
+
showResetButton?: boolean;
|
|
553
|
+
showTitle?: boolean;
|
|
554
|
+
};
|
|
550
555
|
}
|
|
551
556
|
interface CustomJSONSchema7Definition extends JSONSchema7 {
|
|
552
557
|
variant: string;
|
|
@@ -563,13 +568,13 @@ declare const idPickerSanityCheck: (column: string, foreign_key?: {
|
|
|
563
568
|
column?: string | undefined;
|
|
564
569
|
display_column?: string | undefined;
|
|
565
570
|
} | undefined) => void;
|
|
566
|
-
declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
|
|
571
|
+
declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, displayConfig, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
|
|
567
572
|
|
|
568
573
|
interface DefaultFormProps<TData extends FieldValues> {
|
|
569
574
|
formConfig: Omit<FormRootProps<TData>, "children">;
|
|
570
575
|
showTitle?: boolean;
|
|
571
576
|
}
|
|
572
|
-
declare const DefaultForm: <TData extends FieldValues>({ formConfig,
|
|
577
|
+
declare const DefaultForm: <TData extends FieldValues>({ formConfig, }: DefaultFormProps<TData>) => react_jsx_runtime.JSX.Element;
|
|
573
578
|
|
|
574
579
|
declare const FormTitle: () => react_jsx_runtime.JSX.Element;
|
|
575
580
|
|
package/dist/index.js
CHANGED
|
@@ -29,13 +29,13 @@ var gr = require('react-icons/gr');
|
|
|
29
29
|
var reactI18next = require('react-i18next');
|
|
30
30
|
var axios = require('axios');
|
|
31
31
|
var reactHookForm = require('react-hook-form');
|
|
32
|
+
var Ajv = require('ajv');
|
|
33
|
+
var addFormats = require('ajv-formats');
|
|
34
|
+
var addErrors = require('ajv-errors');
|
|
32
35
|
var dayjs = require('dayjs');
|
|
33
36
|
var utc = require('dayjs/plugin/utc');
|
|
34
37
|
var timezone = require('dayjs/plugin/timezone');
|
|
35
38
|
var ti = require('react-icons/ti');
|
|
36
|
-
var Ajv = require('ajv');
|
|
37
|
-
var addFormats = require('ajv-formats');
|
|
38
|
-
var addErrors = require('ajv-errors');
|
|
39
39
|
|
|
40
40
|
function _interopNamespaceDefault(e) {
|
|
41
41
|
var n = Object.create(null);
|
|
@@ -3693,6 +3693,11 @@ const SchemaFormContext = React.createContext({
|
|
|
3693
3693
|
rowNumber: 0,
|
|
3694
3694
|
requestOptions: {},
|
|
3695
3695
|
timezone: 'Asia/Hong_Kong',
|
|
3696
|
+
displayConfig: {
|
|
3697
|
+
showSubmitButton: true,
|
|
3698
|
+
showResetButton: true,
|
|
3699
|
+
showTitle: true,
|
|
3700
|
+
},
|
|
3696
3701
|
});
|
|
3697
3702
|
|
|
3698
3703
|
const useSchemaContext = () => {
|
|
@@ -3703,6 +3708,23 @@ const clearEmptyString = (object) => {
|
|
|
3703
3708
|
return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
|
|
3704
3709
|
};
|
|
3705
3710
|
|
|
3711
|
+
const validateData = (data, schema) => {
|
|
3712
|
+
const ajv = new Ajv({
|
|
3713
|
+
strict: false,
|
|
3714
|
+
allErrors: true,
|
|
3715
|
+
});
|
|
3716
|
+
addFormats(ajv);
|
|
3717
|
+
addErrors(ajv);
|
|
3718
|
+
const validate = ajv.compile(schema);
|
|
3719
|
+
const validationResult = validate(data);
|
|
3720
|
+
const errors = validate.errors;
|
|
3721
|
+
return {
|
|
3722
|
+
isValid: validationResult,
|
|
3723
|
+
validate,
|
|
3724
|
+
errors,
|
|
3725
|
+
};
|
|
3726
|
+
};
|
|
3727
|
+
|
|
3706
3728
|
const idPickerSanityCheck = (column, foreign_key) => {
|
|
3707
3729
|
if (!!foreign_key == false) {
|
|
3708
3730
|
throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
|
|
@@ -3718,7 +3740,11 @@ const idPickerSanityCheck = (column, foreign_key) => {
|
|
|
3718
3740
|
throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
|
|
3719
3741
|
}
|
|
3720
3742
|
};
|
|
3721
|
-
const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer,
|
|
3743
|
+
const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, displayConfig = {
|
|
3744
|
+
showSubmitButton: true,
|
|
3745
|
+
showResetButton: true,
|
|
3746
|
+
showTitle: true,
|
|
3747
|
+
}, }) => {
|
|
3722
3748
|
const [isSuccess, setIsSuccess] = React.useState(false);
|
|
3723
3749
|
const [isError, setIsError] = React.useState(false);
|
|
3724
3750
|
const [isSubmiting, setIsSubmiting] = React.useState(false);
|
|
@@ -3752,6 +3778,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
3752
3778
|
setError,
|
|
3753
3779
|
getUpdatedData,
|
|
3754
3780
|
customErrorRenderer,
|
|
3781
|
+
displayConfig,
|
|
3755
3782
|
}, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
|
|
3756
3783
|
};
|
|
3757
3784
|
|
|
@@ -4087,7 +4114,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4087
4114
|
setOpenSearchResult(true);
|
|
4088
4115
|
}, justifyContent: "start", children: !!watchEnum === false
|
|
4089
4116
|
? ""
|
|
4090
|
-
: translate.t(removeIndex(`${colLabel}.${watchEnum ?? "null"}`)) })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
|
|
4117
|
+
: translate.t(removeIndex(`${colLabel}.${watchEnum ?? "null"}`)) })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
|
|
4091
4118
|
onSearchChange(event);
|
|
4092
4119
|
setOpenSearchResult(true);
|
|
4093
4120
|
}, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), showTotalAndLimit && (jsxRuntime.jsx(react.Text, { children: `${translate.t(removeIndex(`${colLabel}.total`))}: ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` })), jsxRuntime.jsxs(react.Grid, { overflow: "auto", maxHeight: "20rem", children: [jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children: dataList
|
|
@@ -4674,7 +4701,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4674
4701
|
setOpenSearchResult(true);
|
|
4675
4702
|
}, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
|
|
4676
4703
|
setOpenSearchResult(true);
|
|
4677
|
-
}, justifyContent: "start", children: queryDefault.isLoading ? jsxRuntime.jsx(react.Spinner, { size: "sm" }) : getPickedValue() })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(removeIndex(`${colLabel}.type_to_search`)), onChange: onSearchChange, autoComplete: "off", ref: ref, value: searchText }), jsxRuntime.jsx(PopoverTitle, {}), openSearchResult && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, {}), isError && (jsxRuntime.jsx(react.Icon, { color: "red.400", children: jsxRuntime.jsx(bi.BiError, {}) })), jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", children: [jsxRuntime.jsx(InfoTip, { children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit} ${translate.t(removeIndex(`${colLabel}.per_page`), "per page")}` }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxRuntime.jsxs(react.Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/ ", count > 0 ? `${page * limit + 1}-${Math.min((page + 1) * limit, count)}` : '0'] })] })] }), jsxRuntime.jsx(react.Box, { children: jsxRuntime.jsxs("select", { value: limit, onChange: handleLimitChange, style: {
|
|
4704
|
+
}, justifyContent: "start", children: queryDefault.isLoading ? jsxRuntime.jsx(react.Spinner, { size: "sm" }) : getPickedValue() })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(removeIndex(`${colLabel}.type_to_search`)), onChange: onSearchChange, autoComplete: "off", ref: ref, value: searchText }), jsxRuntime.jsx(PopoverTitle, {}), openSearchResult && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, {}), isError && (jsxRuntime.jsx(react.Icon, { color: "red.400", children: jsxRuntime.jsx(bi.BiError, {}) })), jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", children: [jsxRuntime.jsx(InfoTip, { children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit} ${translate.t(removeIndex(`${colLabel}.per_page`), "per page")}` }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxRuntime.jsxs(react.Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/ ", count > 0 ? `${page * limit + 1}-${Math.min((page + 1) * limit, count)}` : '0'] })] })] }), jsxRuntime.jsx(react.Box, { children: jsxRuntime.jsxs("select", { value: limit, onChange: handleLimitChange, style: {
|
|
4678
4705
|
padding: "4px 8px",
|
|
4679
4706
|
borderRadius: "4px",
|
|
4680
4707
|
border: "1px solid #ccc",
|
|
@@ -5942,16 +5969,12 @@ const SubmitButton = () => {
|
|
|
5942
5969
|
const methods = reactHookForm.useFormContext();
|
|
5943
5970
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5944
5971
|
const onValid = (data) => {
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
// @ts-expect-error TODO: find appropriate type
|
|
5952
|
-
const errors = validationResult.errors;
|
|
5953
|
-
if (errors && errors.length > 0) {
|
|
5954
|
-
setError(errors);
|
|
5972
|
+
const { isValid, errors } = validateData(data, schema);
|
|
5973
|
+
if (!isValid) {
|
|
5974
|
+
setError({
|
|
5975
|
+
type: "validation",
|
|
5976
|
+
errors,
|
|
5977
|
+
});
|
|
5955
5978
|
setIsError(true);
|
|
5956
5979
|
return;
|
|
5957
5980
|
}
|
|
@@ -5966,7 +5989,8 @@ const SubmitButton = () => {
|
|
|
5966
5989
|
};
|
|
5967
5990
|
|
|
5968
5991
|
const FormBody = () => {
|
|
5969
|
-
const { schema, requestUrl, order, ignore, include, onSubmit,
|
|
5992
|
+
const { schema, requestUrl, order, ignore, include, onSubmit, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, displayConfig, } = useSchemaContext();
|
|
5993
|
+
const { showSubmitButton, showResetButton } = displayConfig;
|
|
5970
5994
|
const methods = reactHookForm.useFormContext();
|
|
5971
5995
|
const { properties } = schema;
|
|
5972
5996
|
const onBeforeSubmit = () => {
|
|
@@ -5982,24 +6006,11 @@ const FormBody = () => {
|
|
|
5982
6006
|
const onSubmitSuccess = () => {
|
|
5983
6007
|
setIsSuccess(true);
|
|
5984
6008
|
};
|
|
5985
|
-
// Enhanced validation function using AJV with i18n support
|
|
5986
6009
|
const validateFormData = (data) => {
|
|
5987
6010
|
try {
|
|
5988
|
-
const
|
|
5989
|
-
strict: false,
|
|
5990
|
-
allErrors: true,
|
|
5991
|
-
});
|
|
5992
|
-
addFormats(ajv);
|
|
5993
|
-
addErrors(ajv);
|
|
5994
|
-
const validate = ajv.compile(schema);
|
|
5995
|
-
const validationResult = validate(data);
|
|
5996
|
-
const errors = validate.errors;
|
|
5997
|
-
console.log({
|
|
5998
|
-
isValid: validationResult,
|
|
5999
|
-
errors,
|
|
6000
|
-
}, "plkdfs");
|
|
6011
|
+
const { isValid, errors } = validateData(data, schema);
|
|
6001
6012
|
return {
|
|
6002
|
-
isValid
|
|
6013
|
+
isValid,
|
|
6003
6014
|
errors,
|
|
6004
6015
|
};
|
|
6005
6016
|
}
|
|
@@ -6059,10 +6070,7 @@ const FormBody = () => {
|
|
|
6059
6070
|
};
|
|
6060
6071
|
// Custom error renderer for validation errors with i18n support
|
|
6061
6072
|
const renderValidationErrors = (validationErrors) => {
|
|
6062
|
-
return (jsxRuntime.jsx(
|
|
6063
|
-
base: "red.50",
|
|
6064
|
-
_dark: "red.950",
|
|
6065
|
-
}, p: "4", colorPalette: "red", collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "validation-errors", children: [jsxRuntime.jsx(AccordionItemTrigger, { children: translate.t("validation_error") }), jsxRuntime.jsx(AccordionItemContent, { display: "flex", flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxRuntime.jsxs(react.AlertRoot, { status: "error", display: "flex", alignItems: "center", children: [jsxRuntime.jsx(react.AlertIndicator, {}), jsxRuntime.jsx(react.AlertContent, { children: jsxRuntime.jsx(react.AlertDescription, { children: err.message }) })] }))) })] }) }));
|
|
6073
|
+
return (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxRuntime.jsxs(react.Alert.Root, { status: "error", display: "flex", alignItems: "center", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Description, { children: err.message }) })] }, index))) }));
|
|
6066
6074
|
};
|
|
6067
6075
|
const renderColumns = ({ order, keys, ignore, include, }) => {
|
|
6068
6076
|
const included = include.length > 0 ? include : keys;
|
|
@@ -6078,7 +6086,7 @@ const FormBody = () => {
|
|
|
6078
6086
|
include,
|
|
6079
6087
|
});
|
|
6080
6088
|
if (isSuccess) {
|
|
6081
|
-
return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Title, { children: translate.t("submit_success") })] }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { onClick: async () => {
|
|
6089
|
+
return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Title, { children: translate.t("submit_success") }) })] }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { onClick: async () => {
|
|
6082
6090
|
setIsError(false);
|
|
6083
6091
|
setIsSubmiting(false);
|
|
6084
6092
|
setIsSuccess(false);
|
|
@@ -6100,7 +6108,7 @@ const FormBody = () => {
|
|
|
6100
6108
|
}, variant: "subtle", children: translate.t("cancel") }), jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
6101
6109
|
onFormSubmit(validatedData);
|
|
6102
6110
|
}, children: translate.t("confirm") })] }), isSubmiting && (jsxRuntime.jsx(react.Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsxRuntime.jsx(react.Center, { h: "full", children: jsxRuntime.jsx(react.Spinner, { color: "teal.500" }) }) })), isError && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: error?.type === "validation" &&
|
|
6103
|
-
error?.errors ? (renderValidationErrors(error.errors)) : (jsxRuntime.
|
|
6111
|
+
error?.errors ? (renderValidationErrors(error.errors)) : (jsxRuntime.jsxs(react.Alert.Root, { status: "error", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsxs(react.Alert.Content, { children: [jsxRuntime.jsx(react.Alert.Title, { children: "Error" }), jsxRuntime.jsx(react.Alert.Description, { children: jsxRuntime.jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "b", children: [jsxRuntime.jsx(AccordionItemTrigger, { children: `${error}` }), jsxRuntime.jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) })] })] })) })) }))] }));
|
|
6104
6112
|
}
|
|
6105
6113
|
return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: ordered.map((column) => {
|
|
6106
6114
|
return (jsxRuntime.jsx(ColumnRenderer
|
|
@@ -6108,10 +6116,10 @@ const FormBody = () => {
|
|
|
6108
6116
|
, {
|
|
6109
6117
|
// @ts-expect-error find suitable types
|
|
6110
6118
|
properties: properties, prefix: ``, column }, `form-input-${column}`));
|
|
6111
|
-
}) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
6119
|
+
}) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
6112
6120
|
methods.reset();
|
|
6113
|
-
}, variant: "subtle", children: translate.t("reset") }), jsxRuntime.jsx(SubmitButton, {})] }), isError &&
|
|
6114
|
-
|
|
6121
|
+
}, variant: "subtle", children: translate.t("reset") })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: error?.type === "validation" &&
|
|
6122
|
+
error?.errors ? (renderValidationErrors(error.errors)) : (jsxRuntime.jsxs(react.Alert.Root, { status: "error", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsxs(react.Alert.Content, { children: [jsxRuntime.jsx(react.Alert.Title, { children: "Error" }), jsxRuntime.jsx(react.Alert.Description, { children: jsxRuntime.jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "b", children: [jsxRuntime.jsx(AccordionItemTrigger, { children: `${error}` }), jsxRuntime.jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) })] })] })) })) }))] }));
|
|
6115
6123
|
};
|
|
6116
6124
|
|
|
6117
6125
|
const FormTitle = () => {
|
|
@@ -6119,7 +6127,8 @@ const FormTitle = () => {
|
|
|
6119
6127
|
return jsxRuntime.jsx(react.Heading, { children: translate.t("title") });
|
|
6120
6128
|
};
|
|
6121
6129
|
|
|
6122
|
-
const DefaultForm = ({ formConfig,
|
|
6130
|
+
const DefaultForm = ({ formConfig, }) => {
|
|
6131
|
+
const { showTitle } = formConfig.displayConfig ?? {};
|
|
6123
6132
|
return (jsxRuntime.jsx(FormRoot, { ...formConfig, children: jsxRuntime.jsxs(react.Grid, { gap: "2", children: [showTitle && jsxRuntime.jsx(FormTitle, {}), jsxRuntime.jsx(FormBody, {})] }) }));
|
|
6124
6133
|
};
|
|
6125
6134
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Accordion, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center,
|
|
2
|
+
import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Accordion, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading } from '@chakra-ui/react';
|
|
3
3
|
import { AiOutlineColumnWidth } from 'react-icons/ai';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import React__default, { createContext, useContext, useState, useEffect, useRef, forwardRef } from 'react';
|
|
@@ -28,13 +28,13 @@ import { GrAscend, GrDescend } from 'react-icons/gr';
|
|
|
28
28
|
import { useTranslation } from 'react-i18next';
|
|
29
29
|
import axios from 'axios';
|
|
30
30
|
import { FormProvider, useFormContext, useForm as useForm$1 } from 'react-hook-form';
|
|
31
|
+
import Ajv from 'ajv';
|
|
32
|
+
import addFormats from 'ajv-formats';
|
|
33
|
+
import addErrors from 'ajv-errors';
|
|
31
34
|
import dayjs from 'dayjs';
|
|
32
35
|
import utc from 'dayjs/plugin/utc';
|
|
33
36
|
import timezone from 'dayjs/plugin/timezone';
|
|
34
37
|
import { TiDeleteOutline } from 'react-icons/ti';
|
|
35
|
-
import Ajv from 'ajv';
|
|
36
|
-
import addFormats from 'ajv-formats';
|
|
37
|
-
import addErrors from 'ajv-errors';
|
|
38
38
|
|
|
39
39
|
const DataTableContext = createContext({
|
|
40
40
|
table: {},
|
|
@@ -3673,6 +3673,11 @@ const SchemaFormContext = createContext({
|
|
|
3673
3673
|
rowNumber: 0,
|
|
3674
3674
|
requestOptions: {},
|
|
3675
3675
|
timezone: 'Asia/Hong_Kong',
|
|
3676
|
+
displayConfig: {
|
|
3677
|
+
showSubmitButton: true,
|
|
3678
|
+
showResetButton: true,
|
|
3679
|
+
showTitle: true,
|
|
3680
|
+
},
|
|
3676
3681
|
});
|
|
3677
3682
|
|
|
3678
3683
|
const useSchemaContext = () => {
|
|
@@ -3683,6 +3688,23 @@ const clearEmptyString = (object) => {
|
|
|
3683
3688
|
return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
|
|
3684
3689
|
};
|
|
3685
3690
|
|
|
3691
|
+
const validateData = (data, schema) => {
|
|
3692
|
+
const ajv = new Ajv({
|
|
3693
|
+
strict: false,
|
|
3694
|
+
allErrors: true,
|
|
3695
|
+
});
|
|
3696
|
+
addFormats(ajv);
|
|
3697
|
+
addErrors(ajv);
|
|
3698
|
+
const validate = ajv.compile(schema);
|
|
3699
|
+
const validationResult = validate(data);
|
|
3700
|
+
const errors = validate.errors;
|
|
3701
|
+
return {
|
|
3702
|
+
isValid: validationResult,
|
|
3703
|
+
validate,
|
|
3704
|
+
errors,
|
|
3705
|
+
};
|
|
3706
|
+
};
|
|
3707
|
+
|
|
3686
3708
|
const idPickerSanityCheck = (column, foreign_key) => {
|
|
3687
3709
|
if (!!foreign_key == false) {
|
|
3688
3710
|
throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
|
|
@@ -3698,7 +3720,11 @@ const idPickerSanityCheck = (column, foreign_key) => {
|
|
|
3698
3720
|
throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
|
|
3699
3721
|
}
|
|
3700
3722
|
};
|
|
3701
|
-
const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer,
|
|
3723
|
+
const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, displayConfig = {
|
|
3724
|
+
showSubmitButton: true,
|
|
3725
|
+
showResetButton: true,
|
|
3726
|
+
showTitle: true,
|
|
3727
|
+
}, }) => {
|
|
3702
3728
|
const [isSuccess, setIsSuccess] = useState(false);
|
|
3703
3729
|
const [isError, setIsError] = useState(false);
|
|
3704
3730
|
const [isSubmiting, setIsSubmiting] = useState(false);
|
|
@@ -3732,6 +3758,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
3732
3758
|
setError,
|
|
3733
3759
|
getUpdatedData,
|
|
3734
3760
|
customErrorRenderer,
|
|
3761
|
+
displayConfig,
|
|
3735
3762
|
}, children: jsx(FormProvider, { ...form, children: children }) }));
|
|
3736
3763
|
};
|
|
3737
3764
|
|
|
@@ -4067,7 +4094,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4067
4094
|
setOpenSearchResult(true);
|
|
4068
4095
|
}, justifyContent: "start", children: !!watchEnum === false
|
|
4069
4096
|
? ""
|
|
4070
|
-
: translate.t(removeIndex(`${colLabel}.${watchEnum ?? "null"}`)) })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
|
|
4097
|
+
: translate.t(removeIndex(`${colLabel}.${watchEnum ?? "null"}`)) })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { portalled: false, children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
|
|
4071
4098
|
onSearchChange(event);
|
|
4072
4099
|
setOpenSearchResult(true);
|
|
4073
4100
|
}, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), showTotalAndLimit && (jsx(Text, { children: `${translate.t(removeIndex(`${colLabel}.total`))}: ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` })), jsxs(Grid, { overflow: "auto", maxHeight: "20rem", children: [jsx(Flex, { flexFlow: "column wrap", children: dataList
|
|
@@ -4654,7 +4681,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4654
4681
|
setOpenSearchResult(true);
|
|
4655
4682
|
}, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
|
|
4656
4683
|
setOpenSearchResult(true);
|
|
4657
|
-
}, justifyContent: "start", children: queryDefault.isLoading ? jsx(Spinner, { size: "sm" }) : getPickedValue() })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(removeIndex(`${colLabel}.type_to_search`)), onChange: onSearchChange, autoComplete: "off", ref: ref, value: searchText }), jsx(PopoverTitle, {}), openSearchResult && (jsxs(Fragment, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, {}), isError && (jsx(Icon, { color: "red.400", children: jsx(BiError, {}) })), jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxs(Flex, { alignItems: "center", gap: "2", children: [jsx(InfoTip, { children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit} ${translate.t(removeIndex(`${colLabel}.per_page`), "per page")}` }), jsxs(Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxs(Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/ ", count > 0 ? `${page * limit + 1}-${Math.min((page + 1) * limit, count)}` : '0'] })] })] }), jsx(Box, { children: jsxs("select", { value: limit, onChange: handleLimitChange, style: {
|
|
4684
|
+
}, justifyContent: "start", children: queryDefault.isLoading ? jsx(Spinner, { size: "sm" }) : getPickedValue() })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { portalled: false, children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(removeIndex(`${colLabel}.type_to_search`)), onChange: onSearchChange, autoComplete: "off", ref: ref, value: searchText }), jsx(PopoverTitle, {}), openSearchResult && (jsxs(Fragment, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, {}), isError && (jsx(Icon, { color: "red.400", children: jsx(BiError, {}) })), jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxs(Flex, { alignItems: "center", gap: "2", children: [jsx(InfoTip, { children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit} ${translate.t(removeIndex(`${colLabel}.per_page`), "per page")}` }), jsxs(Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxs(Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/ ", count > 0 ? `${page * limit + 1}-${Math.min((page + 1) * limit, count)}` : '0'] })] })] }), jsx(Box, { children: jsxs("select", { value: limit, onChange: handleLimitChange, style: {
|
|
4658
4685
|
padding: "4px 8px",
|
|
4659
4686
|
borderRadius: "4px",
|
|
4660
4687
|
border: "1px solid #ccc",
|
|
@@ -5922,16 +5949,12 @@ const SubmitButton = () => {
|
|
|
5922
5949
|
const methods = useFormContext();
|
|
5923
5950
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5924
5951
|
const onValid = (data) => {
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
// @ts-expect-error TODO: find appropriate type
|
|
5932
|
-
const errors = validationResult.errors;
|
|
5933
|
-
if (errors && errors.length > 0) {
|
|
5934
|
-
setError(errors);
|
|
5952
|
+
const { isValid, errors } = validateData(data, schema);
|
|
5953
|
+
if (!isValid) {
|
|
5954
|
+
setError({
|
|
5955
|
+
type: "validation",
|
|
5956
|
+
errors,
|
|
5957
|
+
});
|
|
5935
5958
|
setIsError(true);
|
|
5936
5959
|
return;
|
|
5937
5960
|
}
|
|
@@ -5946,7 +5969,8 @@ const SubmitButton = () => {
|
|
|
5946
5969
|
};
|
|
5947
5970
|
|
|
5948
5971
|
const FormBody = () => {
|
|
5949
|
-
const { schema, requestUrl, order, ignore, include, onSubmit,
|
|
5972
|
+
const { schema, requestUrl, order, ignore, include, onSubmit, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, displayConfig, } = useSchemaContext();
|
|
5973
|
+
const { showSubmitButton, showResetButton } = displayConfig;
|
|
5950
5974
|
const methods = useFormContext();
|
|
5951
5975
|
const { properties } = schema;
|
|
5952
5976
|
const onBeforeSubmit = () => {
|
|
@@ -5962,24 +5986,11 @@ const FormBody = () => {
|
|
|
5962
5986
|
const onSubmitSuccess = () => {
|
|
5963
5987
|
setIsSuccess(true);
|
|
5964
5988
|
};
|
|
5965
|
-
// Enhanced validation function using AJV with i18n support
|
|
5966
5989
|
const validateFormData = (data) => {
|
|
5967
5990
|
try {
|
|
5968
|
-
const
|
|
5969
|
-
strict: false,
|
|
5970
|
-
allErrors: true,
|
|
5971
|
-
});
|
|
5972
|
-
addFormats(ajv);
|
|
5973
|
-
addErrors(ajv);
|
|
5974
|
-
const validate = ajv.compile(schema);
|
|
5975
|
-
const validationResult = validate(data);
|
|
5976
|
-
const errors = validate.errors;
|
|
5977
|
-
console.log({
|
|
5978
|
-
isValid: validationResult,
|
|
5979
|
-
errors,
|
|
5980
|
-
}, "plkdfs");
|
|
5991
|
+
const { isValid, errors } = validateData(data, schema);
|
|
5981
5992
|
return {
|
|
5982
|
-
isValid
|
|
5993
|
+
isValid,
|
|
5983
5994
|
errors,
|
|
5984
5995
|
};
|
|
5985
5996
|
}
|
|
@@ -6039,10 +6050,7 @@ const FormBody = () => {
|
|
|
6039
6050
|
};
|
|
6040
6051
|
// Custom error renderer for validation errors with i18n support
|
|
6041
6052
|
const renderValidationErrors = (validationErrors) => {
|
|
6042
|
-
return (jsx(
|
|
6043
|
-
base: "red.50",
|
|
6044
|
-
_dark: "red.950",
|
|
6045
|
-
}, p: "4", colorPalette: "red", collapsible: true, defaultValue: [], children: jsxs(AccordionItem, { value: "validation-errors", children: [jsx(AccordionItemTrigger, { children: translate.t("validation_error") }), jsx(AccordionItemContent, { display: "flex", flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxs(AlertRoot, { status: "error", display: "flex", alignItems: "center", children: [jsx(AlertIndicator, {}), jsx(AlertContent, { children: jsx(AlertDescription, { children: err.message }) })] }))) })] }) }));
|
|
6053
|
+
return (jsx(Flex, { flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxs(Alert.Root, { status: "error", display: "flex", alignItems: "center", children: [jsx(Alert.Indicator, {}), jsx(Alert.Content, { children: jsx(Alert.Description, { children: err.message }) })] }, index))) }));
|
|
6046
6054
|
};
|
|
6047
6055
|
const renderColumns = ({ order, keys, ignore, include, }) => {
|
|
6048
6056
|
const included = include.length > 0 ? include : keys;
|
|
@@ -6058,7 +6066,7 @@ const FormBody = () => {
|
|
|
6058
6066
|
include,
|
|
6059
6067
|
});
|
|
6060
6068
|
if (isSuccess) {
|
|
6061
|
-
return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Title, { children: translate.t("submit_success") })] }), jsx(Flex, { justifyContent: "end", children: jsx(Button$1, { onClick: async () => {
|
|
6069
|
+
return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Content, { children: jsx(Alert.Title, { children: translate.t("submit_success") }) })] }), jsx(Flex, { justifyContent: "end", children: jsx(Button$1, { onClick: async () => {
|
|
6062
6070
|
setIsError(false);
|
|
6063
6071
|
setIsSubmiting(false);
|
|
6064
6072
|
setIsSuccess(false);
|
|
@@ -6080,7 +6088,7 @@ const FormBody = () => {
|
|
|
6080
6088
|
}, variant: "subtle", children: translate.t("cancel") }), jsx(Button$1, { onClick: () => {
|
|
6081
6089
|
onFormSubmit(validatedData);
|
|
6082
6090
|
}, children: translate.t("confirm") })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && (jsx(Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsx(Fragment, { children: error?.type === "validation" &&
|
|
6083
|
-
error?.errors ? (renderValidationErrors(error.errors)) : (
|
|
6091
|
+
error?.errors ? (renderValidationErrors(error.errors)) : (jsxs(Alert.Root, { status: "error", children: [jsx(Alert.Indicator, {}), jsxs(Alert.Content, { children: [jsx(Alert.Title, { children: "Error" }), jsx(Alert.Description, { children: jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxs(AccordionItem, { value: "b", children: [jsx(AccordionItemTrigger, { children: `${error}` }), jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) })] })] })) })) }))] }));
|
|
6084
6092
|
}
|
|
6085
6093
|
return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: ordered.map((column) => {
|
|
6086
6094
|
return (jsx(ColumnRenderer
|
|
@@ -6088,10 +6096,10 @@ const FormBody = () => {
|
|
|
6088
6096
|
, {
|
|
6089
6097
|
// @ts-expect-error find suitable types
|
|
6090
6098
|
properties: properties, prefix: ``, column }, `form-input-${column}`));
|
|
6091
|
-
}) }), jsxs(Flex, { justifyContent: "end", gap: "2", children: [jsx(Button$1, { onClick: () => {
|
|
6099
|
+
}) }), jsxs(Flex, { justifyContent: "end", gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
|
|
6092
6100
|
methods.reset();
|
|
6093
|
-
}, variant: "subtle", children: translate.t("reset") }), jsx(SubmitButton, {})] }), isError &&
|
|
6094
|
-
|
|
6101
|
+
}, variant: "subtle", children: translate.t("reset") })), showSubmitButton && jsx(SubmitButton, {})] }), isError && (jsx(Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsx(Fragment, { children: error?.type === "validation" &&
|
|
6102
|
+
error?.errors ? (renderValidationErrors(error.errors)) : (jsxs(Alert.Root, { status: "error", children: [jsx(Alert.Indicator, {}), jsxs(Alert.Content, { children: [jsx(Alert.Title, { children: "Error" }), jsx(Alert.Description, { children: jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxs(AccordionItem, { value: "b", children: [jsx(AccordionItemTrigger, { children: `${error}` }), jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) })] })] })) })) }))] }));
|
|
6095
6103
|
};
|
|
6096
6104
|
|
|
6097
6105
|
const FormTitle = () => {
|
|
@@ -6099,7 +6107,8 @@ const FormTitle = () => {
|
|
|
6099
6107
|
return jsx(Heading, { children: translate.t("title") });
|
|
6100
6108
|
};
|
|
6101
6109
|
|
|
6102
|
-
const DefaultForm = ({ formConfig,
|
|
6110
|
+
const DefaultForm = ({ formConfig, }) => {
|
|
6111
|
+
const { showTitle } = formConfig.displayConfig ?? {};
|
|
6103
6112
|
return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
|
|
6104
6113
|
};
|
|
6105
6114
|
|
|
@@ -5,7 +5,7 @@ import { DensityState } from "./controls/DensityFeature";
|
|
|
5
5
|
import { DataTableLabel } from "./context/DataTableContext";
|
|
6
6
|
import { DataResponse } from "./useDataTableServer";
|
|
7
7
|
import { UseTranslationResponse } from "react-i18next";
|
|
8
|
-
export interface DataTableServerProps<TData
|
|
8
|
+
export interface DataTableServerProps<TData = unknown> {
|
|
9
9
|
children: ReactNode | ReactNode[];
|
|
10
10
|
/**
|
|
11
11
|
* Column definitions for the table.
|
|
@@ -34,10 +34,10 @@ export interface DataTableServerProps<TData extends DataResponse = DataResponse<
|
|
|
34
34
|
setColumnOrder: OnChangeFn<ColumnOrderState>;
|
|
35
35
|
setDensity: OnChangeFn<DensityState>;
|
|
36
36
|
setColumnVisibility: OnChangeFn<VisibilityState>;
|
|
37
|
-
query: UseQueryResult<TData
|
|
37
|
+
query: UseQueryResult<DataResponse<TData>>;
|
|
38
38
|
url: string;
|
|
39
39
|
translate: UseTranslationResponse<any, any>;
|
|
40
|
-
tableLabel
|
|
40
|
+
tableLabel?: DataTableLabel;
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* DataTableServer will create a context to hold all values to
|
|
@@ -50,4 +50,4 @@ export interface DataTableServerProps<TData extends DataResponse = DataResponse<
|
|
|
50
50
|
*
|
|
51
51
|
* @link https://tanstack.com/table/latest/docs/guide/column-defs
|
|
52
52
|
*/
|
|
53
|
-
export declare function DataTableServer<TData
|
|
53
|
+
export declare function DataTableServer<TData = unknown>({ columns, enableRowSelection, enableMultiRowSelection, enableSubRowSelection, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel, }: DataTableServerProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -31,5 +31,10 @@ export interface SchemaFormContext<TData extends FieldValues> {
|
|
|
31
31
|
getUpdatedData: () => TData | Promise<TData>;
|
|
32
32
|
customErrorRenderer?: (error: unknown) => ReactNode;
|
|
33
33
|
timezone?: string;
|
|
34
|
+
displayConfig: {
|
|
35
|
+
showSubmitButton?: boolean;
|
|
36
|
+
showResetButton?: boolean;
|
|
37
|
+
showTitle?: boolean;
|
|
38
|
+
};
|
|
34
39
|
}
|
|
35
40
|
export declare const SchemaFormContext: import("react").Context<SchemaFormContext<unknown>>;
|
|
@@ -4,4 +4,4 @@ export interface DefaultFormProps<TData extends FieldValues> {
|
|
|
4
4
|
formConfig: Omit<FormRootProps<TData>, "children">;
|
|
5
5
|
showTitle?: boolean;
|
|
6
6
|
}
|
|
7
|
-
export declare const DefaultForm: <TData extends FieldValues>({ formConfig,
|
|
7
|
+
export declare const DefaultForm: <TData extends FieldValues>({ formConfig, }: DefaultFormProps<TData>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -22,6 +22,11 @@ export interface FormRootProps<TData extends FieldValues> {
|
|
|
22
22
|
requestOptions?: AxiosRequestConfig;
|
|
23
23
|
getUpdatedData?: () => TData | Promise<TData> | void;
|
|
24
24
|
customErrorRenderer?: (error: unknown) => ReactNode;
|
|
25
|
+
displayConfig?: {
|
|
26
|
+
showSubmitButton?: boolean;
|
|
27
|
+
showResetButton?: boolean;
|
|
28
|
+
showTitle?: boolean;
|
|
29
|
+
};
|
|
25
30
|
}
|
|
26
31
|
export interface CustomJSONSchema7Definition extends JSONSchema7 {
|
|
27
32
|
variant: string;
|
|
@@ -38,4 +43,4 @@ export declare const idPickerSanityCheck: (column: string, foreign_key?: {
|
|
|
38
43
|
column?: string | undefined;
|
|
39
44
|
display_column?: string | undefined;
|
|
40
45
|
} | undefined) => void;
|
|
41
|
-
export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, displayConfig, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ErrorObject, ValidateFunction } from "ajv";
|
|
2
|
+
import { JSONSchema7 } from "json-schema";
|
|
3
|
+
type ValidateDataResult = {
|
|
4
|
+
isValid: boolean;
|
|
5
|
+
validate: ValidateFunction;
|
|
6
|
+
errors: ErrorObject<string, Record<string, any>, unknown>[] | null | undefined;
|
|
7
|
+
};
|
|
8
|
+
export declare const validateData: (data: unknown, schema: JSONSchema7) => ValidateDataResult;
|
|
9
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsol-oss/react-datatable5",
|
|
3
|
-
"version": "12.0.0-beta.
|
|
3
|
+
"version": "12.0.0-beta.65",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
"@typescript-eslint/parser": "^7.2.0",
|
|
76
76
|
"@vitejs/plugin-react": "^4.2.1",
|
|
77
77
|
"ajv": "^8.12.0",
|
|
78
|
-
"ajv-formats": "^3.0.1",
|
|
79
78
|
"ajv-errors": "^3.0.0",
|
|
79
|
+
"ajv-formats": "^3.0.1",
|
|
80
80
|
"eslint": "^8.57.0",
|
|
81
81
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
82
82
|
"eslint-plugin-react-refresh": "^0.4.6",
|