@bsol-oss/react-datatable5 12.0.0-beta.73 → 12.0.0-beta.75

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.
Files changed (84) hide show
  1. package/dist/index.d.ts +133 -124
  2. package/dist/index.js +651 -306
  3. package/dist/index.mjs +653 -309
  4. package/dist/types/components/Form/SchemaFormContext.d.ts +5 -2
  5. package/dist/types/components/Form/components/core/FormRoot.d.ts +2 -1
  6. package/dist/types/components/Form/components/fields/BooleanPicker.d.ts +1 -1
  7. package/dist/types/components/Form/components/fields/ColumnRenderer.d.ts +3 -2
  8. package/dist/types/components/Form/components/fields/DateTimePicker.d.ts +1 -1
  9. package/dist/types/components/Form/components/fields/FilePicker.d.ts +1 -1
  10. package/dist/types/components/Form/components/fields/NumberInputField.d.ts +1 -1
  11. package/dist/types/components/Form/components/fields/ObjectInput.d.ts +1 -1
  12. package/dist/types/components/Form/components/fields/RecordInput.d.ts +1 -1
  13. package/dist/types/components/Form/components/fields/StringInputField.d.ts +1 -1
  14. package/dist/types/components/Form/components/fields/TextAreaInput.d.ts +1 -1
  15. package/dist/types/components/Form/components/fields/TimePicker.d.ts +1 -1
  16. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +4 -0
  17. package/dist/types/components/Form/components/viewers/NumberViewer.d.ts +1 -1
  18. package/dist/types/components/Form/useForm.d.ts +4 -2
  19. package/dist/types/components/Form/utils/ajvResolver.d.ts +13 -0
  20. package/dist/types/components/Form/utils/buildErrorMessages.d.ts +5 -1
  21. package/dist/types/components/Form/utils/getFieldError.d.ts +6 -0
  22. package/dist/types/components/Form/utils/useFormI18n.d.ts +1 -1
  23. package/dist/types/components/Form/utils/validateData.d.ts +2 -2
  24. package/dist/types/components/ui/field.d.ts +3 -3
  25. package/package.json +1 -1
  26. package/dist/types/components/Controls/DensityFeature.d.ts +0 -23
  27. package/dist/types/components/Controls/DensityToggleButton.d.ts +0 -6
  28. package/dist/types/components/Controls/EditFilterButton.d.ts +0 -9
  29. package/dist/types/components/Controls/EditOrderButton.d.ts +0 -7
  30. package/dist/types/components/Controls/EditSortingButton.d.ts +0 -7
  31. package/dist/types/components/Controls/EditViewButton.d.ts +0 -7
  32. package/dist/types/components/Controls/FilterDialog.d.ts +0 -5
  33. package/dist/types/components/Controls/PageSizeControl.d.ts +0 -4
  34. package/dist/types/components/Controls/Pagination.d.ts +0 -1
  35. package/dist/types/components/Controls/ResetFilteringButton.d.ts +0 -4
  36. package/dist/types/components/Controls/ResetSelectionButton.d.ts +0 -4
  37. package/dist/types/components/Controls/ResetSortingButton.d.ts +0 -4
  38. package/dist/types/components/Controls/RowCountText.d.ts +0 -1
  39. package/dist/types/components/Controls/SelectAllRowsToggle.d.ts +0 -8
  40. package/dist/types/components/Controls/TablePagination.d.ts +0 -1
  41. package/dist/types/components/Controls/ViewDialog.d.ts +0 -5
  42. package/dist/types/components/DataTable/CardHeader.d.ts +0 -13
  43. package/dist/types/components/DataTable/DataDisplay.d.ts +0 -6
  44. package/dist/types/components/DataTable/ReloadButton.d.ts +0 -5
  45. package/dist/types/components/DataTable/Table.d.ts +0 -10
  46. package/dist/types/components/DataTable/TableBody.d.ts +0 -21
  47. package/dist/types/components/DataTable/TableCardContainer.d.ts +0 -7
  48. package/dist/types/components/DataTable/TableCards.d.ts +0 -11
  49. package/dist/types/components/DataTable/TableComponent.d.ts +0 -6
  50. package/dist/types/components/DataTable/TableControls.d.ts +0 -21
  51. package/dist/types/components/DataTable/TableFilter.d.ts +0 -1
  52. package/dist/types/components/DataTable/TableFilterTags.d.ts +0 -1
  53. package/dist/types/components/DataTable/TableFilters.d.ts +0 -1
  54. package/dist/types/components/DataTable/TableFooter.d.ts +0 -9
  55. package/dist/types/components/DataTable/TableHeader.d.ts +0 -13
  56. package/dist/types/components/DataTable/TableLoadingComponent.d.ts +0 -5
  57. package/dist/types/components/DataTable/TableOrderer.d.ts +0 -1
  58. package/dist/types/components/DataTable/TableSelector.d.ts +0 -1
  59. package/dist/types/components/DataTable/TableSorter.d.ts +0 -1
  60. package/dist/types/components/DataTable/TableViewer.d.ts +0 -1
  61. package/dist/types/components/DataTable/TextCell.d.ts +0 -10
  62. package/dist/types/components/DataTable/components/EmptyState.d.ts +0 -5
  63. package/dist/types/components/DataTable/components/ErrorAlert.d.ts +0 -4
  64. package/dist/types/components/DataTable/components/RecordDisplay.d.ts +0 -9
  65. package/dist/types/components/DataTable/components/TextCell.d.ts +0 -10
  66. package/dist/types/components/Filter/DateRangeFilter.d.ts +0 -9
  67. package/dist/types/components/Filter/FilterOptions.d.ts +0 -4
  68. package/dist/types/components/Form/Form.d.ts +0 -36
  69. package/dist/types/components/Form/components/ArrayRenderer.d.ts +0 -7
  70. package/dist/types/components/Form/components/BooleanPicker.d.ts +0 -7
  71. package/dist/types/components/Form/components/ColumnRenderer.d.ts +0 -7
  72. package/dist/types/components/Form/components/DatePicker.d.ts +0 -7
  73. package/dist/types/components/Form/components/EnumPicker.d.ts +0 -8
  74. package/dist/types/components/Form/components/FilePicker.d.ts +0 -5
  75. package/dist/types/components/Form/components/IdPicker.d.ts +0 -8
  76. package/dist/types/components/Form/components/IdViewer.d.ts +0 -5
  77. package/dist/types/components/Form/components/NumberInputField.d.ts +0 -7
  78. package/dist/types/components/Form/components/ObjectInput.d.ts +0 -7
  79. package/dist/types/components/Form/components/RecordInput.d.ts +0 -7
  80. package/dist/types/components/Form/components/SchemaRenderer.d.ts +0 -7
  81. package/dist/types/components/Form/components/StringInputField.d.ts +0 -20
  82. package/dist/types/components/Form/components/TagPicker.d.ts +0 -30
  83. package/dist/types/components/Form/utils/translateWrapper.d.ts +0 -6
  84. package/dist/types/components/Form/utils/validation.d.ts +0 -104
package/dist/index.js CHANGED
@@ -31,7 +31,6 @@ var axios = require('axios');
31
31
  var reactHookForm = require('react-hook-form');
32
32
  var Ajv = require('ajv');
33
33
  var addFormats = require('ajv-formats');
34
- var addErrors = require('ajv-errors');
35
34
  var dayjs = require('dayjs');
36
35
  var utc = require('dayjs/plugin/utc');
37
36
  var timezone = require('dayjs/plugin/timezone');
@@ -3664,16 +3663,6 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
3664
3663
  })] }));
3665
3664
  };
3666
3665
 
3667
- const AccordionItemTrigger = React__namespace.forwardRef(function AccordionItemTrigger(props, ref) {
3668
- const { children, indicatorPlacement = "end", ...rest } = props;
3669
- return (jsxRuntime.jsxs(react.Accordion.ItemTrigger, { ...rest, ref: ref, children: [indicatorPlacement === "start" && (jsxRuntime.jsx(react.Accordion.ItemIndicator, { rotate: { base: "-90deg", _open: "0deg" }, children: jsxRuntime.jsx(lu.LuChevronDown, {}) })), jsxRuntime.jsx(react.HStack, { gap: "4", flex: "1", textAlign: "start", width: "full", children: children }), indicatorPlacement === "end" && (jsxRuntime.jsx(react.Accordion.ItemIndicator, { children: jsxRuntime.jsx(lu.LuChevronDown, {}) }))] }));
3670
- });
3671
- const AccordionItemContent = React__namespace.forwardRef(function AccordionItemContent(props, ref) {
3672
- return (jsxRuntime.jsx(react.Accordion.ItemContent, { children: jsxRuntime.jsx(react.Accordion.ItemBody, { ...props, ref: ref }) }));
3673
- });
3674
- const AccordionRoot = react.Accordion.Root;
3675
- const AccordionItem = react.Accordion.Item;
3676
-
3677
3666
  //@ts-expect-error TODO: find appropriate type
3678
3667
  const SchemaFormContext = React.createContext({
3679
3668
  schema: {},
@@ -3691,6 +3680,9 @@ const SchemaFormContext = React.createContext({
3691
3680
  showResetButton: true,
3692
3681
  showTitle: true,
3693
3682
  },
3683
+ requireConfirmation: false,
3684
+ onFormSubmit: async () => { },
3685
+ ajvResolver: async () => ({ values: {}, errors: {} }),
3694
3686
  });
3695
3687
 
3696
3688
  const useSchemaContext = () => {
@@ -3707,7 +3699,6 @@ const validateData = (data, schema) => {
3707
3699
  allErrors: true,
3708
3700
  });
3709
3701
  addFormats(ajv);
3710
- addErrors(ajv);
3711
3702
  const validate = ajv.compile(schema);
3712
3703
  const validationResult = validate(data);
3713
3704
  const errors = validate.errors;
@@ -3719,6 +3710,185 @@ const validateData = (data, schema) => {
3719
3710
  };
3720
3711
  };
3721
3712
 
3713
+ /**
3714
+ * Gets the schema node for a field by following the path from root schema
3715
+ */
3716
+ const getSchemaNodeForField = (schema, fieldPath) => {
3717
+ if (!fieldPath || fieldPath === '') {
3718
+ return schema;
3719
+ }
3720
+ const pathParts = fieldPath.split('.');
3721
+ let currentSchema = schema;
3722
+ for (const part of pathParts) {
3723
+ if (currentSchema &&
3724
+ currentSchema.properties &&
3725
+ currentSchema.properties[part] &&
3726
+ typeof currentSchema.properties[part] === 'object' &&
3727
+ currentSchema.properties[part] !== null) {
3728
+ currentSchema = currentSchema.properties[part];
3729
+ }
3730
+ else {
3731
+ return undefined;
3732
+ }
3733
+ }
3734
+ return currentSchema;
3735
+ };
3736
+ /**
3737
+ * Converts AJV error objects to react-hook-form field errors format
3738
+ */
3739
+ const convertAjvErrorsToFieldErrors = (errors, schema) => {
3740
+ if (!errors || errors.length === 0) {
3741
+ return {};
3742
+ }
3743
+ const fieldErrors = {};
3744
+ errors.forEach((error) => {
3745
+ let fieldName = '';
3746
+ // Special handling for required keyword: map to the specific missing property
3747
+ if (error.keyword === 'required') {
3748
+ const basePath = (error.instancePath || '')
3749
+ .replace(/^\//, '')
3750
+ .replace(/\//g, '.');
3751
+ const missingProperty = (error.params &&
3752
+ error.params.missingProperty);
3753
+ if (missingProperty) {
3754
+ fieldName = basePath
3755
+ ? `${basePath}.${missingProperty}`
3756
+ : missingProperty;
3757
+ }
3758
+ else {
3759
+ // Fallback to schemaPath conversion if missingProperty is unavailable
3760
+ fieldName = (error.schemaPath || '')
3761
+ .replace(/^#\//, '#.')
3762
+ .replace(/\//g, '.');
3763
+ }
3764
+ }
3765
+ else {
3766
+ const fieldPath = error.instancePath || error.schemaPath;
3767
+ if (fieldPath) {
3768
+ fieldName = fieldPath.replace(/^\//, '').replace(/\//g, '.');
3769
+ }
3770
+ }
3771
+ if (fieldName) {
3772
+ // Get the schema node for this field to check for custom error messages
3773
+ const fieldSchema = getSchemaNodeForField(schema, fieldName);
3774
+ const customMessage = fieldSchema?.errorMessages?.[error.keyword];
3775
+ // Provide helpful fallback message if no custom message is provided
3776
+ const fallbackMessage = customMessage ||
3777
+ `Missing error message for ${error.keyword}. Add errorMessages.${error.keyword} to schema for field '${fieldName}'`;
3778
+ if (error.keyword === 'required') {
3779
+ // Required errors override any existing non-required errors for this field
3780
+ fieldErrors[fieldName] = {
3781
+ type: 'required',
3782
+ keyword: error.keyword,
3783
+ params: error.params,
3784
+ message: fallbackMessage,
3785
+ };
3786
+ }
3787
+ else {
3788
+ const existing = fieldErrors[fieldName];
3789
+ if (existing) {
3790
+ // Do not override required errors
3791
+ if (existing.type === 'required') {
3792
+ return;
3793
+ }
3794
+ // Combine messages if multiple errors for same field
3795
+ existing.message = existing.message
3796
+ ? `${existing.message}; ${fallbackMessage}`
3797
+ : fallbackMessage;
3798
+ }
3799
+ else {
3800
+ fieldErrors[fieldName] = {
3801
+ type: error.keyword,
3802
+ keyword: error.keyword,
3803
+ params: error.params,
3804
+ message: fallbackMessage,
3805
+ };
3806
+ }
3807
+ }
3808
+ }
3809
+ });
3810
+ return fieldErrors;
3811
+ };
3812
+ /**
3813
+ * AJV resolver for react-hook-form
3814
+ * Integrates AJV validation with react-hook-form's validation system
3815
+ */
3816
+ /**
3817
+ * Strips null, undefined, and empty string values from an object
3818
+ */
3819
+ const stripEmptyValues = (obj) => {
3820
+ if (obj === null || obj === undefined) {
3821
+ return undefined;
3822
+ }
3823
+ if (typeof obj === 'string' && obj.trim() === '') {
3824
+ return undefined;
3825
+ }
3826
+ if (Array.isArray(obj)) {
3827
+ const filtered = obj
3828
+ .map(stripEmptyValues)
3829
+ .filter((item) => item !== undefined);
3830
+ return filtered.length > 0 ? filtered : undefined;
3831
+ }
3832
+ if (typeof obj === 'object' && obj !== null) {
3833
+ const result = {};
3834
+ let hasValues = false;
3835
+ for (const [key, value] of Object.entries(obj)) {
3836
+ const cleanedValue = stripEmptyValues(value);
3837
+ if (cleanedValue !== undefined) {
3838
+ result[key] = cleanedValue;
3839
+ hasValues = true;
3840
+ }
3841
+ }
3842
+ return hasValues ? result : undefined;
3843
+ }
3844
+ return obj;
3845
+ };
3846
+ const ajvResolver = (schema) => {
3847
+ return async (values) => {
3848
+ try {
3849
+ // Strip empty values before validation
3850
+ const cleanedValues = stripEmptyValues(values);
3851
+ // Use empty object for validation if all values were stripped
3852
+ const valuesToValidate = cleanedValues === undefined ? {} : cleanedValues;
3853
+ const { isValid, errors } = validateData(valuesToValidate, schema);
3854
+ console.debug('AJV Validation Result:', {
3855
+ isValid,
3856
+ errors,
3857
+ cleanedValues,
3858
+ valuesToValidate,
3859
+ });
3860
+ if (isValid) {
3861
+ return {
3862
+ values: (cleanedValues || {}),
3863
+ errors: {},
3864
+ };
3865
+ }
3866
+ const fieldErrors = convertAjvErrorsToFieldErrors(errors, schema);
3867
+ console.debug('AJV Validation Failed:', {
3868
+ errors,
3869
+ fieldErrors,
3870
+ cleanedValues,
3871
+ valuesToValidate,
3872
+ });
3873
+ return {
3874
+ values: {},
3875
+ errors: fieldErrors,
3876
+ };
3877
+ }
3878
+ catch (error) {
3879
+ return {
3880
+ values: {},
3881
+ errors: {
3882
+ root: {
3883
+ type: 'validation',
3884
+ message: error instanceof Error ? error.message : 'Validation failed',
3885
+ },
3886
+ },
3887
+ };
3888
+ }
3889
+ };
3890
+ };
3891
+
3722
3892
  const idPickerSanityCheck = (column, foreign_key) => {
3723
3893
  if (!!foreign_key == false) {
3724
3894
  throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
@@ -3738,13 +3908,61 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3738
3908
  showSubmitButton: true,
3739
3909
  showResetButton: true,
3740
3910
  showTitle: true,
3741
- }, dateTimePickerLabels, idPickerLabels, enumPickerLabels, }) => {
3911
+ }, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, }) => {
3742
3912
  const [isSuccess, setIsSuccess] = React.useState(false);
3743
3913
  const [isError, setIsError] = React.useState(false);
3744
3914
  const [isSubmiting, setIsSubmiting] = React.useState(false);
3745
3915
  const [isConfirming, setIsConfirming] = React.useState(false);
3746
3916
  const [validatedData, setValidatedData] = React.useState();
3747
3917
  const [error, setError] = React.useState();
3918
+ const onBeforeSubmit = () => {
3919
+ setIsSubmiting(true);
3920
+ };
3921
+ const onAfterSubmit = () => {
3922
+ setIsSubmiting(false);
3923
+ };
3924
+ const onSubmitError = (error) => {
3925
+ setIsError(true);
3926
+ setError(error);
3927
+ };
3928
+ const onSubmitSuccess = () => {
3929
+ setIsSuccess(true);
3930
+ };
3931
+ const defaultOnSubmit = async (promise) => {
3932
+ try {
3933
+ console.log('onBeforeSubmit');
3934
+ onBeforeSubmit();
3935
+ await promise;
3936
+ console.log('onSubmitSuccess');
3937
+ onSubmitSuccess();
3938
+ }
3939
+ catch (error) {
3940
+ console.log('onSubmitError', error);
3941
+ onSubmitError(error);
3942
+ }
3943
+ finally {
3944
+ onAfterSubmit();
3945
+ }
3946
+ };
3947
+ const defaultSubmitPromise = (data) => {
3948
+ const options = {
3949
+ method: 'POST',
3950
+ url: `${serverUrl}`,
3951
+ data: clearEmptyString(data),
3952
+ ...requestOptions,
3953
+ };
3954
+ return axios.request(options);
3955
+ };
3956
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3957
+ const onFormSubmit = async (data) => {
3958
+ // AJV validation is now handled by react-hook-form resolver
3959
+ // This function will only be called if validation passes
3960
+ if (onSubmit === undefined) {
3961
+ await defaultOnSubmit(Promise.resolve(defaultSubmitPromise(data)));
3962
+ return;
3963
+ }
3964
+ await defaultOnSubmit(Promise.resolve(onSubmit(data)));
3965
+ };
3748
3966
  return (jsxRuntime.jsx(SchemaFormContext.Provider, { value: {
3749
3967
  schema,
3750
3968
  serverUrl,
@@ -3774,9 +3992,12 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3774
3992
  customErrorRenderer,
3775
3993
  customSuccessRenderer,
3776
3994
  displayConfig,
3995
+ requireConfirmation,
3996
+ onFormSubmit,
3777
3997
  dateTimePickerLabels,
3778
3998
  idPickerLabels,
3779
3999
  enumPickerLabels,
4000
+ ajvResolver: ajvResolver(schema),
3780
4001
  }, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
3781
4002
  };
3782
4003
 
@@ -3822,20 +4043,22 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
3822
4043
 
3823
4044
  const Field = React__namespace.forwardRef(function Field(props, ref) {
3824
4045
  const { label, children, helperText, errorText, optionalText, ...rest } = props;
3825
- return (jsxRuntime.jsxs(react.Field.Root, { ref: ref, ...rest, children: [label && (jsxRuntime.jsxs(react.Field.Label, { children: [label, jsxRuntime.jsx(react.Field.RequiredIndicator, { fallback: optionalText })] })), children, helperText && (jsxRuntime.jsx(react.Field.HelperText, { children: helperText })), errorText && (jsxRuntime.jsx(react.Field.ErrorText, { children: errorText }))] }));
4046
+ return (jsxRuntime.jsxs(react.Field.Root, { ref: ref, ...rest, children: [label && (jsxRuntime.jsxs(react.Field.Label, { children: [label, jsxRuntime.jsx(react.Field.RequiredIndicator, { color: rest.invalid && rest.required ? 'red.500' : undefined, fallback: optionalText })] })), children, helperText && (jsxRuntime.jsx(react.Field.HelperText, { children: helperText })), !!errorText && (jsxRuntime.jsxs(react.Field.ErrorText, { children: [rest.required && rest.invalid && (jsxRuntime.jsx("span", { style: { color: 'var(--chakra-colors-red-500)' }, children: "* " })), errorText] }))] }));
3826
4047
  });
3827
4048
 
3828
4049
  const BooleanPicker = ({ schema, column, prefix }) => {
3829
4050
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
3830
4051
  const { translate } = useSchemaContext();
3831
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4052
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
3832
4053
  const isRequired = required?.some((columnId) => columnId === column);
3833
4054
  const colLabel = `${prefix}${column}`;
3834
4055
  const value = watch(colLabel);
3835
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3836
- gridRow, children: [jsxRuntime.jsx(CheckboxCard, { checked: value, variant: "surface", onChange: () => {
3837
- setValue(colLabel, !value);
3838
- } }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4056
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4057
+ gridRow, errorText: errors[`${colLabel}`]
4058
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
4059
+ : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
4060
+ setValue(colLabel, !value);
4061
+ } }) }));
3839
4062
  };
3840
4063
 
3841
4064
  const CustomInput = ({ column, schema, prefix }) => {
@@ -4068,83 +4291,83 @@ const DatePicker = ({ column, schema, prefix }) => {
4068
4291
  console.error(e);
4069
4292
  }
4070
4293
  }, [selectedDate, dateFormat, colLabel, setValue]);
4071
- return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4072
- 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: () => {
4073
- setOpen(true);
4074
- }, 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 }) => {
4075
- setValue(colLabel, dayjs(date).format(dateFormat));
4076
- setOpen(false);
4077
- }, labels: {
4078
- monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4079
- formI18n.translate.t(`common.month_1`, {
4080
- defaultValue: 'January',
4081
- }),
4082
- formI18n.translate.t(`common.month_2`, {
4083
- defaultValue: 'February',
4084
- }),
4085
- formI18n.translate.t(`common.month_3`, {
4086
- defaultValue: 'March',
4087
- }),
4088
- formI18n.translate.t(`common.month_4`, {
4089
- defaultValue: 'April',
4090
- }),
4091
- formI18n.translate.t(`common.month_5`, {
4092
- defaultValue: 'May',
4093
- }),
4094
- formI18n.translate.t(`common.month_6`, {
4095
- defaultValue: 'June',
4096
- }),
4097
- formI18n.translate.t(`common.month_7`, {
4098
- defaultValue: 'July',
4099
- }),
4100
- formI18n.translate.t(`common.month_8`, {
4101
- defaultValue: 'August',
4102
- }),
4103
- formI18n.translate.t(`common.month_9`, {
4104
- defaultValue: 'September',
4105
- }),
4106
- formI18n.translate.t(`common.month_10`, {
4107
- defaultValue: 'October',
4108
- }),
4109
- formI18n.translate.t(`common.month_11`, {
4110
- defaultValue: 'November',
4111
- }),
4112
- formI18n.translate.t(`common.month_12`, {
4113
- defaultValue: 'December',
4114
- }),
4115
- ],
4116
- weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4117
- formI18n.translate.t(`common.weekday_1`, {
4118
- defaultValue: 'Sun',
4119
- }),
4120
- formI18n.translate.t(`common.weekday_2`, {
4121
- defaultValue: 'Mon',
4122
- }),
4123
- formI18n.translate.t(`common.weekday_3`, {
4124
- defaultValue: 'Tue',
4125
- }),
4126
- formI18n.translate.t(`common.weekday_4`, {
4127
- defaultValue: 'Wed',
4128
- }),
4129
- formI18n.translate.t(`common.weekday_5`, {
4130
- defaultValue: 'Thu',
4131
- }),
4132
- formI18n.translate.t(`common.weekday_6`, {
4133
- defaultValue: 'Fri',
4134
- }),
4135
- formI18n.translate.t(`common.weekday_7`, {
4136
- defaultValue: 'Sat',
4137
- }),
4138
- ],
4139
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4140
- formI18n.translate.t(`common.back_button`, {
4141
- defaultValue: 'Back',
4142
- }),
4143
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4144
- formI18n.translate.t(`common.forward_button`, {
4145
- defaultValue: 'Forward',
4146
- }),
4147
- } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
4294
+ return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4295
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], 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: () => {
4296
+ setOpen(true);
4297
+ }, 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 }) => {
4298
+ setValue(colLabel, dayjs(date).format(dateFormat));
4299
+ setOpen(false);
4300
+ }, labels: {
4301
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4302
+ formI18n.translate.t(`common.month_1`, {
4303
+ defaultValue: 'January',
4304
+ }),
4305
+ formI18n.translate.t(`common.month_2`, {
4306
+ defaultValue: 'February',
4307
+ }),
4308
+ formI18n.translate.t(`common.month_3`, {
4309
+ defaultValue: 'March',
4310
+ }),
4311
+ formI18n.translate.t(`common.month_4`, {
4312
+ defaultValue: 'April',
4313
+ }),
4314
+ formI18n.translate.t(`common.month_5`, {
4315
+ defaultValue: 'May',
4316
+ }),
4317
+ formI18n.translate.t(`common.month_6`, {
4318
+ defaultValue: 'June',
4319
+ }),
4320
+ formI18n.translate.t(`common.month_7`, {
4321
+ defaultValue: 'July',
4322
+ }),
4323
+ formI18n.translate.t(`common.month_8`, {
4324
+ defaultValue: 'August',
4325
+ }),
4326
+ formI18n.translate.t(`common.month_9`, {
4327
+ defaultValue: 'September',
4328
+ }),
4329
+ formI18n.translate.t(`common.month_10`, {
4330
+ defaultValue: 'October',
4331
+ }),
4332
+ formI18n.translate.t(`common.month_11`, {
4333
+ defaultValue: 'November',
4334
+ }),
4335
+ formI18n.translate.t(`common.month_12`, {
4336
+ defaultValue: 'December',
4337
+ }),
4338
+ ],
4339
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4340
+ formI18n.translate.t(`common.weekday_1`, {
4341
+ defaultValue: 'Sun',
4342
+ }),
4343
+ formI18n.translate.t(`common.weekday_2`, {
4344
+ defaultValue: 'Mon',
4345
+ }),
4346
+ formI18n.translate.t(`common.weekday_3`, {
4347
+ defaultValue: 'Tue',
4348
+ }),
4349
+ formI18n.translate.t(`common.weekday_4`, {
4350
+ defaultValue: 'Wed',
4351
+ }),
4352
+ formI18n.translate.t(`common.weekday_5`, {
4353
+ defaultValue: 'Thu',
4354
+ }),
4355
+ formI18n.translate.t(`common.weekday_6`, {
4356
+ defaultValue: 'Fri',
4357
+ }),
4358
+ formI18n.translate.t(`common.weekday_7`, {
4359
+ defaultValue: 'Sat',
4360
+ }),
4361
+ ],
4362
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4363
+ formI18n.translate.t(`common.back_button`, {
4364
+ defaultValue: 'Back',
4365
+ }),
4366
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4367
+ formI18n.translate.t(`common.forward_button`, {
4368
+ defaultValue: 'Forward',
4369
+ }),
4370
+ } })] }) })] }) }));
4148
4371
  };
4149
4372
 
4150
4373
  function filterArray(array, searchTerm) {
@@ -4179,7 +4402,9 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4179
4402
  };
4180
4403
  if (variant === 'radio') {
4181
4404
  return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4182
- gridRow, children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
4405
+ gridRow, errorText: errors[`${colLabel}`]
4406
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
4407
+ : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
4183
4408
  return (jsxRuntime.jsxs(react.RadioGroup.Item, { onClick: () => {
4184
4409
  if (!isMultiple) {
4185
4410
  setOpenSearchResult(false);
@@ -4194,7 +4419,9 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4194
4419
  }) }) }) }));
4195
4420
  }
4196
4421
  return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4197
- gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
4422
+ gridRow, errorText: errors[`${colLabel}`]
4423
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
4424
+ : undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
4198
4425
  const item = enumValue;
4199
4426
  if (!!item === false) {
4200
4427
  return jsxRuntime.jsx(jsxRuntime.Fragment, {});
@@ -4249,7 +4476,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4249
4476
  ? renderDisplay(item)
4250
4477
  : translate.t(removeIndex(`${colLabel}.${item}`)) }, `${colLabel}-${item}`));
4251
4478
  }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: enumPickerLabels?.emptySearchResult ??
4252
- translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4479
+ translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] })] }));
4253
4480
  };
4254
4481
 
4255
4482
  function isEnteringWindow(_ref) {
@@ -4607,20 +4834,22 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
4607
4834
  const FilePicker = ({ column, schema, prefix }) => {
4608
4835
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4609
4836
  const { translate } = useSchemaContext();
4610
- const { required, gridColumn = "span 12", gridRow = "span 1", } = schema;
4837
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
4611
4838
  const isRequired = required?.some((columnId) => columnId === column);
4612
4839
  const currentFiles = (watch(column) ?? []);
4613
4840
  const colLabel = `${prefix}${column}`;
4614
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4841
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: 'grid', gridTemplateRows: 'auto 1fr auto', alignItems: 'stretch', errorText: errors[`${colLabel}`]
4842
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
4843
+ : undefined, invalid: !!errors[colLabel], children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4615
4844
  const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4616
4845
  setValue(colLabel, [...currentFiles, ...newFiles]);
4617
- }, placeholder: translate.t(removeIndex(`${colLabel}.fileDropzone`)) }), jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
4618
- return (jsxRuntime.jsx(react.Card.Root, { variant: "subtle", children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", cursor: "pointer", onClick: () => {
4846
+ }, placeholder: translate.t(removeIndex(`${colLabel}.fileDropzone`)) }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file) => {
4847
+ return (jsxRuntime.jsx(react.Card.Root, { variant: 'subtle', children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", cursor: 'pointer', onClick: () => {
4619
4848
  setValue(column, currentFiles.filter(({ name }) => {
4620
4849
  return name !== file.name;
4621
4850
  }));
4622
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [file.type.startsWith("image/") && (jsxRuntime.jsx(react.Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
4623
- }) }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4851
+ }, display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', children: [file.type.startsWith('image/') && (jsxRuntime.jsx(react.Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
4852
+ }) })] }));
4624
4853
  };
4625
4854
 
4626
4855
  const ToggleTip = React__namespace.forwardRef(function ToggleTip(props, ref) {
@@ -4809,7 +5038,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4809
5038
  return record[display_column];
4810
5039
  };
4811
5040
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4812
- gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchIds.map((id) => {
5041
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchIds.map((id) => {
4813
5042
  const item = idMap[id];
4814
5043
  if (item === undefined) {
4815
5044
  return (jsxRuntime.jsx(react.Text, { children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
@@ -4860,7 +5089,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4860
5089
  ? idPickerLabels?.emptySearchResult ??
4861
5090
  formI18n.t('empty_search_result')
4862
5091
  : idPickerLabels?.initialResults ??
4863
- formI18n.t('initial_results') })) }), jsxRuntime.jsx(PaginationRoot, { justifySelf: 'center', count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxRuntime.jsxs(react.HStack, { gap: "4", children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), count > 0 && jsxRuntime.jsx(PaginationPageText, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
5092
+ formI18n.t('initial_results') })) }), jsxRuntime.jsx(PaginationRoot, { justifySelf: 'center', count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxRuntime.jsxs(react.HStack, { gap: "4", children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), count > 0 && jsxRuntime.jsx(PaginationPageText, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) })] }))] }) })] })] }));
4864
5093
  };
4865
5094
 
4866
5095
  const NumberInputRoot = React__namespace.forwardRef(function NumberInput(props, ref) {
@@ -4871,20 +5100,84 @@ const NumberInputField$1 = react.NumberInput.Input;
4871
5100
  react.NumberInput.Scrubber;
4872
5101
  react.NumberInput.Label;
4873
5102
 
5103
+ /**
5104
+ * Gets the error message for a specific field from react-hook-form errors
5105
+ * Prioritizes required errors (#.required) over field-specific validation errors
5106
+ */
5107
+ const getFieldError = (errors, fieldName) => {
5108
+ // Check for form-level required errors first (highest priority)
5109
+ const requiredError = errors['#.required'];
5110
+ if (requiredError) {
5111
+ const requiredErrorMessage = extractErrorMessage(requiredError);
5112
+ if (requiredErrorMessage) {
5113
+ return requiredErrorMessage;
5114
+ }
5115
+ }
5116
+ // If no required errors, return field-specific error
5117
+ const fieldError = errors[fieldName];
5118
+ if (fieldError) {
5119
+ const fieldErrorMessage = extractErrorMessage(fieldError);
5120
+ if (fieldErrorMessage) {
5121
+ return fieldErrorMessage;
5122
+ }
5123
+ }
5124
+ return undefined;
5125
+ };
5126
+ /**
5127
+ * Helper function to extract error message from various error formats
5128
+ * Only returns message if explicitly provided, no fallback text
5129
+ */
5130
+ const extractErrorMessage = (error) => {
5131
+ if (!error) {
5132
+ return undefined;
5133
+ }
5134
+ // If it's a simple string error
5135
+ if (typeof error === 'string') {
5136
+ return error;
5137
+ }
5138
+ // If it's an error object with a message property
5139
+ if (error && typeof error === 'object' && 'message' in error) {
5140
+ return error.message;
5141
+ }
5142
+ // If it's an array of errors, get the first one
5143
+ if (Array.isArray(error) && error.length > 0) {
5144
+ const firstError = error[0];
5145
+ if (typeof firstError === 'string') {
5146
+ return firstError;
5147
+ }
5148
+ if (firstError &&
5149
+ typeof firstError === 'object' &&
5150
+ 'message' in firstError) {
5151
+ return firstError.message;
5152
+ }
5153
+ }
5154
+ // No fallback - return undefined if no message provided
5155
+ return undefined;
5156
+ };
5157
+
4874
5158
  const NumberInputField = ({ schema, column, prefix, }) => {
4875
5159
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4876
5160
  const { translate } = useSchemaContext();
4877
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5161
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', numberStorageType = 'number', } = schema;
4878
5162
  const isRequired = required?.some((columnId) => columnId === column);
4879
5163
  const colLabel = `${prefix}${column}`;
4880
5164
  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`)) }))] }));
5165
+ const fieldError = getFieldError(errors, colLabel);
5166
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, errorText: fieldError
5167
+ ? fieldError.includes('required')
5168
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
5169
+ : fieldError
5170
+ : undefined, invalid: !!fieldError, children: jsxRuntime.jsx(NumberInputRoot, { value: value, onValueChange: (details) => {
5171
+ // Store as string or number based on configuration, default to number
5172
+ const value = numberStorageType === 'string'
5173
+ ? details.value
5174
+ : details.valueAsNumber;
5175
+ setValue(`${colLabel}`, value);
5176
+ }, 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 }) }) }));
4884
5177
  };
4885
5178
 
4886
5179
  const ObjectInput = ({ schema, column, prefix }) => {
4887
- const { properties, gridColumn = "span 12", gridRow = "span 1", required, showLabel = true, } = schema;
5180
+ const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
4888
5181
  const { translate } = useSchemaContext();
4889
5182
  const colLabel = `${prefix}${column}`;
4890
5183
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4892,29 +5185,32 @@ const ObjectInput = ({ schema, column, prefix }) => {
4892
5185
  if (properties === undefined) {
4893
5186
  throw new Error(`properties is undefined when using ObjectInput`);
4894
5187
  }
4895
- return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [showLabel && (jsxRuntime.jsxs(react.Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] })), jsxRuntime.jsx(react.Grid, { bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
4896
- base: "colorPalette.200",
4897
- _dark: "colorPalette.800",
4898
- }, gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: Object.keys(properties ?? {}).map((key) => {
5188
+ return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [showLabel && (jsxRuntime.jsxs(react.Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsxRuntime.jsx("span", { children: "*" })] })), jsxRuntime.jsx(react.Grid, { bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
5189
+ base: 'colorPalette.200',
5190
+ _dark: 'colorPalette.800',
5191
+ }, gap: "4", padding: '4', gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: Object.keys(properties ?? {}).map((key) => {
4899
5192
  return (
4900
5193
  // @ts-expect-error find suitable types
4901
5194
  jsxRuntime.jsx(ColumnRenderer, { column: `${key}`,
4902
5195
  prefix: `${prefix}${column}.`,
4903
- properties }, `form-${colLabel}-${key}`));
4904
- }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5196
+ properties,
5197
+ parentRequired: required }, `form-${colLabel}-${key}`));
5198
+ }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4905
5199
  };
4906
5200
 
4907
5201
  const RecordInput$1 = ({ column, schema, prefix }) => {
4908
5202
  const { formState: { errors }, setValue, getValues, } = reactHookForm.useFormContext();
4909
5203
  const { translate } = useSchemaContext();
4910
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5204
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
4911
5205
  const isRequired = required?.some((columnId) => columnId === column);
4912
5206
  const entries = Object.entries(getValues(column) ?? {});
4913
5207
  const [showNewEntries, setShowNewEntries] = React.useState(false);
4914
5208
  const [newKey, setNewKey] = React.useState();
4915
5209
  const [newValue, setNewValue] = React.useState();
4916
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
4917
- return (jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
5210
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: errors[`${column}`]
5211
+ ? translate.t(`${column}.field_required`)
5212
+ : undefined, invalid: !!errors[column], children: [entries.map(([key, value]) => {
5213
+ return (jsxRuntime.jsxs(react.Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
4918
5214
  const filtered = entries.filter(([target]) => {
4919
5215
  return target !== key;
4920
5216
  });
@@ -4924,17 +5220,17 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
4924
5220
  ...getValues(column),
4925
5221
  [key]: e.target.value,
4926
5222
  });
4927
- }, autoComplete: "off" }), jsxRuntime.jsx(react.IconButton, { variant: "ghost", onClick: () => {
5223
+ }, autoComplete: "off" }), jsxRuntime.jsx(react.IconButton, { variant: 'ghost', onClick: () => {
4928
5224
  const filtered = entries.filter(([target]) => {
4929
5225
  return target !== key;
4930
5226
  });
4931
5227
  setValue(column, Object.fromEntries([...filtered]));
4932
5228
  }, children: jsxRuntime.jsx(cg.CgClose, {}) })] }));
4933
- }), jsxRuntime.jsx(react.Show, { when: showNewEntries, children: jsxRuntime.jsxs(react.Card.Root, { children: [jsxRuntime.jsx(react.Card.Body, { gap: "2", children: jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsxRuntime.jsx(react.Input, { value: newKey, onChange: (e) => {
5229
+ }), jsxRuntime.jsx(react.Show, { when: showNewEntries, children: jsxRuntime.jsxs(react.Card.Root, { children: [jsxRuntime.jsx(react.Card.Body, { gap: "2", children: jsxRuntime.jsxs(react.Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsxRuntime.jsx(react.Input, { value: newKey, onChange: (e) => {
4934
5230
  setNewKey(e.target.value);
4935
5231
  }, autoComplete: "off" }), jsxRuntime.jsx(react.Input, { value: newValue, onChange: (e) => {
4936
5232
  setNewValue(e.target.value);
4937
- }, autoComplete: "off" })] }) }), jsxRuntime.jsxs(react.Card.Footer, { justifyContent: "flex-end", children: [jsxRuntime.jsx(react.IconButton, { variant: "subtle", onClick: () => {
5233
+ }, autoComplete: "off" })] }) }), jsxRuntime.jsxs(react.Card.Footer, { justifyContent: "flex-end", children: [jsxRuntime.jsx(react.IconButton, { variant: 'subtle', onClick: () => {
4938
5234
  setShowNewEntries(false);
4939
5235
  setNewKey(undefined);
4940
5236
  setNewValue(undefined);
@@ -4953,16 +5249,17 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
4953
5249
  setShowNewEntries(true);
4954
5250
  setNewKey(undefined);
4955
5251
  setNewValue(undefined);
4956
- }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
5252
+ }, children: translate.t(`${column}.addNew`) })] }));
4957
5253
  };
4958
5254
 
4959
5255
  const StringInputField = ({ column, schema, prefix, }) => {
4960
5256
  const { register, formState: { errors }, } = reactHookForm.useFormContext();
4961
5257
  const { translate } = useSchemaContext();
4962
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5258
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
4963
5259
  const isRequired = required?.some((columnId) => columnId === column);
4964
5260
  const colLabel = `${prefix}${column}`;
4965
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsxRuntime.jsx(react.Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5261
+ const fieldError = getFieldError(errors, colLabel);
5262
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: fieldError, invalid: !!fieldError, children: jsxRuntime.jsx(react.Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
4966
5263
  };
4967
5264
 
4968
5265
  const RadioCardItem = React__namespace.forwardRef(function RadioCardItem(props, ref) {
@@ -5148,13 +5445,18 @@ Textarea.displayName = "Textarea";
5148
5445
  const TextAreaInput = ({ column, schema, prefix, }) => {
5149
5446
  const { register, formState: { errors }, } = reactHookForm.useFormContext();
5150
5447
  const { translate } = useSchemaContext();
5151
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5448
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5152
5449
  const isRequired = required?.some((columnId) => columnId === column);
5153
5450
  const colLabel = `${prefix}${column}`;
5154
5451
  const form = reactHookForm.useFormContext();
5155
5452
  const { setValue, watch } = form;
5453
+ const fieldError = getFieldError(errors, colLabel);
5156
5454
  const watchValue = watch(colLabel);
5157
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", children: [jsxRuntime.jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5455
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
5456
+ ? fieldError.includes('required')
5457
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
5458
+ : fieldError
5459
+ : undefined, invalid: !!fieldError, children: jsxRuntime.jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
5158
5460
  };
5159
5461
 
5160
5462
  function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
@@ -5285,25 +5587,25 @@ dayjs.extend(timezone);
5285
5587
  const TimePicker = ({ column, schema, prefix }) => {
5286
5588
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5287
5589
  const { translate, timezone } = useSchemaContext();
5288
- const { required, gridColumn = "span 12", gridRow = "span 1", timeFormat = "HH:mm:ssZ", displayTimeFormat = "hh:mm A", } = schema;
5590
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
5289
5591
  const isRequired = required?.some((columnId) => columnId === column);
5290
5592
  const colLabel = `${prefix}${column}`;
5291
5593
  const [open, setOpen] = React.useState(false);
5292
5594
  const value = watch(colLabel);
5293
5595
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
5294
5596
  ? dayjs(`1970-01-01T${value}`).tz(timezone).format(displayTimeFormat)
5295
- : "";
5597
+ : '';
5296
5598
  // Parse the initial time parts from the time string (HH:mm:ssZ)
5297
5599
  const parseTime = (time) => {
5298
5600
  if (!time)
5299
- return { hour: 12, minute: 0, meridiem: "am" };
5601
+ return { hour: 12, minute: 0, meridiem: 'am' };
5300
5602
  const parsed = dayjs(`1970-01-01T${time}`).tz(timezone);
5301
5603
  if (!parsed.isValid()) {
5302
- return { hour: 12, minute: 0, meridiem: "am" };
5604
+ return { hour: 12, minute: 0, meridiem: 'am' };
5303
5605
  }
5304
5606
  let hour = parsed.hour();
5305
5607
  const minute = parsed.minute();
5306
- const meridiem = hour >= 12 ? "pm" : "am";
5608
+ const meridiem = hour >= 12 ? 'pm' : 'am';
5307
5609
  if (hour === 0)
5308
5610
  hour = 12;
5309
5611
  else if (hour > 12)
@@ -5324,10 +5626,15 @@ const TimePicker = ({ column, schema, prefix }) => {
5324
5626
  if (hour === null || minute === null || meridiem === null)
5325
5627
  return null;
5326
5628
  let newHour = hour;
5327
- if (meridiem === "pm" && hour !== 12) {
5629
+ if (meridiem === 'pm' && hour !== 12) {
5328
5630
  newHour = hour + 12;
5329
5631
  }
5330
- return dayjs().tz(timezone).hour(newHour).minute(minute).second(0).format(timeFormat);
5632
+ return dayjs()
5633
+ .tz(timezone)
5634
+ .hour(newHour)
5635
+ .minute(minute)
5636
+ .second(0)
5637
+ .format(timeFormat);
5331
5638
  };
5332
5639
  // Handle changes to time parts
5333
5640
  const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
@@ -5337,13 +5644,15 @@ const TimePicker = ({ column, schema, prefix }) => {
5337
5644
  const timeString = getTimeString(newHour, newMinute, newMeridiem);
5338
5645
  setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
5339
5646
  };
5340
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5341
- gridRow, children: [jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5342
- setOpen(true);
5343
- }, justifyContent: "start", children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ""] }) }), jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5344
- am: translate.t(`common.am`, { defaultValue: "AM" }),
5345
- pm: translate.t(`common.pm`, { defaultValue: "PM" }),
5346
- } }) }) }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5647
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
5648
+ gridRow, errorText: errors[`${colLabel}`]
5649
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
5650
+ : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5651
+ setOpen(true);
5652
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5653
+ am: translate.t(`common.am`, { defaultValue: 'AM' }),
5654
+ pm: translate.t(`common.pm`, { defaultValue: 'PM' }),
5655
+ } }) }) }) })] }) }));
5347
5656
  };
5348
5657
 
5349
5658
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond, onChange = (_newValue) => { }, }) {
@@ -5549,9 +5858,9 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
5549
5858
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5550
5859
  const { timezone, dateTimePickerLabels } = useSchemaContext();
5551
5860
  const formI18n = useFormI18n(column, prefix);
5552
- const { required, gridColumn = "span 12", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss",
5861
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
5553
5862
  // with timezone
5554
- dateFormat = "YYYY-MM-DD[T]HH:mm:ssZ", } = schema;
5863
+ dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
5555
5864
  const isRequired = required?.some((columnId) => columnId === column);
5556
5865
  const colLabel = formI18n.colLabel;
5557
5866
  const [open, setOpen] = React.useState(false);
@@ -5582,44 +5891,82 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
5582
5891
  console.error(e);
5583
5892
  }
5584
5893
  }, [selectedDate, dateFormat, colLabel, setValue]);
5585
- return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
5586
- 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: () => {
5587
- setOpen(true);
5588
- }, justifyContent: "start", children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsxRuntime.jsx(PopoverContent, { minW: "450px", children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
5589
- setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
5590
- }, timezone: timezone, labels: {
5591
- monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
5592
- formI18n.translate.t(`common.month_1`, { defaultValue: "January" }),
5593
- formI18n.translate.t(`common.month_2`, { defaultValue: "February" }),
5594
- formI18n.translate.t(`common.month_3`, { defaultValue: "March" }),
5595
- formI18n.translate.t(`common.month_4`, { defaultValue: "April" }),
5596
- formI18n.translate.t(`common.month_5`, { defaultValue: "May" }),
5597
- formI18n.translate.t(`common.month_6`, { defaultValue: "June" }),
5598
- formI18n.translate.t(`common.month_7`, { defaultValue: "July" }),
5599
- formI18n.translate.t(`common.month_8`, { defaultValue: "August" }),
5600
- formI18n.translate.t(`common.month_9`, { defaultValue: "September" }),
5601
- formI18n.translate.t(`common.month_10`, { defaultValue: "October" }),
5602
- formI18n.translate.t(`common.month_11`, { defaultValue: "November" }),
5603
- formI18n.translate.t(`common.month_12`, { defaultValue: "December" }),
5604
- ],
5605
- weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
5606
- formI18n.translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
5607
- formI18n.translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
5608
- formI18n.translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
5609
- formI18n.translate.t(`common.weekday_4`, {
5610
- defaultValue: "Wed",
5611
- }),
5612
- formI18n.translate.t(`common.weekday_5`, { defaultValue: "Thu" }),
5613
- formI18n.translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
5614
- formI18n.translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
5615
- ],
5616
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? formI18n.translate.t(`common.back_button`, {
5617
- defaultValue: "Back",
5894
+ return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5895
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], 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: () => {
5896
+ setOpen(true);
5897
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsxRuntime.jsx(PopoverContent, { minW: '450px', children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
5898
+ setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
5899
+ }, timezone: timezone, labels: {
5900
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
5901
+ formI18n.translate.t(`common.month_1`, {
5902
+ defaultValue: 'January',
5903
+ }),
5904
+ formI18n.translate.t(`common.month_2`, {
5905
+ defaultValue: 'February',
5906
+ }),
5907
+ formI18n.translate.t(`common.month_3`, {
5908
+ defaultValue: 'March',
5909
+ }),
5910
+ formI18n.translate.t(`common.month_4`, {
5911
+ defaultValue: 'April',
5912
+ }),
5913
+ formI18n.translate.t(`common.month_5`, {
5914
+ defaultValue: 'May',
5915
+ }),
5916
+ formI18n.translate.t(`common.month_6`, {
5917
+ defaultValue: 'June',
5918
+ }),
5919
+ formI18n.translate.t(`common.month_7`, {
5920
+ defaultValue: 'July',
5921
+ }),
5922
+ formI18n.translate.t(`common.month_8`, {
5923
+ defaultValue: 'August',
5924
+ }),
5925
+ formI18n.translate.t(`common.month_9`, {
5926
+ defaultValue: 'September',
5618
5927
  }),
5619
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? formI18n.translate.t(`common.forward_button`, {
5620
- defaultValue: "Forward",
5928
+ formI18n.translate.t(`common.month_10`, {
5929
+ defaultValue: 'October',
5621
5930
  }),
5622
- } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
5931
+ formI18n.translate.t(`common.month_11`, {
5932
+ defaultValue: 'November',
5933
+ }),
5934
+ formI18n.translate.t(`common.month_12`, {
5935
+ defaultValue: 'December',
5936
+ }),
5937
+ ],
5938
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
5939
+ formI18n.translate.t(`common.weekday_1`, {
5940
+ defaultValue: 'Sun',
5941
+ }),
5942
+ formI18n.translate.t(`common.weekday_2`, {
5943
+ defaultValue: 'Mon',
5944
+ }),
5945
+ formI18n.translate.t(`common.weekday_3`, {
5946
+ defaultValue: 'Tue',
5947
+ }),
5948
+ formI18n.translate.t(`common.weekday_4`, {
5949
+ defaultValue: 'Wed',
5950
+ }),
5951
+ formI18n.translate.t(`common.weekday_5`, {
5952
+ defaultValue: 'Thu',
5953
+ }),
5954
+ formI18n.translate.t(`common.weekday_6`, {
5955
+ defaultValue: 'Fri',
5956
+ }),
5957
+ formI18n.translate.t(`common.weekday_7`, {
5958
+ defaultValue: 'Sat',
5959
+ }),
5960
+ ],
5961
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
5962
+ formI18n.translate.t(`common.back_button`, {
5963
+ defaultValue: 'Back',
5964
+ }),
5965
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
5966
+ formI18n.translate.t(`common.forward_button`, {
5967
+ defaultValue: 'Forward',
5968
+ }),
5969
+ } })] }) })] }) }));
5623
5970
  };
5624
5971
 
5625
5972
  const SchemaRenderer = ({ schema, prefix, column, }) => {
@@ -5693,13 +6040,18 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
5693
6040
  return jsxRuntime.jsx(react.Text, { children: "missing type" });
5694
6041
  };
5695
6042
 
5696
- const ColumnRenderer = ({ column, properties, prefix, }) => {
6043
+ const ColumnRenderer = ({ column, properties, prefix, parentRequired, }) => {
5697
6044
  const colSchema = properties[column];
5698
6045
  const colLabel = `${prefix}${column}`;
5699
6046
  if (colSchema === undefined) {
5700
6047
  throw new Error(`${colLabel} does not exist when using ColumnRenderer`);
5701
6048
  }
5702
- return jsxRuntime.jsx(SchemaRenderer, { schema: colSchema, prefix, column });
6049
+ // Merge parent's required array with the schema's required array
6050
+ const schemaWithRequired = {
6051
+ ...colSchema,
6052
+ required: parentRequired || colSchema.required,
6053
+ };
6054
+ return jsxRuntime.jsx(SchemaRenderer, { schema: schemaWithRequired, prefix, column });
5703
6055
  };
5704
6056
 
5705
6057
  const ArrayViewer = ({ schema, column, prefix }) => {
@@ -5822,11 +6174,29 @@ const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
5822
6174
  const NumberViewer = ({ schema, column, prefix, }) => {
5823
6175
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
5824
6176
  const { translate } = useSchemaContext();
5825
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
6177
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5826
6178
  const isRequired = required?.some((columnId) => columnId === column);
5827
6179
  const colLabel = `${prefix}${column}`;
5828
6180
  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`)) }))] }));
6181
+ // Format the value for display if formatOptions are provided
6182
+ const formatValue = (val) => {
6183
+ if (val === undefined || val === null || val === '')
6184
+ return '';
6185
+ const numValue = typeof val === 'string' ? parseFloat(val) : val;
6186
+ if (isNaN(numValue))
6187
+ return String(val);
6188
+ // Use formatOptions if available, otherwise display as-is
6189
+ if (schema.formatOptions) {
6190
+ try {
6191
+ return new Intl.NumberFormat(undefined, schema.formatOptions).format(numValue);
6192
+ }
6193
+ catch {
6194
+ return String(val);
6195
+ }
6196
+ }
6197
+ return String(val);
6198
+ };
6199
+ 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
6200
  };
5831
6201
 
5832
6202
  const ObjectViewer = ({ schema, column, prefix }) => {
@@ -6118,113 +6488,43 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
6118
6488
  };
6119
6489
 
6120
6490
  const SubmitButton = () => {
6121
- const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, } = useSchemaContext();
6491
+ const { translate, setValidatedData, setIsError, setIsConfirming, setError, schema, requireConfirmation, onFormSubmit, } = useSchemaContext();
6122
6492
  const methods = reactHookForm.useFormContext();
6123
6493
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6124
6494
  const onValid = (data) => {
6125
- const { isValid, errors } = validateData(data, schema);
6126
- if (!isValid) {
6127
- setError({
6128
- type: "validation",
6129
- errors,
6130
- });
6131
- setIsError(true);
6132
- return;
6495
+ // const { isValid, errors } = validateData(data, schema);
6496
+ // if (!isValid) {
6497
+ // setError({
6498
+ // type: 'validation',
6499
+ // errors,
6500
+ // });
6501
+ // setIsError(true);
6502
+ // return;
6503
+ // }
6504
+ // If validation passes, check if confirmation is required
6505
+ if (requireConfirmation) {
6506
+ // Show confirmation (existing behavior)
6507
+ setValidatedData(data);
6508
+ setIsError(false);
6509
+ setIsConfirming(true);
6510
+ }
6511
+ else {
6512
+ // Skip confirmation and submit directly
6513
+ setValidatedData(data);
6514
+ setIsError(false);
6515
+ onFormSubmit(data);
6133
6516
  }
6134
- // If validation passes, proceed to confirmation
6135
- setValidatedData(data);
6136
- setIsError(false);
6137
- setIsConfirming(true);
6138
6517
  };
6139
6518
  return (jsxRuntime.jsx(react.Button, { onClick: () => {
6140
6519
  methods.handleSubmit(onValid)();
6141
- }, formNoValidate: true, children: translate.t("submit") }));
6520
+ }, formNoValidate: true, children: translate.t('submit') }));
6142
6521
  };
6143
6522
 
6144
6523
  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();
6524
+ const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, } = useSchemaContext();
6146
6525
  const { showSubmitButton, showResetButton } = displayConfig;
6147
6526
  const methods = reactHookForm.useFormContext();
6148
6527
  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
- // Custom error renderer for validation errors with i18n support
6225
- 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))) }));
6227
- };
6228
6528
  const renderColumns = ({ order, keys, ignore, include, }) => {
6229
6529
  const included = include.length > 0 ? include : keys;
6230
6530
  const not_exist = included.filter((columnA) => !order.some((columnB) => columnA === columnB));
@@ -6251,32 +6551,30 @@ const FormBody = () => {
6251
6551
  if (customSuccessRenderer) {
6252
6552
  return customSuccessRenderer(resetHandler);
6253
6553
  }
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") }) })] }));
6554
+ 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
6555
  }
6256
6556
  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) => {
6557
+ 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
6558
  return (jsxRuntime.jsx(ColumnViewer
6259
6559
  // @ts-expect-error find suitable types
6260
6560
  , {
6261
6561
  // @ts-expect-error find suitable types
6262
6562
  properties: properties, prefix: ``, column }, `form-viewer-${column}`));
6263
- }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [jsxRuntime.jsx(react.Button, { onClick: () => {
6563
+ }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: '2', children: [jsxRuntime.jsx(react.Button, { onClick: () => {
6264
6564
  setIsConfirming(false);
6265
- }, variant: "subtle", children: translate.t("cancel") }), jsxRuntime.jsx(react.Button, { onClick: () => {
6565
+ }, variant: 'subtle', children: translate.t('cancel') }), jsxRuntime.jsx(react.Button, { onClick: () => {
6266
6566
  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)}` })] }) }) })] })] })) })) }))] }));
6567
+ }, 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 && customErrorRenderer && customErrorRenderer(error)] }));
6269
6568
  }
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) => {
6569
+ 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
6570
  return (jsxRuntime.jsx(ColumnRenderer
6272
6571
  // @ts-expect-error find suitable types
6273
6572
  , {
6274
6573
  // @ts-expect-error find suitable types
6275
- properties: properties, prefix: ``, column }, `form-input-${column}`));
6276
- }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
6574
+ properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
6575
+ }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
6277
6576
  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)}` })] }) }) })] })] })) })) }))] }));
6577
+ }, variant: 'subtle', children: translate.t('reset') })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
6280
6578
  };
6281
6579
 
6282
6580
  const FormTitle = () => {
@@ -6289,12 +6587,15 @@ const DefaultForm = ({ formConfig, }) => {
6289
6587
  return (jsxRuntime.jsx(FormRoot, { ...formConfig, children: jsxRuntime.jsxs(react.Grid, { gap: "2", children: [showTitle && jsxRuntime.jsx(FormTitle, {}), jsxRuntime.jsx(FormBody, {})] }) }));
6290
6588
  };
6291
6589
 
6292
- const useForm = ({ preLoadedValues, keyPrefix, namespace }) => {
6590
+ const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
6293
6591
  const form = reactHookForm.useForm({
6294
6592
  values: preLoadedValues,
6593
+ resolver: schema ? ajvResolver(schema) : undefined,
6594
+ mode: 'onBlur',
6595
+ reValidateMode: 'onBlur',
6295
6596
  });
6296
6597
  const [idMap, setIdMap] = React.useState({});
6297
- const translate = reactI18next.useTranslation(namespace || "", { keyPrefix });
6598
+ const translate = reactI18next.useTranslation(namespace || '', { keyPrefix });
6298
6599
  return {
6299
6600
  form,
6300
6601
  idMap,
@@ -6364,15 +6665,15 @@ const buildErrorMessages = (config) => {
6364
6665
  }
6365
6666
  // Add global fallback error messages
6366
6667
  const globalKeys = [
6367
- "minLength",
6368
- "maxLength",
6369
- "pattern",
6370
- "minimum",
6371
- "maximum",
6372
- "multipleOf",
6373
- "format",
6374
- "type",
6375
- "enum",
6668
+ 'minLength',
6669
+ 'maxLength',
6670
+ 'pattern',
6671
+ 'minimum',
6672
+ 'maximum',
6673
+ 'multipleOf',
6674
+ 'format',
6675
+ 'type',
6676
+ 'enum',
6376
6677
  ];
6377
6678
  globalKeys.forEach((key) => {
6378
6679
  if (config[key]) {
@@ -6381,6 +6682,46 @@ const buildErrorMessages = (config) => {
6381
6682
  });
6382
6683
  return result;
6383
6684
  };
6685
+ /**
6686
+ * Converts buildErrorMessages result to ajv-errors compatible format
6687
+ */
6688
+ const convertToAjvErrorsFormat = (errorMessages) => {
6689
+ const result = {};
6690
+ // Convert required field errors
6691
+ if (errorMessages.required) {
6692
+ result.required = errorMessages.required;
6693
+ }
6694
+ // Convert properties errors to ajv-errors format
6695
+ if (errorMessages.properties) {
6696
+ result.properties = {};
6697
+ Object.keys(errorMessages.properties).forEach((fieldName) => {
6698
+ const fieldErrors = errorMessages.properties[fieldName];
6699
+ result.properties[fieldName] = {};
6700
+ Object.keys(fieldErrors).forEach((keyword) => {
6701
+ result.properties[fieldName][keyword] =
6702
+ fieldErrors[keyword];
6703
+ });
6704
+ });
6705
+ }
6706
+ // Add global fallback errors
6707
+ const globalKeys = [
6708
+ 'minLength',
6709
+ 'maxLength',
6710
+ 'pattern',
6711
+ 'minimum',
6712
+ 'maximum',
6713
+ 'multipleOf',
6714
+ 'format',
6715
+ 'type',
6716
+ 'enum',
6717
+ ];
6718
+ globalKeys.forEach((key) => {
6719
+ if (errorMessages[key]) {
6720
+ result[key] = errorMessages[key];
6721
+ }
6722
+ });
6723
+ return result;
6724
+ };
6384
6725
  /**
6385
6726
  * Helper function to build required field errors
6386
6727
  *
@@ -6423,10 +6764,10 @@ const buildErrorMessages = (config) => {
6423
6764
  * // Result: { username: "user.username.field_required", email: "user.email.field_required" }
6424
6765
  * ```
6425
6766
  */
6426
- const buildRequiredErrors = (fields, messageOrGenerator, keyPrefix = "") => {
6767
+ const buildRequiredErrors = (fields, messageOrGenerator, keyPrefix = '') => {
6427
6768
  const result = {};
6428
6769
  fields.forEach((field) => {
6429
- if (typeof messageOrGenerator === "function") {
6770
+ if (typeof messageOrGenerator === 'function') {
6430
6771
  const message = messageOrGenerator(field);
6431
6772
  result[field] = keyPrefix ? `${keyPrefix}.${message}` : message;
6432
6773
  }
@@ -6497,11 +6838,14 @@ const buildFieldErrors = (config) => {
6497
6838
  * ```
6498
6839
  */
6499
6840
  const createErrorMessage = (required, properties, globalFallbacks) => {
6500
- return buildErrorMessages({
6841
+ const config = {
6501
6842
  required,
6502
6843
  properties,
6503
- ...globalFallbacks,
6504
- });
6844
+ };
6845
+ if (globalFallbacks) {
6846
+ Object.assign(config, globalFallbacks);
6847
+ }
6848
+ return buildErrorMessages(config);
6505
6849
  };
6506
6850
 
6507
6851
  const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) => {
@@ -6564,6 +6908,7 @@ exports.ViewDialog = ViewDialog;
6564
6908
  exports.buildErrorMessages = buildErrorMessages;
6565
6909
  exports.buildFieldErrors = buildFieldErrors;
6566
6910
  exports.buildRequiredErrors = buildRequiredErrors;
6911
+ exports.convertToAjvErrorsFormat = convertToAjvErrorsFormat;
6567
6912
  exports.createErrorMessage = createErrorMessage;
6568
6913
  exports.getColumns = getColumns;
6569
6914
  exports.getMultiDates = getMultiDates;