@bsol-oss/react-datatable5 12.0.0-beta.71 → 12.0.0-beta.72
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 +254 -14
- package/dist/index.js +262 -48
- package/dist/index.mjs +259 -49
- package/dist/types/components/Form/SchemaFormContext.d.ts +9 -5
- package/dist/types/components/Form/components/core/FormBody.d.ts +2 -1
- package/dist/types/components/Form/components/core/FormRoot.d.ts +11 -8
- package/dist/types/components/Form/components/fields/IdPicker.d.ts +1 -1
- package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +20 -4
- package/dist/types/components/Form/useForm.d.ts +3 -2
- package/dist/types/components/Form/utils/buildErrorMessages.d.ts +219 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +10 -2
package/dist/index.mjs
CHANGED
|
@@ -3657,8 +3657,8 @@ const AccordionItem = Accordion.Item;
|
|
|
3657
3657
|
//@ts-expect-error TODO: find appropriate type
|
|
3658
3658
|
const SchemaFormContext = createContext({
|
|
3659
3659
|
schema: {},
|
|
3660
|
-
serverUrl:
|
|
3661
|
-
requestUrl:
|
|
3660
|
+
serverUrl: '',
|
|
3661
|
+
requestUrl: '',
|
|
3662
3662
|
order: [],
|
|
3663
3663
|
ignore: [],
|
|
3664
3664
|
include: [],
|
|
@@ -3714,11 +3714,11 @@ const idPickerSanityCheck = (column, foreign_key) => {
|
|
|
3714
3714
|
throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
|
|
3715
3715
|
}
|
|
3716
3716
|
};
|
|
3717
|
-
const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, displayConfig = {
|
|
3717
|
+
const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
|
|
3718
3718
|
showSubmitButton: true,
|
|
3719
3719
|
showResetButton: true,
|
|
3720
3720
|
showTitle: true,
|
|
3721
|
-
}, }) => {
|
|
3721
|
+
}, dateTimePickerLabels, idPickerLabels, }) => {
|
|
3722
3722
|
const [isSuccess, setIsSuccess] = useState(false);
|
|
3723
3723
|
const [isError, setIsError] = useState(false);
|
|
3724
3724
|
const [isSubmiting, setIsSubmiting] = useState(false);
|
|
@@ -3752,7 +3752,10 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
3752
3752
|
setError,
|
|
3753
3753
|
getUpdatedData,
|
|
3754
3754
|
customErrorRenderer,
|
|
3755
|
+
customSuccessRenderer,
|
|
3755
3756
|
displayConfig,
|
|
3757
|
+
dateTimePickerLabels,
|
|
3758
|
+
idPickerLabels,
|
|
3756
3759
|
}, children: jsx(FormProvider, { ...form, children: children }) }));
|
|
3757
3760
|
};
|
|
3758
3761
|
|
|
@@ -4595,12 +4598,12 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
|
|
|
4595
4598
|
|
|
4596
4599
|
const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
4597
4600
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4598
|
-
const { serverUrl, idMap, setIdMap, schema: parentSchema, } = useSchemaContext();
|
|
4601
|
+
const { serverUrl, idMap, setIdMap, schema: parentSchema, idPickerLabels, } = useSchemaContext();
|
|
4599
4602
|
const formI18n = useFormI18n(column, prefix);
|
|
4600
|
-
const { required, gridColumn =
|
|
4603
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
|
|
4601
4604
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4602
4605
|
const { table, column: column_ref, display_column, customQueryFn, } = foreign_key;
|
|
4603
|
-
const [searchText, setSearchText] = useState(
|
|
4606
|
+
const [searchText, setSearchText] = useState('');
|
|
4604
4607
|
const [limit, setLimit] = useState(10);
|
|
4605
4608
|
const [openSearchResult, setOpenSearchResult] = useState();
|
|
4606
4609
|
const [page, setPage] = useState(0);
|
|
@@ -4614,7 +4617,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4614
4617
|
queryFn: async () => {
|
|
4615
4618
|
if (customQueryFn) {
|
|
4616
4619
|
const { data, idMap } = await customQueryFn({
|
|
4617
|
-
searching: searchText ??
|
|
4620
|
+
searching: searchText ?? '',
|
|
4618
4621
|
limit: limit,
|
|
4619
4622
|
offset: page * limit,
|
|
4620
4623
|
});
|
|
@@ -4625,7 +4628,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4625
4628
|
}
|
|
4626
4629
|
const data = await getTableData({
|
|
4627
4630
|
serverUrl,
|
|
4628
|
-
searching: searchText ??
|
|
4631
|
+
searching: searchText ?? '',
|
|
4629
4632
|
in_table: table,
|
|
4630
4633
|
limit: limit,
|
|
4631
4634
|
offset: page * limit,
|
|
@@ -4655,7 +4658,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4655
4658
|
queryFn: async () => {
|
|
4656
4659
|
if (customQueryFn) {
|
|
4657
4660
|
const { data, idMap } = await customQueryFn({
|
|
4658
|
-
searching: watchIds.join(
|
|
4661
|
+
searching: watchIds.join(','),
|
|
4659
4662
|
limit: isMultiple ? watchIds.length : 1,
|
|
4660
4663
|
offset: 0,
|
|
4661
4664
|
});
|
|
@@ -4667,7 +4670,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4667
4670
|
if (!watchId && (!watchIds || watchIds.length === 0)) {
|
|
4668
4671
|
return { data: [] };
|
|
4669
4672
|
}
|
|
4670
|
-
const searchValue = isMultiple ? watchIds.join(
|
|
4673
|
+
const searchValue = isMultiple ? watchIds.join(',') : watchId;
|
|
4671
4674
|
const data = await getTableData({
|
|
4672
4675
|
serverUrl,
|
|
4673
4676
|
searching: searchValue,
|
|
@@ -4704,7 +4707,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4704
4707
|
useEffect(() => {
|
|
4705
4708
|
if (openSearchResult) {
|
|
4706
4709
|
// Reset search text when opening the popover
|
|
4707
|
-
setSearchText(
|
|
4710
|
+
setSearchText('');
|
|
4708
4711
|
// Reset page to first page
|
|
4709
4712
|
setPage(0);
|
|
4710
4713
|
// Fetch initial data
|
|
@@ -4730,44 +4733,44 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4730
4733
|
const count = data?.count ?? 0;
|
|
4731
4734
|
const getPickedValue = () => {
|
|
4732
4735
|
if (Object.keys(idMap).length <= 0) {
|
|
4733
|
-
return
|
|
4736
|
+
return '';
|
|
4734
4737
|
}
|
|
4735
4738
|
const record = idMap[watchId];
|
|
4736
4739
|
if (record === undefined) {
|
|
4737
|
-
return
|
|
4740
|
+
return '';
|
|
4738
4741
|
}
|
|
4739
4742
|
if (!!renderDisplay === true) {
|
|
4740
4743
|
return renderDisplay(record);
|
|
4741
4744
|
}
|
|
4742
4745
|
return record[display_column];
|
|
4743
4746
|
};
|
|
4744
|
-
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems:
|
|
4745
|
-
gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow:
|
|
4747
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4748
|
+
gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow: 'wrap', gap: 1, children: [watchIds.map((id) => {
|
|
4746
4749
|
const item = idMap[id];
|
|
4747
4750
|
if (item === undefined) {
|
|
4748
|
-
return (jsx(Text, { children: formI18n.t('undefined') }, id));
|
|
4751
|
+
return (jsx(Text, { children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
|
|
4749
4752
|
}
|
|
4750
4753
|
return (jsx(Tag, { closable: true, onClick: () => {
|
|
4751
4754
|
setValue(colLabel, watchIds.filter((itemId) => itemId !== item[column_ref]));
|
|
4752
4755
|
}, children: !!renderDisplay === true
|
|
4753
4756
|
? renderDisplay(item)
|
|
4754
4757
|
: item[display_column] }, id));
|
|
4755
|
-
}), jsx(Tag, { cursor:
|
|
4758
|
+
}), jsx(Tag, { cursor: 'pointer', onClick: () => {
|
|
4756
4759
|
setOpenSearchResult(true);
|
|
4757
|
-
}, children: formI18n.t('add_more') })] })), !isMultiple && (jsx(Button, { variant:
|
|
4760
|
+
}, children: idPickerLabels?.addMore ?? formI18n.t('add_more') })] })), !isMultiple && (jsx(Button, { variant: 'outline', onClick: () => {
|
|
4758
4761
|
setOpenSearchResult(true);
|
|
4759
|
-
}, justifyContent:
|
|
4762
|
+
}, 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: idPickerLabels?.typeToSearch ?? formI18n.t('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: `${idPickerLabels?.total ?? formI18n.t('total')} ${count}, ${idPickerLabels?.showing ?? formI18n.t('showing')} ${limit} ${idPickerLabels?.perPage ?? formI18n.t('per_page', { defaultValue: 'per page' })}` }), jsxs(Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxs(Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/", ' ', count > 0
|
|
4760
4763
|
? `${page * limit + 1}-${Math.min((page + 1) * limit, count)}`
|
|
4761
|
-
:
|
|
4762
|
-
padding:
|
|
4763
|
-
borderRadius:
|
|
4764
|
-
border:
|
|
4765
|
-
fontSize:
|
|
4766
|
-
}, children: [jsx("option", { value: "5", children: "5" }), jsx("option", { value: "10", children: "10" }), jsx("option", { value: "20", children: "20" }), jsx("option", { value: "30", children: "30" })] }) })] }), jsx(Grid, { overflowY:
|
|
4764
|
+
: '0'] })] })] }), jsx(Box, { children: jsxs("select", { value: limit, onChange: handleLimitChange, style: {
|
|
4765
|
+
padding: '4px 8px',
|
|
4766
|
+
borderRadius: '4px',
|
|
4767
|
+
border: '1px solid #ccc',
|
|
4768
|
+
fontSize: '14px',
|
|
4769
|
+
}, children: [jsx("option", { value: "5", children: "5" }), jsx("option", { value: "10", children: "10" }), jsx("option", { value: "20", children: "20" }), jsx("option", { value: "30", children: "30" })] }) })] }), jsx(Grid, { overflowY: 'auto', children: dataList.length > 0 ? (jsx(Flex, { flexFlow: 'column wrap', gap: 1, children: dataList.map((item) => {
|
|
4767
4770
|
const selected = isMultiple
|
|
4768
4771
|
? watchIds.some((id) => item[column_ref] === id)
|
|
4769
4772
|
: watchId === item[column_ref];
|
|
4770
|
-
return (jsx(Box, { cursor:
|
|
4773
|
+
return (jsx(Box, { cursor: 'pointer', onClick: () => {
|
|
4771
4774
|
if (!isMultiple) {
|
|
4772
4775
|
setOpenSearchResult(false);
|
|
4773
4776
|
setValue(colLabel, item[column_ref]);
|
|
@@ -4783,15 +4786,17 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4783
4786
|
setValue(colLabel, [...newSet]);
|
|
4784
4787
|
}, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
|
|
4785
4788
|
? {
|
|
4786
|
-
color:
|
|
4787
|
-
fontWeight:
|
|
4789
|
+
color: 'colorPalette.400/50',
|
|
4790
|
+
fontWeight: 'bold',
|
|
4788
4791
|
}
|
|
4789
4792
|
: {}), children: !!renderDisplay === true
|
|
4790
4793
|
? renderDisplay(item)
|
|
4791
4794
|
: item[display_column] }, item[column_ref]));
|
|
4792
4795
|
}) })) : (jsx(Text, { children: searchText
|
|
4793
|
-
?
|
|
4794
|
-
|
|
4796
|
+
? idPickerLabels?.emptySearchResult ??
|
|
4797
|
+
formI18n.t('empty_search_result')
|
|
4798
|
+
: idPickerLabels?.initialResults ??
|
|
4799
|
+
formI18n.t('initial_results') })) }), jsx(PaginationRoot, { justifySelf: 'center', count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxs(HStack, { gap: "4", children: [jsx(PaginationPrevTrigger, {}), count > 0 && jsx(PaginationPageText, {}), jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
4795
4800
|
};
|
|
4796
4801
|
|
|
4797
4802
|
const NumberInputRoot = React.forwardRef(function NumberInput$1(props, ref) {
|
|
@@ -5478,7 +5483,7 @@ dayjs.extend(utc);
|
|
|
5478
5483
|
dayjs.extend(timezone);
|
|
5479
5484
|
const DateTimePicker = ({ column, schema, prefix, }) => {
|
|
5480
5485
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
5481
|
-
const { timezone } = useSchemaContext();
|
|
5486
|
+
const { timezone, dateTimePickerLabels } = useSchemaContext();
|
|
5482
5487
|
const formI18n = useFormI18n(column, prefix);
|
|
5483
5488
|
const { required, gridColumn = "span 12", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss",
|
|
5484
5489
|
// with timezone
|
|
@@ -5519,7 +5524,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
|
|
|
5519
5524
|
}, justifyContent: "start", children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsx(PopoverContent, { minW: "450px", children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
|
|
5520
5525
|
setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
|
|
5521
5526
|
}, timezone: timezone, labels: {
|
|
5522
|
-
monthNamesShort: [
|
|
5527
|
+
monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
|
|
5523
5528
|
formI18n.translate.t(`common.month_1`, { defaultValue: "January" }),
|
|
5524
5529
|
formI18n.translate.t(`common.month_2`, { defaultValue: "February" }),
|
|
5525
5530
|
formI18n.translate.t(`common.month_3`, { defaultValue: "March" }),
|
|
@@ -5533,7 +5538,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
|
|
|
5533
5538
|
formI18n.translate.t(`common.month_11`, { defaultValue: "November" }),
|
|
5534
5539
|
formI18n.translate.t(`common.month_12`, { defaultValue: "December" }),
|
|
5535
5540
|
],
|
|
5536
|
-
weekdayNamesShort: [
|
|
5541
|
+
weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
|
|
5537
5542
|
formI18n.translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
|
|
5538
5543
|
formI18n.translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
|
|
5539
5544
|
formI18n.translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
|
|
@@ -5544,10 +5549,10 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
|
|
|
5544
5549
|
formI18n.translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
|
|
5545
5550
|
formI18n.translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
|
|
5546
5551
|
],
|
|
5547
|
-
backButtonLabel: formI18n.translate.t(`common.back_button`, {
|
|
5552
|
+
backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? formI18n.translate.t(`common.back_button`, {
|
|
5548
5553
|
defaultValue: "Back",
|
|
5549
5554
|
}),
|
|
5550
|
-
forwardButtonLabel: formI18n.translate.t(`common.forward_button`, {
|
|
5555
|
+
forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? formI18n.translate.t(`common.forward_button`, {
|
|
5551
5556
|
defaultValue: "Forward",
|
|
5552
5557
|
}),
|
|
5553
5558
|
} })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: formI18n.required() }))] }));
|
|
@@ -6073,7 +6078,7 @@ const SubmitButton = () => {
|
|
|
6073
6078
|
};
|
|
6074
6079
|
|
|
6075
6080
|
const FormBody = () => {
|
|
6076
|
-
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();
|
|
6081
|
+
const { schema, requestUrl, order, ignore, include, onSubmit, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, } = useSchemaContext();
|
|
6077
6082
|
const { showSubmitButton, showResetButton } = displayConfig;
|
|
6078
6083
|
const methods = useFormContext();
|
|
6079
6084
|
const { properties } = schema;
|
|
@@ -6170,15 +6175,19 @@ const FormBody = () => {
|
|
|
6170
6175
|
include,
|
|
6171
6176
|
});
|
|
6172
6177
|
if (isSuccess) {
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6178
|
+
const resetHandler = async () => {
|
|
6179
|
+
setIsError(false);
|
|
6180
|
+
setIsSubmiting(false);
|
|
6181
|
+
setIsSuccess(false);
|
|
6182
|
+
setIsConfirming(false);
|
|
6183
|
+
setValidatedData(undefined);
|
|
6184
|
+
const data = await getUpdatedData();
|
|
6185
|
+
methods.reset(data);
|
|
6186
|
+
};
|
|
6187
|
+
if (customSuccessRenderer) {
|
|
6188
|
+
return customSuccessRenderer(resetHandler);
|
|
6189
|
+
}
|
|
6190
|
+
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: resetHandler, formNoValidate: true, children: translate.t("submit_again") }) })] }));
|
|
6182
6191
|
}
|
|
6183
6192
|
if (isConfirming) {
|
|
6184
6193
|
return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsx(Grid, { gap: 4, gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: "repeat(12, max-content)", autoFlow: "row", children: ordered.map((column) => {
|
|
@@ -6216,12 +6225,12 @@ const DefaultForm = ({ formConfig, }) => {
|
|
|
6216
6225
|
return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
|
|
6217
6226
|
};
|
|
6218
6227
|
|
|
6219
|
-
const useForm = ({ preLoadedValues, keyPrefix }) => {
|
|
6228
|
+
const useForm = ({ preLoadedValues, keyPrefix, namespace }) => {
|
|
6220
6229
|
const form = useForm$1({
|
|
6221
6230
|
values: preLoadedValues,
|
|
6222
6231
|
});
|
|
6223
6232
|
const [idMap, setIdMap] = useState({});
|
|
6224
|
-
const translate = useTranslation("", { keyPrefix });
|
|
6233
|
+
const translate = useTranslation(namespace || "", { keyPrefix });
|
|
6225
6234
|
return {
|
|
6226
6235
|
form,
|
|
6227
6236
|
idMap,
|
|
@@ -6230,6 +6239,207 @@ const useForm = ({ preLoadedValues, keyPrefix }) => {
|
|
|
6230
6239
|
};
|
|
6231
6240
|
};
|
|
6232
6241
|
|
|
6242
|
+
/**
|
|
6243
|
+
* Type definitions for error message configuration
|
|
6244
|
+
*/
|
|
6245
|
+
/**
|
|
6246
|
+
* Schema-level error message builder
|
|
6247
|
+
*
|
|
6248
|
+
* Builds a complete errorMessage object compatible with ajv-errors plugin.
|
|
6249
|
+
* Supports both i18n translation keys and plain string messages.
|
|
6250
|
+
*
|
|
6251
|
+
* @param config - Error message configuration
|
|
6252
|
+
* @returns Complete errorMessage object for JSON Schema
|
|
6253
|
+
*
|
|
6254
|
+
* @example
|
|
6255
|
+
* ```typescript
|
|
6256
|
+
* // Simple required field errors
|
|
6257
|
+
* const errorMessage = buildErrorMessages({
|
|
6258
|
+
* required: {
|
|
6259
|
+
* username: "Username is required",
|
|
6260
|
+
* email: "user.email.field_required" // i18n key
|
|
6261
|
+
* }
|
|
6262
|
+
* });
|
|
6263
|
+
*
|
|
6264
|
+
* // With validation rules
|
|
6265
|
+
* const errorMessage = buildErrorMessages({
|
|
6266
|
+
* required: {
|
|
6267
|
+
* password: "Password is required"
|
|
6268
|
+
* },
|
|
6269
|
+
* properties: {
|
|
6270
|
+
* password: {
|
|
6271
|
+
* minLength: "Password must be at least 8 characters",
|
|
6272
|
+
* pattern: "Password must contain letters and numbers"
|
|
6273
|
+
* },
|
|
6274
|
+
* age: {
|
|
6275
|
+
* minimum: "Must be 18 or older",
|
|
6276
|
+
* maximum: "Must be under 120"
|
|
6277
|
+
* }
|
|
6278
|
+
* }
|
|
6279
|
+
* });
|
|
6280
|
+
*
|
|
6281
|
+
* // With global fallbacks
|
|
6282
|
+
* const errorMessage = buildErrorMessages({
|
|
6283
|
+
* required: {
|
|
6284
|
+
* email: "Email is required"
|
|
6285
|
+
* },
|
|
6286
|
+
* minLength: "This field is too short", // applies to all fields
|
|
6287
|
+
* minimum: "Value is too small"
|
|
6288
|
+
* });
|
|
6289
|
+
* ```
|
|
6290
|
+
*/
|
|
6291
|
+
const buildErrorMessages = (config) => {
|
|
6292
|
+
const result = {};
|
|
6293
|
+
// Add required field errors
|
|
6294
|
+
if (config.required && Object.keys(config.required).length > 0) {
|
|
6295
|
+
result.required = config.required;
|
|
6296
|
+
}
|
|
6297
|
+
// Add field-specific validation errors
|
|
6298
|
+
if (config.properties && Object.keys(config.properties).length > 0) {
|
|
6299
|
+
result.properties = config.properties;
|
|
6300
|
+
}
|
|
6301
|
+
// Add global fallback error messages
|
|
6302
|
+
const globalKeys = [
|
|
6303
|
+
"minLength",
|
|
6304
|
+
"maxLength",
|
|
6305
|
+
"pattern",
|
|
6306
|
+
"minimum",
|
|
6307
|
+
"maximum",
|
|
6308
|
+
"multipleOf",
|
|
6309
|
+
"format",
|
|
6310
|
+
"type",
|
|
6311
|
+
"enum",
|
|
6312
|
+
];
|
|
6313
|
+
globalKeys.forEach((key) => {
|
|
6314
|
+
if (config[key]) {
|
|
6315
|
+
result[key] = config[key];
|
|
6316
|
+
}
|
|
6317
|
+
});
|
|
6318
|
+
return result;
|
|
6319
|
+
};
|
|
6320
|
+
/**
|
|
6321
|
+
* Helper function to build required field errors
|
|
6322
|
+
*
|
|
6323
|
+
* Simplifies creating required field error messages, especially useful
|
|
6324
|
+
* for generating i18n translation keys following a pattern.
|
|
6325
|
+
*
|
|
6326
|
+
* @param fields - Array of required field names
|
|
6327
|
+
* @param messageOrGenerator - Either a string template or function to generate messages
|
|
6328
|
+
* @returns Required field error configuration
|
|
6329
|
+
*
|
|
6330
|
+
* @example
|
|
6331
|
+
* ```typescript
|
|
6332
|
+
* // Plain string messages
|
|
6333
|
+
* const required = buildRequiredErrors(
|
|
6334
|
+
* ["username", "email", "password"],
|
|
6335
|
+
* (field) => `${field} is required`
|
|
6336
|
+
* );
|
|
6337
|
+
* // Result: { username: "username is required", email: "email is required", ... }
|
|
6338
|
+
*
|
|
6339
|
+
* // i18n translation keys
|
|
6340
|
+
* const required = buildRequiredErrors(
|
|
6341
|
+
* ["username", "email"],
|
|
6342
|
+
* (field) => `user.${field}.field_required`
|
|
6343
|
+
* );
|
|
6344
|
+
* // Result: { username: "user.username.field_required", email: "user.email.field_required" }
|
|
6345
|
+
*
|
|
6346
|
+
* // Same message for all fields
|
|
6347
|
+
* const required = buildRequiredErrors(
|
|
6348
|
+
* ["username", "email"],
|
|
6349
|
+
* "This field is required"
|
|
6350
|
+
* );
|
|
6351
|
+
* // Result: { username: "This field is required", email: "This field is required" }
|
|
6352
|
+
*
|
|
6353
|
+
* // With keyPrefix for i18n
|
|
6354
|
+
* const required = buildRequiredErrors(
|
|
6355
|
+
* ["username", "email"],
|
|
6356
|
+
* (field) => `${field}.field_required`,
|
|
6357
|
+
* "user"
|
|
6358
|
+
* );
|
|
6359
|
+
* // Result: { username: "user.username.field_required", email: "user.email.field_required" }
|
|
6360
|
+
* ```
|
|
6361
|
+
*/
|
|
6362
|
+
const buildRequiredErrors = (fields, messageOrGenerator, keyPrefix = "") => {
|
|
6363
|
+
const result = {};
|
|
6364
|
+
fields.forEach((field) => {
|
|
6365
|
+
if (typeof messageOrGenerator === "function") {
|
|
6366
|
+
const message = messageOrGenerator(field);
|
|
6367
|
+
result[field] = keyPrefix ? `${keyPrefix}.${message}` : message;
|
|
6368
|
+
}
|
|
6369
|
+
else {
|
|
6370
|
+
result[field] = messageOrGenerator;
|
|
6371
|
+
}
|
|
6372
|
+
});
|
|
6373
|
+
return result;
|
|
6374
|
+
};
|
|
6375
|
+
/**
|
|
6376
|
+
* Helper function to build field-specific validation errors
|
|
6377
|
+
*
|
|
6378
|
+
* Creates property-specific error messages for multiple fields at once.
|
|
6379
|
+
*
|
|
6380
|
+
* @param config - Maps field names to their validation error configurations
|
|
6381
|
+
* @returns Properties error configuration
|
|
6382
|
+
*
|
|
6383
|
+
* @example
|
|
6384
|
+
* ```typescript
|
|
6385
|
+
* const properties = buildFieldErrors({
|
|
6386
|
+
* username: {
|
|
6387
|
+
* minLength: "Username must be at least 3 characters",
|
|
6388
|
+
* pattern: "Username can only contain letters and numbers"
|
|
6389
|
+
* },
|
|
6390
|
+
* age: {
|
|
6391
|
+
* minimum: "Must be 18 or older",
|
|
6392
|
+
* maximum: "Must be under 120"
|
|
6393
|
+
* },
|
|
6394
|
+
* email: {
|
|
6395
|
+
* format: "Please enter a valid email address"
|
|
6396
|
+
* }
|
|
6397
|
+
* });
|
|
6398
|
+
* ```
|
|
6399
|
+
*/
|
|
6400
|
+
const buildFieldErrors = (config) => {
|
|
6401
|
+
return config;
|
|
6402
|
+
};
|
|
6403
|
+
/**
|
|
6404
|
+
* Helper function to create a complete error message configuration in one call
|
|
6405
|
+
*
|
|
6406
|
+
* Convenient wrapper that combines required and validation errors.
|
|
6407
|
+
*
|
|
6408
|
+
* @param required - Required field error messages
|
|
6409
|
+
* @param properties - Field-specific validation error messages
|
|
6410
|
+
* @param globalFallbacks - Global fallback error messages
|
|
6411
|
+
* @returns Complete error message configuration
|
|
6412
|
+
*
|
|
6413
|
+
* @example
|
|
6414
|
+
* ```typescript
|
|
6415
|
+
* const errorMessage = createErrorMessage(
|
|
6416
|
+
* {
|
|
6417
|
+
* username: "Username is required",
|
|
6418
|
+
* email: "Email is required"
|
|
6419
|
+
* },
|
|
6420
|
+
* {
|
|
6421
|
+
* username: {
|
|
6422
|
+
* minLength: "Username must be at least 3 characters"
|
|
6423
|
+
* },
|
|
6424
|
+
* email: {
|
|
6425
|
+
* format: "Please enter a valid email"
|
|
6426
|
+
* }
|
|
6427
|
+
* },
|
|
6428
|
+
* {
|
|
6429
|
+
* minLength: "This field is too short",
|
|
6430
|
+
* format: "Invalid format"
|
|
6431
|
+
* }
|
|
6432
|
+
* );
|
|
6433
|
+
* ```
|
|
6434
|
+
*/
|
|
6435
|
+
const createErrorMessage = (required, properties, globalFallbacks) => {
|
|
6436
|
+
return buildErrorMessages({
|
|
6437
|
+
required,
|
|
6438
|
+
properties,
|
|
6439
|
+
...globalFallbacks,
|
|
6440
|
+
});
|
|
6441
|
+
};
|
|
6442
|
+
|
|
6233
6443
|
const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) => {
|
|
6234
6444
|
if (!selectable) {
|
|
6235
6445
|
return [...selectedDates];
|
|
@@ -6246,4 +6456,4 @@ const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) =
|
|
|
6246
6456
|
}
|
|
6247
6457
|
};
|
|
6248
6458
|
|
|
6249
|
-
export { CardHeader, DataDisplay, DataTable, DataTableServer, DefaultCardTitle, DefaultForm, DefaultTable, DensityToggleButton, EditSortingButton, EmptyState$1 as EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
|
|
6459
|
+
export { CardHeader, DataDisplay, DataTable, DataTableServer, DefaultCardTitle, DefaultForm, DefaultTable, DensityToggleButton, EditSortingButton, EmptyState$1 as EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, createErrorMessage, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { AxiosRequestConfig } from
|
|
2
|
-
import { JSONSchema7 } from
|
|
3
|
-
import { Dispatch, ReactNode, SetStateAction } from
|
|
4
|
-
import { FieldValues } from
|
|
5
|
-
import { UseTranslationResponse } from
|
|
1
|
+
import { AxiosRequestConfig } from 'axios';
|
|
2
|
+
import { JSONSchema7 } from 'json-schema';
|
|
3
|
+
import { Dispatch, ReactNode, SetStateAction } from 'react';
|
|
4
|
+
import { FieldValues } from 'react-hook-form';
|
|
5
|
+
import { UseTranslationResponse } from 'react-i18next';
|
|
6
|
+
import { DateTimePickerLabels, IdPickerLabels } from './components/types/CustomJSONSchema7';
|
|
6
7
|
export interface SchemaFormContext<TData extends FieldValues> {
|
|
7
8
|
schema: JSONSchema7;
|
|
8
9
|
serverUrl: string;
|
|
@@ -30,11 +31,14 @@ export interface SchemaFormContext<TData extends FieldValues> {
|
|
|
30
31
|
setError: Dispatch<SetStateAction<unknown>>;
|
|
31
32
|
getUpdatedData: () => TData | Promise<TData>;
|
|
32
33
|
customErrorRenderer?: (error: unknown) => ReactNode;
|
|
34
|
+
customSuccessRenderer?: (resetHandler: () => void | Promise<void>) => ReactNode;
|
|
33
35
|
timezone?: string;
|
|
34
36
|
displayConfig: {
|
|
35
37
|
showSubmitButton?: boolean;
|
|
36
38
|
showResetButton?: boolean;
|
|
37
39
|
showTitle?: boolean;
|
|
38
40
|
};
|
|
41
|
+
dateTimePickerLabels?: DateTimePickerLabels;
|
|
42
|
+
idPickerLabels?: IdPickerLabels;
|
|
39
43
|
}
|
|
40
44
|
export declare const SchemaFormContext: import("react").Context<SchemaFormContext<unknown>>;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export declare const FormBody: <TData extends object>() => string | number | bigint | boolean | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ForeignKeyProps } from
|
|
2
|
-
import { AxiosRequestConfig } from
|
|
3
|
-
import { JSONSchema7 } from
|
|
4
|
-
import { Dispatch, ReactNode, SetStateAction } from
|
|
5
|
-
import { FieldValues, SubmitHandler, UseFormReturn } from
|
|
6
|
-
import { UseTranslationResponse } from
|
|
7
|
-
import { CustomJSONSchema7 } from
|
|
1
|
+
import { ForeignKeyProps } from '@/components/Form/components/fields/StringInputField';
|
|
2
|
+
import { AxiosRequestConfig } from 'axios';
|
|
3
|
+
import { JSONSchema7 } from 'json-schema';
|
|
4
|
+
import { Dispatch, ReactNode, SetStateAction } from 'react';
|
|
5
|
+
import { FieldValues, SubmitHandler, UseFormReturn } from 'react-hook-form';
|
|
6
|
+
import { UseTranslationResponse } from 'react-i18next';
|
|
7
|
+
import { CustomJSONSchema7, DateTimePickerLabels, IdPickerLabels } from '../types/CustomJSONSchema7';
|
|
8
8
|
export interface FormRootProps<TData extends FieldValues> {
|
|
9
9
|
schema: CustomJSONSchema7;
|
|
10
10
|
serverUrl: string;
|
|
@@ -22,11 +22,14 @@ export interface FormRootProps<TData extends FieldValues> {
|
|
|
22
22
|
requestOptions?: AxiosRequestConfig;
|
|
23
23
|
getUpdatedData?: () => TData | Promise<TData> | void;
|
|
24
24
|
customErrorRenderer?: (error: unknown) => ReactNode;
|
|
25
|
+
customSuccessRenderer?: (resetHandler: () => void | Promise<void>) => ReactNode;
|
|
25
26
|
displayConfig?: {
|
|
26
27
|
showSubmitButton?: boolean;
|
|
27
28
|
showResetButton?: boolean;
|
|
28
29
|
showTitle?: boolean;
|
|
29
30
|
};
|
|
31
|
+
dateTimePickerLabels?: DateTimePickerLabels;
|
|
32
|
+
idPickerLabels?: IdPickerLabels;
|
|
30
33
|
}
|
|
31
34
|
export interface CustomJSONSchema7Definition extends JSONSchema7 {
|
|
32
35
|
variant: string;
|
|
@@ -43,4 +46,4 @@ export declare const idPickerSanityCheck: (column: string, foreign_key?: {
|
|
|
43
46
|
column?: string | undefined;
|
|
44
47
|
display_column?: string | undefined;
|
|
45
48
|
} | undefined) => void;
|
|
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;
|
|
49
|
+
export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, dateTimePickerLabels, idPickerLabels, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
-
import { JSONSchema7 } from
|
|
2
|
-
import { ReactNode } from
|
|
3
|
-
import { ForeignKeyProps } from
|
|
4
|
-
import { UseFormReturn } from
|
|
1
|
+
import { JSONSchema7 } from 'json-schema';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { ForeignKeyProps } from '../fields/StringInputField';
|
|
4
|
+
import { UseFormReturn } from 'react-hook-form';
|
|
5
|
+
export interface DateTimePickerLabels {
|
|
6
|
+
monthNamesShort?: string[];
|
|
7
|
+
weekdayNamesShort?: string[];
|
|
8
|
+
backButtonLabel?: string;
|
|
9
|
+
forwardButtonLabel?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface IdPickerLabels {
|
|
12
|
+
undefined?: string;
|
|
13
|
+
addMore?: string;
|
|
14
|
+
typeToSearch?: string;
|
|
15
|
+
total?: string;
|
|
16
|
+
showing?: string;
|
|
17
|
+
perPage?: string;
|
|
18
|
+
emptySearchResult?: string;
|
|
19
|
+
initialResults?: string;
|
|
20
|
+
}
|
|
5
21
|
export interface CustomJSONSchema7 extends JSONSchema7 {
|
|
6
22
|
gridColumn?: string;
|
|
7
23
|
gridRow?: string;
|
|
@@ -3,10 +3,11 @@ import { FieldValues } from "react-hook-form";
|
|
|
3
3
|
export interface UseFormProps {
|
|
4
4
|
preLoadedValues?: FieldValues | undefined;
|
|
5
5
|
keyPrefix?: string;
|
|
6
|
+
namespace?: string;
|
|
6
7
|
}
|
|
7
|
-
export declare const useForm: ({ preLoadedValues, keyPrefix }: UseFormProps) => {
|
|
8
|
+
export declare const useForm: ({ preLoadedValues, keyPrefix, namespace }: UseFormProps) => {
|
|
8
9
|
form: import("react-hook-form").UseFormReturn<FieldValues, any, undefined>;
|
|
9
10
|
idMap: Record<string, object>;
|
|
10
11
|
setIdMap: import("react").Dispatch<import("react").SetStateAction<Record<string, object>>>;
|
|
11
|
-
translate: import("react-i18next").UseTranslationResponse<
|
|
12
|
+
translate: import("react-i18next").UseTranslationResponse<string, string>;
|
|
12
13
|
};
|