@bsol-oss/react-datatable5 12.0.0-beta.72 → 12.0.0-beta.74

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.js CHANGED
@@ -3691,16 +3691,14 @@ const SchemaFormContext = React.createContext({
3691
3691
  showResetButton: true,
3692
3692
  showTitle: true,
3693
3693
  },
3694
+ requireConfirmation: false,
3695
+ onFormSubmit: async () => { },
3694
3696
  });
3695
3697
 
3696
3698
  const useSchemaContext = () => {
3697
3699
  return React.useContext(SchemaFormContext);
3698
3700
  };
3699
3701
 
3700
- const clearEmptyString = (object) => {
3701
- return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3702
- };
3703
-
3704
3702
  const validateData = (data, schema) => {
3705
3703
  const ajv = new Ajv({
3706
3704
  strict: false,
@@ -3719,6 +3717,10 @@ const validateData = (data, schema) => {
3719
3717
  };
3720
3718
  };
3721
3719
 
3720
+ const clearEmptyString = (object) => {
3721
+ return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3722
+ };
3723
+
3722
3724
  const idPickerSanityCheck = (column, foreign_key) => {
3723
3725
  if (!!foreign_key == false) {
3724
3726
  throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
@@ -3738,13 +3740,88 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3738
3740
  showSubmitButton: true,
3739
3741
  showResetButton: true,
3740
3742
  showTitle: true,
3741
- }, dateTimePickerLabels, idPickerLabels, }) => {
3743
+ }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, }) => {
3742
3744
  const [isSuccess, setIsSuccess] = React.useState(false);
3743
3745
  const [isError, setIsError] = React.useState(false);
3744
3746
  const [isSubmiting, setIsSubmiting] = React.useState(false);
3745
3747
  const [isConfirming, setIsConfirming] = React.useState(false);
3746
3748
  const [validatedData, setValidatedData] = React.useState();
3747
3749
  const [error, setError] = React.useState();
3750
+ const onBeforeSubmit = () => {
3751
+ setIsSubmiting(true);
3752
+ };
3753
+ const onAfterSubmit = () => {
3754
+ setIsSubmiting(false);
3755
+ };
3756
+ const onSubmitError = (error) => {
3757
+ setIsError(true);
3758
+ setError(error);
3759
+ };
3760
+ const onSubmitSuccess = () => {
3761
+ setIsSuccess(true);
3762
+ };
3763
+ const validateFormData = (data) => {
3764
+ try {
3765
+ const { isValid, errors } = validateData(data, schema);
3766
+ return {
3767
+ isValid,
3768
+ errors,
3769
+ };
3770
+ }
3771
+ catch (error) {
3772
+ return {
3773
+ isValid: false,
3774
+ errors: [
3775
+ {
3776
+ field: 'validation',
3777
+ message: error instanceof Error ? error.message : 'Unknown error',
3778
+ },
3779
+ ],
3780
+ };
3781
+ }
3782
+ };
3783
+ const defaultOnSubmit = async (promise) => {
3784
+ try {
3785
+ onBeforeSubmit();
3786
+ await promise;
3787
+ onSubmitSuccess();
3788
+ }
3789
+ catch (error) {
3790
+ onSubmitError(error);
3791
+ }
3792
+ finally {
3793
+ onAfterSubmit();
3794
+ }
3795
+ };
3796
+ const defaultSubmitPromise = (data) => {
3797
+ const options = {
3798
+ method: 'POST',
3799
+ url: `${requestUrl}`,
3800
+ data: clearEmptyString(data),
3801
+ ...requestOptions,
3802
+ };
3803
+ return axios.request(options);
3804
+ };
3805
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3806
+ const onFormSubmit = async (data) => {
3807
+ // Validate data using AJV before submission
3808
+ const validationResult = validateFormData(data);
3809
+ if (!validationResult.isValid) {
3810
+ // Set validation errors
3811
+ const validationErrorMessage = {
3812
+ type: 'validation',
3813
+ errors: validationResult.errors,
3814
+ message: translate.t('validation_error'),
3815
+ };
3816
+ onSubmitError(validationErrorMessage);
3817
+ return;
3818
+ }
3819
+ if (onSubmit === undefined) {
3820
+ await defaultOnSubmit(defaultSubmitPromise(data));
3821
+ return;
3822
+ }
3823
+ await defaultOnSubmit(onSubmit(data));
3824
+ };
3748
3825
  return (jsxRuntime.jsx(SchemaFormContext.Provider, { value: {
3749
3826
  schema,
3750
3827
  serverUrl,
@@ -3774,8 +3851,11 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3774
3851
  customErrorRenderer,
3775
3852
  customSuccessRenderer,
3776
3853
  displayConfig,
3854
+ requireConfirmation,
3855
+ onFormSubmit,
3777
3856
  dateTimePickerLabels,
3778
3857
  idPickerLabels,
3858
+ enumPickerLabels,
3779
3859
  }, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
3780
3860
  };
3781
3861
 
@@ -4034,14 +4114,16 @@ dayjs.extend(utc);
4034
4114
  dayjs.extend(timezone);
4035
4115
  const DatePicker = ({ column, schema, prefix }) => {
4036
4116
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4037
- const { timezone } = useSchemaContext();
4117
+ const { timezone, dateTimePickerLabels } = useSchemaContext();
4038
4118
  const formI18n = useFormI18n(column, prefix);
4039
- const { required, gridColumn = "span 12", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD", dateFormat = "YYYY-MM-DD", } = schema;
4119
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4040
4120
  const isRequired = required?.some((columnId) => columnId === column);
4041
4121
  const colLabel = formI18n.colLabel;
4042
4122
  const [open, setOpen] = React.useState(false);
4043
4123
  const selectedDate = watch(colLabel);
4044
- const displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
4124
+ const displayDate = dayjs(selectedDate)
4125
+ .tz(timezone)
4126
+ .format(displayDateFormat);
4045
4127
  React.useEffect(() => {
4046
4128
  try {
4047
4129
  if (selectedDate) {
@@ -4065,45 +4147,83 @@ const DatePicker = ({ column, schema, prefix }) => {
4065
4147
  console.error(e);
4066
4148
  }
4067
4149
  }, [selectedDate, dateFormat, colLabel, setValue]);
4068
- return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
4150
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4069
4151
  gridRow, children: [jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4070
4152
  setOpen(true);
4071
- }, justifyContent: "start", children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4153
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4072
4154
  setValue(colLabel, dayjs(date).format(dateFormat));
4073
4155
  setOpen(false);
4074
4156
  }, labels: {
4075
- monthNamesShort: [
4076
- formI18n.translate.t(`common.month_1`, { defaultValue: "January" }),
4077
- formI18n.translate.t(`common.month_2`, { defaultValue: "February" }),
4078
- formI18n.translate.t(`common.month_3`, { defaultValue: "March" }),
4079
- formI18n.translate.t(`common.month_4`, { defaultValue: "April" }),
4080
- formI18n.translate.t(`common.month_5`, { defaultValue: "May" }),
4081
- formI18n.translate.t(`common.month_6`, { defaultValue: "June" }),
4082
- formI18n.translate.t(`common.month_7`, { defaultValue: "July" }),
4083
- formI18n.translate.t(`common.month_8`, { defaultValue: "August" }),
4084
- formI18n.translate.t(`common.month_9`, { defaultValue: "September" }),
4085
- formI18n.translate.t(`common.month_10`, { defaultValue: "October" }),
4086
- formI18n.translate.t(`common.month_11`, { defaultValue: "November" }),
4087
- formI18n.translate.t(`common.month_12`, { defaultValue: "December" }),
4157
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4158
+ formI18n.translate.t(`common.month_1`, {
4159
+ defaultValue: 'January',
4160
+ }),
4161
+ formI18n.translate.t(`common.month_2`, {
4162
+ defaultValue: 'February',
4163
+ }),
4164
+ formI18n.translate.t(`common.month_3`, {
4165
+ defaultValue: 'March',
4166
+ }),
4167
+ formI18n.translate.t(`common.month_4`, {
4168
+ defaultValue: 'April',
4169
+ }),
4170
+ formI18n.translate.t(`common.month_5`, {
4171
+ defaultValue: 'May',
4172
+ }),
4173
+ formI18n.translate.t(`common.month_6`, {
4174
+ defaultValue: 'June',
4175
+ }),
4176
+ formI18n.translate.t(`common.month_7`, {
4177
+ defaultValue: 'July',
4178
+ }),
4179
+ formI18n.translate.t(`common.month_8`, {
4180
+ defaultValue: 'August',
4181
+ }),
4182
+ formI18n.translate.t(`common.month_9`, {
4183
+ defaultValue: 'September',
4184
+ }),
4185
+ formI18n.translate.t(`common.month_10`, {
4186
+ defaultValue: 'October',
4187
+ }),
4188
+ formI18n.translate.t(`common.month_11`, {
4189
+ defaultValue: 'November',
4190
+ }),
4191
+ formI18n.translate.t(`common.month_12`, {
4192
+ defaultValue: 'December',
4193
+ }),
4088
4194
  ],
4089
- weekdayNamesShort: [
4090
- formI18n.translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
4091
- formI18n.translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
4092
- formI18n.translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
4195
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4196
+ formI18n.translate.t(`common.weekday_1`, {
4197
+ defaultValue: 'Sun',
4198
+ }),
4199
+ formI18n.translate.t(`common.weekday_2`, {
4200
+ defaultValue: 'Mon',
4201
+ }),
4202
+ formI18n.translate.t(`common.weekday_3`, {
4203
+ defaultValue: 'Tue',
4204
+ }),
4093
4205
  formI18n.translate.t(`common.weekday_4`, {
4094
- defaultValue: "Wed",
4206
+ defaultValue: 'Wed',
4207
+ }),
4208
+ formI18n.translate.t(`common.weekday_5`, {
4209
+ defaultValue: 'Thu',
4210
+ }),
4211
+ formI18n.translate.t(`common.weekday_6`, {
4212
+ defaultValue: 'Fri',
4213
+ }),
4214
+ formI18n.translate.t(`common.weekday_7`, {
4215
+ defaultValue: 'Sat',
4095
4216
  }),
4096
- formI18n.translate.t(`common.weekday_5`, { defaultValue: "Thu" }),
4097
- formI18n.translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
4098
- formI18n.translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
4099
4217
  ],
4100
- backButtonLabel: formI18n.translate.t(`common.back_button`, {
4101
- defaultValue: "Back",
4102
- }),
4103
- forwardButtonLabel: formI18n.translate.t(`common.forward_button`, {
4104
- defaultValue: "Forward",
4105
- }),
4106
- } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
4218
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4219
+ formI18n.translate.t(`common.back_button`, {
4220
+ defaultValue: 'Back',
4221
+ }),
4222
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4223
+ formI18n.translate.t(`common.forward_button`, {
4224
+ defaultValue: 'Forward',
4225
+ }),
4226
+ } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
4107
4227
  };
4108
4228
 
4109
4229
  function filterArray(array, searchTerm) {
@@ -4118,10 +4238,10 @@ function filterArray(array, searchTerm) {
4118
4238
 
4119
4239
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
4120
4240
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4121
- const { translate } = useSchemaContext();
4241
+ const { translate, enumPickerLabels } = useSchemaContext();
4122
4242
  const { required, variant } = schema;
4123
4243
  const isRequired = required?.some((columnId) => columnId === column);
4124
- const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
4244
+ const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
4125
4245
  const [searchText, setSearchText] = React.useState();
4126
4246
  const [limit, setLimit] = React.useState(10);
4127
4247
  const [openSearchResult, setOpenSearchResult] = React.useState();
@@ -4136,9 +4256,9 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4136
4256
  setSearchText(event.target.value);
4137
4257
  setLimit(10);
4138
4258
  };
4139
- if (variant === "radio") {
4140
- return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4141
- gridRow, children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? "").map((item) => {
4259
+ if (variant === 'radio') {
4260
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4261
+ gridRow, children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
4142
4262
  return (jsxRuntime.jsxs(react.RadioGroup.Item, { onClick: () => {
4143
4263
  if (!isMultiple) {
4144
4264
  setOpenSearchResult(false);
@@ -4152,8 +4272,8 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4152
4272
  : translate.t(removeIndex(`${colLabel}.${item}`)) })] }, `${colLabel}-${item}`));
4153
4273
  }) }) }) }));
4154
4274
  }
4155
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4156
- gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
4275
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4276
+ gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
4157
4277
  const item = enumValue;
4158
4278
  if (!!item === false) {
4159
4279
  return jsxRuntime.jsx(jsxRuntime.Fragment, {});
@@ -4163,18 +4283,20 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4163
4283
  }, children: !!renderDisplay === true
4164
4284
  ? renderDisplay(item)
4165
4285
  : translate.t(removeIndex(`${colLabel}.${item}`)) }, item));
4166
- }), jsxRuntime.jsx(Tag, { size: "lg", cursor: "pointer", onClick: () => {
4286
+ }), jsxRuntime.jsx(Tag, { size: "lg", cursor: 'pointer', onClick: () => {
4167
4287
  setOpenSearchResult(true);
4168
- }, children: translate.t(removeIndex(`${colLabel}.add_more`)) }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
4288
+ }, children: enumPickerLabels?.addMore ??
4289
+ translate.t(removeIndex(`${colLabel}.add_more`)) }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: 'outline', onClick: () => {
4169
4290
  setOpenSearchResult(true);
4170
- }, justifyContent: "start", children: !!watchEnum === false
4171
- ? ""
4172
- : 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) => {
4291
+ }, justifyContent: 'start', children: !!watchEnum === false
4292
+ ? ''
4293
+ : 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: enumPickerLabels?.typeToSearch ??
4294
+ translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
4173
4295
  onSearchChange(event);
4174
4296
  setOpenSearchResult(true);
4175
- }, 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
4297
+ }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), showTotalAndLimit && (jsxRuntime.jsx(react.Text, { children: `${enumPickerLabels?.total ?? translate.t(removeIndex(`${colLabel}.total`))}: ${count}, ${enumPickerLabels?.showing ?? translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` })), jsxRuntime.jsxs(react.Grid, { overflow: 'auto', maxHeight: '20rem', children: [jsxRuntime.jsx(react.Flex, { flexFlow: 'column wrap', children: dataList
4176
4298
  .filter((item) => {
4177
- const searchTerm = (searchText || "").toLowerCase();
4299
+ const searchTerm = (searchText || '').toLowerCase();
4178
4300
  if (!searchTerm)
4179
4301
  return true;
4180
4302
  // Check if the original enum value contains the search text
@@ -4194,7 +4316,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4194
4316
  const selected = isMultiple
4195
4317
  ? watchEnums.some((enumValue) => item === enumValue)
4196
4318
  : watchEnum == item;
4197
- return (jsxRuntime.jsx(react.Box, { cursor: "pointer", onClick: () => {
4319
+ return (jsxRuntime.jsx(react.Box, { cursor: 'pointer', onClick: () => {
4198
4320
  if (!isMultiple) {
4199
4321
  setOpenSearchResult(false);
4200
4322
  setValue(colLabel, item);
@@ -4202,10 +4324,11 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4202
4324
  }
4203
4325
  const newSet = new Set([...(watchEnums ?? []), item]);
4204
4326
  setValue(colLabel, [...newSet]);
4205
- }, ...(selected ? { color: "colorPalette.400/50" } : {}), children: !!renderDisplay === true
4327
+ }, ...(selected ? { color: 'colorPalette.400/50' } : {}), children: !!renderDisplay === true
4206
4328
  ? renderDisplay(item)
4207
4329
  : translate.t(removeIndex(`${colLabel}.${item}`)) }, `${colLabel}-${item}`));
4208
- }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4330
+ }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: enumPickerLabels?.emptySearchResult ??
4331
+ translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4209
4332
  };
4210
4333
 
4211
4334
  function isEnteringWindow(_ref) {
@@ -4830,13 +4953,13 @@ react.NumberInput.Label;
4830
4953
  const NumberInputField = ({ schema, column, prefix, }) => {
4831
4954
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4832
4955
  const { translate } = useSchemaContext();
4833
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4956
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
4834
4957
  const isRequired = required?.some((columnId) => columnId === column);
4835
4958
  const colLabel = `${prefix}${column}`;
4836
4959
  const value = watch(`${colLabel}`);
4837
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(NumberInputRoot, { children: jsxRuntime.jsx(NumberInputField$1, { required: isRequired, value: value, onChange: (event) => {
4838
- setValue(`${colLabel}`, Number(event.target.value));
4839
- } }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4960
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(NumberInputRoot, { value: value, onValueChange: (details) => {
4961
+ setValue(`${colLabel}`, details.value); // Store as string to avoid floating-point precision issues
4962
+ }, min: schema.minimum, max: schema.maximum, step: schema.multipleOf || 0.01, allowOverflow: false, clampValueOnBlur: false, inputMode: "decimal", formatOptions: schema.formatOptions, children: jsxRuntime.jsx(NumberInputField$1, { required: isRequired }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4840
4963
  };
4841
4964
 
4842
4965
  const ObjectInput = ({ schema, column, prefix }) => {
@@ -5778,11 +5901,29 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
5778
5901
  const NumberViewer = ({ schema, column, prefix, }) => {
5779
5902
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
5780
5903
  const { translate } = useSchemaContext();
5781
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5904
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5782
5905
  const isRequired = required?.some((columnId) => columnId === column);
5783
5906
  const colLabel = `${prefix}${column}`;
5784
5907
  const value = watch(colLabel);
5785
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(react.Text, { children: value }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5908
+ // Format the value for display if formatOptions are provided
5909
+ const formatValue = (val) => {
5910
+ if (val === undefined || val === null || val === '')
5911
+ return '';
5912
+ const numValue = typeof val === 'string' ? parseFloat(val) : val;
5913
+ if (isNaN(numValue))
5914
+ return String(val);
5915
+ // Use formatOptions if available, otherwise display as-is
5916
+ if (schema.formatOptions) {
5917
+ try {
5918
+ return new Intl.NumberFormat(undefined, schema.formatOptions).format(numValue);
5919
+ }
5920
+ catch {
5921
+ return String(val);
5922
+ }
5923
+ }
5924
+ return String(val);
5925
+ };
5926
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(react.Text, { children: formatValue(value) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5786
5927
  };
5787
5928
 
5788
5929
  const ObjectViewer = ({ schema, column, prefix }) => {
@@ -6074,112 +6215,46 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
6074
6215
  };
6075
6216
 
6076
6217
  const SubmitButton = () => {
6077
- const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, } = useSchemaContext();
6218
+ const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, requireConfirmation, onFormSubmit, } = useSchemaContext();
6078
6219
  const methods = reactHookForm.useFormContext();
6079
6220
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6080
6221
  const onValid = (data) => {
6081
6222
  const { isValid, errors } = validateData(data, schema);
6082
6223
  if (!isValid) {
6083
6224
  setError({
6084
- type: "validation",
6225
+ type: 'validation',
6085
6226
  errors,
6086
6227
  });
6087
6228
  setIsError(true);
6088
6229
  return;
6089
6230
  }
6090
- // If validation passes, proceed to confirmation
6091
- setValidatedData(data);
6092
- setIsError(false);
6093
- setIsConfirming(true);
6231
+ // If validation passes, check if confirmation is required
6232
+ if (requireConfirmation) {
6233
+ // Show confirmation (existing behavior)
6234
+ setValidatedData(data);
6235
+ setIsError(false);
6236
+ setIsConfirming(true);
6237
+ }
6238
+ else {
6239
+ // Skip confirmation and submit directly
6240
+ setValidatedData(data);
6241
+ setIsError(false);
6242
+ onFormSubmit(data);
6243
+ }
6094
6244
  };
6095
6245
  return (jsxRuntime.jsx(react.Button, { onClick: () => {
6096
6246
  methods.handleSubmit(onValid)();
6097
- }, formNoValidate: true, children: translate.t("submit") }));
6247
+ }, formNoValidate: true, children: translate.t('submit') }));
6098
6248
  };
6099
6249
 
6100
6250
  const FormBody = () => {
6101
- 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();
6251
+ const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, } = useSchemaContext();
6102
6252
  const { showSubmitButton, showResetButton } = displayConfig;
6103
6253
  const methods = reactHookForm.useFormContext();
6104
6254
  const { properties } = schema;
6105
- const onBeforeSubmit = () => {
6106
- setIsSubmiting(true);
6107
- };
6108
- const onAfterSubmit = () => {
6109
- setIsSubmiting(false);
6110
- };
6111
- const onSubmitError = (error) => {
6112
- setIsError(true);
6113
- setError(error);
6114
- };
6115
- const onSubmitSuccess = () => {
6116
- setIsSuccess(true);
6117
- };
6118
- const validateFormData = (data) => {
6119
- try {
6120
- const { isValid, errors } = validateData(data, schema);
6121
- return {
6122
- isValid,
6123
- errors,
6124
- };
6125
- }
6126
- catch (error) {
6127
- return {
6128
- isValid: false,
6129
- errors: [
6130
- {
6131
- field: "validation",
6132
- message: error instanceof Error ? error.message : "Unknown error",
6133
- },
6134
- ],
6135
- };
6136
- }
6137
- };
6138
- const defaultOnSubmit = async (promise) => {
6139
- try {
6140
- onBeforeSubmit();
6141
- await promise;
6142
- onSubmitSuccess();
6143
- }
6144
- catch (error) {
6145
- onSubmitError(error);
6146
- }
6147
- finally {
6148
- onAfterSubmit();
6149
- }
6150
- };
6151
- const defaultSubmitPromise = (data) => {
6152
- const options = {
6153
- method: "POST",
6154
- url: `${requestUrl}`,
6155
- data: clearEmptyString(data),
6156
- ...requestOptions,
6157
- };
6158
- return axios.request(options);
6159
- };
6160
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6161
- const onFormSubmit = async (data) => {
6162
- // Validate data using AJV before submission
6163
- const validationResult = validateFormData(data);
6164
- if (!validationResult.isValid) {
6165
- // Set validation errors
6166
- const validationErrorMessage = {
6167
- type: "validation",
6168
- errors: validationResult.errors,
6169
- message: translate.t("validation_error"),
6170
- };
6171
- onSubmitError(validationErrorMessage);
6172
- return;
6173
- }
6174
- if (onSubmit === undefined) {
6175
- await defaultOnSubmit(defaultSubmitPromise(data));
6176
- return;
6177
- }
6178
- await defaultOnSubmit(onSubmit(data));
6179
- };
6180
6255
  // Custom error renderer for validation errors with i18n support
6181
6256
  const renderValidationErrors = (validationErrors) => {
6182
- 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))) }));
6257
+ 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))) }));
6183
6258
  };
6184
6259
  const renderColumns = ({ order, keys, ignore, include, }) => {
6185
6260
  const included = include.length > 0 ? include : keys;
@@ -6207,32 +6282,32 @@ const FormBody = () => {
6207
6282
  if (customSuccessRenderer) {
6208
6283
  return customSuccessRenderer(resetHandler);
6209
6284
  }
6210
- 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: resetHandler, formNoValidate: true, children: translate.t("submit_again") }) })] }));
6285
+ 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: resetHandler, formNoValidate: true, children: translate.t('submit_again') }) })] }));
6211
6286
  }
6212
6287
  if (isConfirming) {
6213
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: 4, gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: "repeat(12, max-content)", autoFlow: "row", children: ordered.map((column) => {
6288
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: 4, gridTemplateColumns: 'repeat(12, 1fr)', gridTemplateRows: 'repeat(12, max-content)', autoFlow: 'row', children: ordered.map((column) => {
6214
6289
  return (jsxRuntime.jsx(ColumnViewer
6215
6290
  // @ts-expect-error find suitable types
6216
6291
  , {
6217
6292
  // @ts-expect-error find suitable types
6218
6293
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
6219
- }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [jsxRuntime.jsx(react.Button, { onClick: () => {
6294
+ }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: '2', children: [jsxRuntime.jsx(react.Button, { onClick: () => {
6220
6295
  setIsConfirming(false);
6221
- }, variant: "subtle", children: translate.t("cancel") }), jsxRuntime.jsx(react.Button, { onClick: () => {
6296
+ }, variant: 'subtle', children: translate.t('cancel') }), jsxRuntime.jsx(react.Button, { onClick: () => {
6222
6297
  onFormSubmit(validatedData);
6223
- }, 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" &&
6224
- 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)}` })] }) }) })] })] })) })) }))] }));
6298
+ }, 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' &&
6299
+ 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)}` })] }) }) })] })] })) })) }))] }));
6225
6300
  }
6226
- 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) => {
6301
+ 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) => {
6227
6302
  return (jsxRuntime.jsx(ColumnRenderer
6228
6303
  // @ts-expect-error find suitable types
6229
6304
  , {
6230
6305
  // @ts-expect-error find suitable types
6231
6306
  properties: properties, prefix: ``, column }, `form-input-${column}`));
6232
- }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
6307
+ }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
6233
6308
  methods.reset();
6234
- }, 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" &&
6235
- 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)}` })] }) }) })] })] })) })) }))] }));
6309
+ }, 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' &&
6310
+ 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)}` })] }) }) })] })] })) })) }))] }));
6236
6311
  };
6237
6312
 
6238
6313
  const FormTitle = () => {