@bsol-oss/react-datatable5 12.0.0-beta.73 → 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.d.ts CHANGED
@@ -622,6 +622,7 @@ interface CustomJSONSchema7 extends JSONSchema7 {
622
622
  timeFormat?: string;
623
623
  displayTimeFormat?: string;
624
624
  showLabel?: boolean;
625
+ formatOptions?: Intl.NumberFormatOptions;
625
626
  }
626
627
  interface TagPickerProps {
627
628
  column: string;
@@ -652,6 +653,7 @@ interface FormRootProps<TData extends FieldValues> {
652
653
  showResetButton?: boolean;
653
654
  showTitle?: boolean;
654
655
  };
656
+ requireConfirmation?: boolean;
655
657
  dateTimePickerLabels?: DateTimePickerLabels;
656
658
  idPickerLabels?: IdPickerLabels;
657
659
  enumPickerLabels?: EnumPickerLabels;
@@ -671,7 +673,7 @@ declare const idPickerSanityCheck: (column: string, foreign_key?: {
671
673
  column?: string | undefined;
672
674
  display_column?: string | undefined;
673
675
  } | undefined) => void;
674
- 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, enumPickerLabels, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
676
+ declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, requireConfirmation, dateTimePickerLabels, idPickerLabels, enumPickerLabels, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
675
677
 
676
678
  interface DefaultFormProps<TData extends FieldValues> {
677
679
  formConfig: Omit<FormRootProps<TData>, "children">;
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, enumPickerLabels, }) => {
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,6 +3851,8 @@ 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,
3779
3858
  enumPickerLabels,
@@ -4874,13 +4953,13 @@ react.NumberInput.Label;
4874
4953
  const NumberInputField = ({ schema, column, prefix, }) => {
4875
4954
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4876
4955
  const { translate } = useSchemaContext();
4877
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4956
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
4878
4957
  const isRequired = required?.some((columnId) => columnId === column);
4879
4958
  const colLabel = `${prefix}${column}`;
4880
4959
  const value = watch(`${colLabel}`);
4881
- 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) => {
4882
- setValue(`${colLabel}`, Number(event.target.value));
4883
- } }) }), 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`)) }))] }));
4884
4963
  };
4885
4964
 
4886
4965
  const ObjectInput = ({ schema, column, prefix }) => {
@@ -5822,11 +5901,29 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
5822
5901
  const NumberViewer = ({ schema, column, prefix, }) => {
5823
5902
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
5824
5903
  const { translate } = useSchemaContext();
5825
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5904
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5826
5905
  const isRequired = required?.some((columnId) => columnId === column);
5827
5906
  const colLabel = `${prefix}${column}`;
5828
5907
  const value = watch(colLabel);
5829
- 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`)) }))] }));
5830
5927
  };
5831
5928
 
5832
5929
  const ObjectViewer = ({ schema, column, prefix }) => {
@@ -6118,112 +6215,46 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
6118
6215
  };
6119
6216
 
6120
6217
  const SubmitButton = () => {
6121
- const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, } = useSchemaContext();
6218
+ const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, requireConfirmation, onFormSubmit, } = useSchemaContext();
6122
6219
  const methods = reactHookForm.useFormContext();
6123
6220
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6124
6221
  const onValid = (data) => {
6125
6222
  const { isValid, errors } = validateData(data, schema);
6126
6223
  if (!isValid) {
6127
6224
  setError({
6128
- type: "validation",
6225
+ type: 'validation',
6129
6226
  errors,
6130
6227
  });
6131
6228
  setIsError(true);
6132
6229
  return;
6133
6230
  }
6134
- // If validation passes, proceed to confirmation
6135
- setValidatedData(data);
6136
- setIsError(false);
6137
- 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
+ }
6138
6244
  };
6139
6245
  return (jsxRuntime.jsx(react.Button, { onClick: () => {
6140
6246
  methods.handleSubmit(onValid)();
6141
- }, formNoValidate: true, children: translate.t("submit") }));
6247
+ }, formNoValidate: true, children: translate.t('submit') }));
6142
6248
  };
6143
6249
 
6144
6250
  const FormBody = () => {
6145
- 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();
6146
6252
  const { showSubmitButton, showResetButton } = displayConfig;
6147
6253
  const methods = reactHookForm.useFormContext();
6148
6254
  const { properties } = schema;
6149
- const onBeforeSubmit = () => {
6150
- setIsSubmiting(true);
6151
- };
6152
- const onAfterSubmit = () => {
6153
- setIsSubmiting(false);
6154
- };
6155
- const onSubmitError = (error) => {
6156
- setIsError(true);
6157
- setError(error);
6158
- };
6159
- const onSubmitSuccess = () => {
6160
- setIsSuccess(true);
6161
- };
6162
- const validateFormData = (data) => {
6163
- try {
6164
- const { isValid, errors } = validateData(data, schema);
6165
- return {
6166
- isValid,
6167
- errors,
6168
- };
6169
- }
6170
- catch (error) {
6171
- return {
6172
- isValid: false,
6173
- errors: [
6174
- {
6175
- field: "validation",
6176
- message: error instanceof Error ? error.message : "Unknown error",
6177
- },
6178
- ],
6179
- };
6180
- }
6181
- };
6182
- const defaultOnSubmit = async (promise) => {
6183
- try {
6184
- onBeforeSubmit();
6185
- await promise;
6186
- onSubmitSuccess();
6187
- }
6188
- catch (error) {
6189
- onSubmitError(error);
6190
- }
6191
- finally {
6192
- onAfterSubmit();
6193
- }
6194
- };
6195
- const defaultSubmitPromise = (data) => {
6196
- const options = {
6197
- method: "POST",
6198
- url: `${requestUrl}`,
6199
- data: clearEmptyString(data),
6200
- ...requestOptions,
6201
- };
6202
- return axios.request(options);
6203
- };
6204
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6205
- const onFormSubmit = async (data) => {
6206
- // Validate data using AJV before submission
6207
- const validationResult = validateFormData(data);
6208
- if (!validationResult.isValid) {
6209
- // Set validation errors
6210
- const validationErrorMessage = {
6211
- type: "validation",
6212
- errors: validationResult.errors,
6213
- message: translate.t("validation_error"),
6214
- };
6215
- onSubmitError(validationErrorMessage);
6216
- return;
6217
- }
6218
- if (onSubmit === undefined) {
6219
- await defaultOnSubmit(defaultSubmitPromise(data));
6220
- return;
6221
- }
6222
- await defaultOnSubmit(onSubmit(data));
6223
- };
6224
6255
  // Custom error renderer for validation errors with i18n support
6225
6256
  const renderValidationErrors = (validationErrors) => {
6226
- 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))) }));
6227
6258
  };
6228
6259
  const renderColumns = ({ order, keys, ignore, include, }) => {
6229
6260
  const included = include.length > 0 ? include : keys;
@@ -6251,32 +6282,32 @@ const FormBody = () => {
6251
6282
  if (customSuccessRenderer) {
6252
6283
  return customSuccessRenderer(resetHandler);
6253
6284
  }
6254
- 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') }) })] }));
6255
6286
  }
6256
6287
  if (isConfirming) {
6257
- 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) => {
6258
6289
  return (jsxRuntime.jsx(ColumnViewer
6259
6290
  // @ts-expect-error find suitable types
6260
6291
  , {
6261
6292
  // @ts-expect-error find suitable types
6262
6293
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
6263
- }) }), 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: () => {
6264
6295
  setIsConfirming(false);
6265
- }, variant: "subtle", children: translate.t("cancel") }), jsxRuntime.jsx(react.Button, { onClick: () => {
6296
+ }, variant: 'subtle', children: translate.t('cancel') }), jsxRuntime.jsx(react.Button, { onClick: () => {
6266
6297
  onFormSubmit(validatedData);
6267
- }, 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" &&
6268
- 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)}` })] }) }) })] })] })) })) }))] }));
6269
6300
  }
6270
- 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) => {
6271
6302
  return (jsxRuntime.jsx(ColumnRenderer
6272
6303
  // @ts-expect-error find suitable types
6273
6304
  , {
6274
6305
  // @ts-expect-error find suitable types
6275
6306
  properties: properties, prefix: ``, column }, `form-input-${column}`));
6276
- }) }), 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: () => {
6277
6308
  methods.reset();
6278
- }, 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" &&
6279
- 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)}` })] }) }) })] })] })) })) }))] }));
6280
6311
  };
6281
6312
 
6282
6313
  const FormTitle = () => {
package/dist/index.mjs CHANGED
@@ -3671,16 +3671,14 @@ const SchemaFormContext = createContext({
3671
3671
  showResetButton: true,
3672
3672
  showTitle: true,
3673
3673
  },
3674
+ requireConfirmation: false,
3675
+ onFormSubmit: async () => { },
3674
3676
  });
3675
3677
 
3676
3678
  const useSchemaContext = () => {
3677
3679
  return useContext(SchemaFormContext);
3678
3680
  };
3679
3681
 
3680
- const clearEmptyString = (object) => {
3681
- return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3682
- };
3683
-
3684
3682
  const validateData = (data, schema) => {
3685
3683
  const ajv = new Ajv({
3686
3684
  strict: false,
@@ -3699,6 +3697,10 @@ const validateData = (data, schema) => {
3699
3697
  };
3700
3698
  };
3701
3699
 
3700
+ const clearEmptyString = (object) => {
3701
+ return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3702
+ };
3703
+
3702
3704
  const idPickerSanityCheck = (column, foreign_key) => {
3703
3705
  if (!!foreign_key == false) {
3704
3706
  throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
@@ -3718,13 +3720,88 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3718
3720
  showSubmitButton: true,
3719
3721
  showResetButton: true,
3720
3722
  showTitle: true,
3721
- }, dateTimePickerLabels, idPickerLabels, enumPickerLabels, }) => {
3723
+ }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, }) => {
3722
3724
  const [isSuccess, setIsSuccess] = useState(false);
3723
3725
  const [isError, setIsError] = useState(false);
3724
3726
  const [isSubmiting, setIsSubmiting] = useState(false);
3725
3727
  const [isConfirming, setIsConfirming] = useState(false);
3726
3728
  const [validatedData, setValidatedData] = useState();
3727
3729
  const [error, setError] = useState();
3730
+ const onBeforeSubmit = () => {
3731
+ setIsSubmiting(true);
3732
+ };
3733
+ const onAfterSubmit = () => {
3734
+ setIsSubmiting(false);
3735
+ };
3736
+ const onSubmitError = (error) => {
3737
+ setIsError(true);
3738
+ setError(error);
3739
+ };
3740
+ const onSubmitSuccess = () => {
3741
+ setIsSuccess(true);
3742
+ };
3743
+ const validateFormData = (data) => {
3744
+ try {
3745
+ const { isValid, errors } = validateData(data, schema);
3746
+ return {
3747
+ isValid,
3748
+ errors,
3749
+ };
3750
+ }
3751
+ catch (error) {
3752
+ return {
3753
+ isValid: false,
3754
+ errors: [
3755
+ {
3756
+ field: 'validation',
3757
+ message: error instanceof Error ? error.message : 'Unknown error',
3758
+ },
3759
+ ],
3760
+ };
3761
+ }
3762
+ };
3763
+ const defaultOnSubmit = async (promise) => {
3764
+ try {
3765
+ onBeforeSubmit();
3766
+ await promise;
3767
+ onSubmitSuccess();
3768
+ }
3769
+ catch (error) {
3770
+ onSubmitError(error);
3771
+ }
3772
+ finally {
3773
+ onAfterSubmit();
3774
+ }
3775
+ };
3776
+ const defaultSubmitPromise = (data) => {
3777
+ const options = {
3778
+ method: 'POST',
3779
+ url: `${requestUrl}`,
3780
+ data: clearEmptyString(data),
3781
+ ...requestOptions,
3782
+ };
3783
+ return axios.request(options);
3784
+ };
3785
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3786
+ const onFormSubmit = async (data) => {
3787
+ // Validate data using AJV before submission
3788
+ const validationResult = validateFormData(data);
3789
+ if (!validationResult.isValid) {
3790
+ // Set validation errors
3791
+ const validationErrorMessage = {
3792
+ type: 'validation',
3793
+ errors: validationResult.errors,
3794
+ message: translate.t('validation_error'),
3795
+ };
3796
+ onSubmitError(validationErrorMessage);
3797
+ return;
3798
+ }
3799
+ if (onSubmit === undefined) {
3800
+ await defaultOnSubmit(defaultSubmitPromise(data));
3801
+ return;
3802
+ }
3803
+ await defaultOnSubmit(onSubmit(data));
3804
+ };
3728
3805
  return (jsx(SchemaFormContext.Provider, { value: {
3729
3806
  schema,
3730
3807
  serverUrl,
@@ -3754,6 +3831,8 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3754
3831
  customErrorRenderer,
3755
3832
  customSuccessRenderer,
3756
3833
  displayConfig,
3834
+ requireConfirmation,
3835
+ onFormSubmit,
3757
3836
  dateTimePickerLabels,
3758
3837
  idPickerLabels,
3759
3838
  enumPickerLabels,
@@ -4854,13 +4933,13 @@ NumberInput.Label;
4854
4933
  const NumberInputField = ({ schema, column, prefix, }) => {
4855
4934
  const { setValue, formState: { errors }, watch, } = useFormContext();
4856
4935
  const { translate } = useSchemaContext();
4857
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4936
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
4858
4937
  const isRequired = required?.some((columnId) => columnId === column);
4859
4938
  const colLabel = `${prefix}${column}`;
4860
4939
  const value = watch(`${colLabel}`);
4861
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(NumberInputRoot, { children: jsx(NumberInputField$1, { required: isRequired, value: value, onChange: (event) => {
4862
- setValue(`${colLabel}`, Number(event.target.value));
4863
- } }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4940
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(NumberInputRoot, { value: value, onValueChange: (details) => {
4941
+ setValue(`${colLabel}`, details.value); // Store as string to avoid floating-point precision issues
4942
+ }, min: schema.minimum, max: schema.maximum, step: schema.multipleOf || 0.01, allowOverflow: false, clampValueOnBlur: false, inputMode: "decimal", formatOptions: schema.formatOptions, children: jsx(NumberInputField$1, { required: isRequired }) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4864
4943
  };
4865
4944
 
4866
4945
  const ObjectInput = ({ schema, column, prefix }) => {
@@ -5802,11 +5881,29 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
5802
5881
  const NumberViewer = ({ schema, column, prefix, }) => {
5803
5882
  const { watch, formState: { errors }, } = useFormContext();
5804
5883
  const { translate } = useSchemaContext();
5805
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5884
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5806
5885
  const isRequired = required?.some((columnId) => columnId === column);
5807
5886
  const colLabel = `${prefix}${column}`;
5808
5887
  const value = watch(colLabel);
5809
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(Text, { children: value }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5888
+ // Format the value for display if formatOptions are provided
5889
+ const formatValue = (val) => {
5890
+ if (val === undefined || val === null || val === '')
5891
+ return '';
5892
+ const numValue = typeof val === 'string' ? parseFloat(val) : val;
5893
+ if (isNaN(numValue))
5894
+ return String(val);
5895
+ // Use formatOptions if available, otherwise display as-is
5896
+ if (schema.formatOptions) {
5897
+ try {
5898
+ return new Intl.NumberFormat(undefined, schema.formatOptions).format(numValue);
5899
+ }
5900
+ catch {
5901
+ return String(val);
5902
+ }
5903
+ }
5904
+ return String(val);
5905
+ };
5906
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(Text, { children: formatValue(value) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5810
5907
  };
5811
5908
 
5812
5909
  const ObjectViewer = ({ schema, column, prefix }) => {
@@ -6098,112 +6195,46 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
6098
6195
  };
6099
6196
 
6100
6197
  const SubmitButton = () => {
6101
- const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, } = useSchemaContext();
6198
+ const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, requireConfirmation, onFormSubmit, } = useSchemaContext();
6102
6199
  const methods = useFormContext();
6103
6200
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6104
6201
  const onValid = (data) => {
6105
6202
  const { isValid, errors } = validateData(data, schema);
6106
6203
  if (!isValid) {
6107
6204
  setError({
6108
- type: "validation",
6205
+ type: 'validation',
6109
6206
  errors,
6110
6207
  });
6111
6208
  setIsError(true);
6112
6209
  return;
6113
6210
  }
6114
- // If validation passes, proceed to confirmation
6115
- setValidatedData(data);
6116
- setIsError(false);
6117
- setIsConfirming(true);
6211
+ // If validation passes, check if confirmation is required
6212
+ if (requireConfirmation) {
6213
+ // Show confirmation (existing behavior)
6214
+ setValidatedData(data);
6215
+ setIsError(false);
6216
+ setIsConfirming(true);
6217
+ }
6218
+ else {
6219
+ // Skip confirmation and submit directly
6220
+ setValidatedData(data);
6221
+ setIsError(false);
6222
+ onFormSubmit(data);
6223
+ }
6118
6224
  };
6119
6225
  return (jsx(Button$1, { onClick: () => {
6120
6226
  methods.handleSubmit(onValid)();
6121
- }, formNoValidate: true, children: translate.t("submit") }));
6227
+ }, formNoValidate: true, children: translate.t('submit') }));
6122
6228
  };
6123
6229
 
6124
6230
  const FormBody = () => {
6125
- 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();
6231
+ const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, } = useSchemaContext();
6126
6232
  const { showSubmitButton, showResetButton } = displayConfig;
6127
6233
  const methods = useFormContext();
6128
6234
  const { properties } = schema;
6129
- const onBeforeSubmit = () => {
6130
- setIsSubmiting(true);
6131
- };
6132
- const onAfterSubmit = () => {
6133
- setIsSubmiting(false);
6134
- };
6135
- const onSubmitError = (error) => {
6136
- setIsError(true);
6137
- setError(error);
6138
- };
6139
- const onSubmitSuccess = () => {
6140
- setIsSuccess(true);
6141
- };
6142
- const validateFormData = (data) => {
6143
- try {
6144
- const { isValid, errors } = validateData(data, schema);
6145
- return {
6146
- isValid,
6147
- errors,
6148
- };
6149
- }
6150
- catch (error) {
6151
- return {
6152
- isValid: false,
6153
- errors: [
6154
- {
6155
- field: "validation",
6156
- message: error instanceof Error ? error.message : "Unknown error",
6157
- },
6158
- ],
6159
- };
6160
- }
6161
- };
6162
- const defaultOnSubmit = async (promise) => {
6163
- try {
6164
- onBeforeSubmit();
6165
- await promise;
6166
- onSubmitSuccess();
6167
- }
6168
- catch (error) {
6169
- onSubmitError(error);
6170
- }
6171
- finally {
6172
- onAfterSubmit();
6173
- }
6174
- };
6175
- const defaultSubmitPromise = (data) => {
6176
- const options = {
6177
- method: "POST",
6178
- url: `${requestUrl}`,
6179
- data: clearEmptyString(data),
6180
- ...requestOptions,
6181
- };
6182
- return axios.request(options);
6183
- };
6184
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6185
- const onFormSubmit = async (data) => {
6186
- // Validate data using AJV before submission
6187
- const validationResult = validateFormData(data);
6188
- if (!validationResult.isValid) {
6189
- // Set validation errors
6190
- const validationErrorMessage = {
6191
- type: "validation",
6192
- errors: validationResult.errors,
6193
- message: translate.t("validation_error"),
6194
- };
6195
- onSubmitError(validationErrorMessage);
6196
- return;
6197
- }
6198
- if (onSubmit === undefined) {
6199
- await defaultOnSubmit(defaultSubmitPromise(data));
6200
- return;
6201
- }
6202
- await defaultOnSubmit(onSubmit(data));
6203
- };
6204
6235
  // Custom error renderer for validation errors with i18n support
6205
6236
  const renderValidationErrors = (validationErrors) => {
6206
- 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))) }));
6237
+ 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))) }));
6207
6238
  };
6208
6239
  const renderColumns = ({ order, keys, ignore, include, }) => {
6209
6240
  const included = include.length > 0 ? include : keys;
@@ -6231,32 +6262,32 @@ const FormBody = () => {
6231
6262
  if (customSuccessRenderer) {
6232
6263
  return customSuccessRenderer(resetHandler);
6233
6264
  }
6234
- 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") }) })] }));
6265
+ 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') }) })] }));
6235
6266
  }
6236
6267
  if (isConfirming) {
6237
- 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) => {
6268
+ 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) => {
6238
6269
  return (jsx(ColumnViewer
6239
6270
  // @ts-expect-error find suitable types
6240
6271
  , {
6241
6272
  // @ts-expect-error find suitable types
6242
6273
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
6243
- }) }), jsxs(Flex, { justifyContent: "end", gap: "2", children: [jsx(Button$1, { onClick: () => {
6274
+ }) }), jsxs(Flex, { justifyContent: 'end', gap: '2', children: [jsx(Button$1, { onClick: () => {
6244
6275
  setIsConfirming(false);
6245
- }, variant: "subtle", children: translate.t("cancel") }), jsx(Button$1, { onClick: () => {
6276
+ }, variant: 'subtle', children: translate.t('cancel') }), jsx(Button$1, { onClick: () => {
6246
6277
  onFormSubmit(validatedData);
6247
- }, 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" &&
6248
- 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)}` })] }) }) })] })] })) })) }))] }));
6278
+ }, 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' &&
6279
+ 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)}` })] }) }) })] })] })) })) }))] }));
6249
6280
  }
6250
- return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: ordered.map((column) => {
6281
+ return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
6251
6282
  return (jsx(ColumnRenderer
6252
6283
  // @ts-expect-error find suitable types
6253
6284
  , {
6254
6285
  // @ts-expect-error find suitable types
6255
6286
  properties: properties, prefix: ``, column }, `form-input-${column}`));
6256
- }) }), jsxs(Flex, { justifyContent: "end", gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
6287
+ }) }), jsxs(Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
6257
6288
  methods.reset();
6258
- }, variant: "subtle", children: translate.t("reset") })), showSubmitButton && jsx(SubmitButton, {})] }), isError && (jsx(Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsx(Fragment, { children: error?.type === "validation" &&
6259
- 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)}` })] }) }) })] })] })) })) }))] }));
6289
+ }, variant: 'subtle', children: translate.t('reset') })), showSubmitButton && jsx(SubmitButton, {})] }), isError && (jsx(Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsx(Fragment, { children: error?.type === 'validation' &&
6290
+ 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)}` })] }) }) })] })] })) })) }))] }));
6260
6291
  };
6261
6292
 
6262
6293
  const FormTitle = () => {
@@ -38,6 +38,8 @@ export interface SchemaFormContext<TData extends FieldValues> {
38
38
  showResetButton?: boolean;
39
39
  showTitle?: boolean;
40
40
  };
41
+ requireConfirmation: boolean;
42
+ onFormSubmit: (data: TData) => Promise<void>;
41
43
  dateTimePickerLabels?: DateTimePickerLabels;
42
44
  idPickerLabels?: IdPickerLabels;
43
45
  enumPickerLabels?: EnumPickerLabels;
@@ -28,6 +28,7 @@ export interface FormRootProps<TData extends FieldValues> {
28
28
  showResetButton?: boolean;
29
29
  showTitle?: boolean;
30
30
  };
31
+ requireConfirmation?: boolean;
31
32
  dateTimePickerLabels?: DateTimePickerLabels;
32
33
  idPickerLabels?: IdPickerLabels;
33
34
  enumPickerLabels?: EnumPickerLabels;
@@ -47,4 +48,4 @@ export declare const idPickerSanityCheck: (column: string, foreign_key?: {
47
48
  column?: string | undefined;
48
49
  display_column?: string | undefined;
49
50
  } | undefined) => void;
50
- 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, enumPickerLabels, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
51
+ export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, requireConfirmation, dateTimePickerLabels, idPickerLabels, enumPickerLabels, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
1
+ import { CustomJSONSchema7 } from '../types/CustomJSONSchema7';
2
2
  export interface NumberInputFieldProps {
3
3
  column: string;
4
4
  schema: CustomJSONSchema7;
@@ -51,6 +51,7 @@ export interface CustomJSONSchema7 extends JSONSchema7 {
51
51
  timeFormat?: string;
52
52
  displayTimeFormat?: string;
53
53
  showLabel?: boolean;
54
+ formatOptions?: Intl.NumberFormatOptions;
54
55
  }
55
56
  export interface TagPickerProps {
56
57
  column: string;
@@ -1,4 +1,4 @@
1
- import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
1
+ import { CustomJSONSchema7 } from '../types/CustomJSONSchema7';
2
2
  export interface NumberInputFieldProps {
3
3
  column: string;
4
4
  schema: CustomJSONSchema7;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsol-oss/react-datatable5",
3
- "version": "12.0.0-beta.73",
3
+ "version": "12.0.0-beta.74",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",