@bsol-oss/react-datatable5 12.0.0-beta.74 → 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 (81) hide show
  1. package/dist/index.d.ts +133 -126
  2. package/dist/index.js +567 -253
  3. package/dist/index.mjs +569 -256
  4. package/dist/types/components/Form/SchemaFormContext.d.ts +3 -2
  5. package/dist/types/components/Form/components/fields/BooleanPicker.d.ts +1 -1
  6. package/dist/types/components/Form/components/fields/ColumnRenderer.d.ts +3 -2
  7. package/dist/types/components/Form/components/fields/DateTimePicker.d.ts +1 -1
  8. package/dist/types/components/Form/components/fields/FilePicker.d.ts +1 -1
  9. package/dist/types/components/Form/components/fields/ObjectInput.d.ts +1 -1
  10. package/dist/types/components/Form/components/fields/RecordInput.d.ts +1 -1
  11. package/dist/types/components/Form/components/fields/StringInputField.d.ts +1 -1
  12. package/dist/types/components/Form/components/fields/TextAreaInput.d.ts +1 -1
  13. package/dist/types/components/Form/components/fields/TimePicker.d.ts +1 -1
  14. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +3 -0
  15. package/dist/types/components/Form/useForm.d.ts +4 -2
  16. package/dist/types/components/Form/utils/ajvResolver.d.ts +13 -0
  17. package/dist/types/components/Form/utils/buildErrorMessages.d.ts +5 -1
  18. package/dist/types/components/Form/utils/getFieldError.d.ts +6 -0
  19. package/dist/types/components/Form/utils/useFormI18n.d.ts +1 -1
  20. package/dist/types/components/Form/utils/validateData.d.ts +2 -2
  21. package/dist/types/components/ui/field.d.ts +3 -3
  22. package/package.json +1 -1
  23. package/dist/types/components/Controls/DensityFeature.d.ts +0 -23
  24. package/dist/types/components/Controls/DensityToggleButton.d.ts +0 -6
  25. package/dist/types/components/Controls/EditFilterButton.d.ts +0 -9
  26. package/dist/types/components/Controls/EditOrderButton.d.ts +0 -7
  27. package/dist/types/components/Controls/EditSortingButton.d.ts +0 -7
  28. package/dist/types/components/Controls/EditViewButton.d.ts +0 -7
  29. package/dist/types/components/Controls/FilterDialog.d.ts +0 -5
  30. package/dist/types/components/Controls/PageSizeControl.d.ts +0 -4
  31. package/dist/types/components/Controls/Pagination.d.ts +0 -1
  32. package/dist/types/components/Controls/ResetFilteringButton.d.ts +0 -4
  33. package/dist/types/components/Controls/ResetSelectionButton.d.ts +0 -4
  34. package/dist/types/components/Controls/ResetSortingButton.d.ts +0 -4
  35. package/dist/types/components/Controls/RowCountText.d.ts +0 -1
  36. package/dist/types/components/Controls/SelectAllRowsToggle.d.ts +0 -8
  37. package/dist/types/components/Controls/TablePagination.d.ts +0 -1
  38. package/dist/types/components/Controls/ViewDialog.d.ts +0 -5
  39. package/dist/types/components/DataTable/CardHeader.d.ts +0 -13
  40. package/dist/types/components/DataTable/DataDisplay.d.ts +0 -6
  41. package/dist/types/components/DataTable/ReloadButton.d.ts +0 -5
  42. package/dist/types/components/DataTable/Table.d.ts +0 -10
  43. package/dist/types/components/DataTable/TableBody.d.ts +0 -21
  44. package/dist/types/components/DataTable/TableCardContainer.d.ts +0 -7
  45. package/dist/types/components/DataTable/TableCards.d.ts +0 -11
  46. package/dist/types/components/DataTable/TableComponent.d.ts +0 -6
  47. package/dist/types/components/DataTable/TableControls.d.ts +0 -21
  48. package/dist/types/components/DataTable/TableFilter.d.ts +0 -1
  49. package/dist/types/components/DataTable/TableFilterTags.d.ts +0 -1
  50. package/dist/types/components/DataTable/TableFilters.d.ts +0 -1
  51. package/dist/types/components/DataTable/TableFooter.d.ts +0 -9
  52. package/dist/types/components/DataTable/TableHeader.d.ts +0 -13
  53. package/dist/types/components/DataTable/TableLoadingComponent.d.ts +0 -5
  54. package/dist/types/components/DataTable/TableOrderer.d.ts +0 -1
  55. package/dist/types/components/DataTable/TableSelector.d.ts +0 -1
  56. package/dist/types/components/DataTable/TableSorter.d.ts +0 -1
  57. package/dist/types/components/DataTable/TableViewer.d.ts +0 -1
  58. package/dist/types/components/DataTable/TextCell.d.ts +0 -10
  59. package/dist/types/components/DataTable/components/EmptyState.d.ts +0 -5
  60. package/dist/types/components/DataTable/components/ErrorAlert.d.ts +0 -4
  61. package/dist/types/components/DataTable/components/RecordDisplay.d.ts +0 -9
  62. package/dist/types/components/DataTable/components/TextCell.d.ts +0 -10
  63. package/dist/types/components/Filter/DateRangeFilter.d.ts +0 -9
  64. package/dist/types/components/Filter/FilterOptions.d.ts +0 -4
  65. package/dist/types/components/Form/Form.d.ts +0 -36
  66. package/dist/types/components/Form/components/ArrayRenderer.d.ts +0 -7
  67. package/dist/types/components/Form/components/BooleanPicker.d.ts +0 -7
  68. package/dist/types/components/Form/components/ColumnRenderer.d.ts +0 -7
  69. package/dist/types/components/Form/components/DatePicker.d.ts +0 -7
  70. package/dist/types/components/Form/components/EnumPicker.d.ts +0 -8
  71. package/dist/types/components/Form/components/FilePicker.d.ts +0 -5
  72. package/dist/types/components/Form/components/IdPicker.d.ts +0 -8
  73. package/dist/types/components/Form/components/IdViewer.d.ts +0 -5
  74. package/dist/types/components/Form/components/NumberInputField.d.ts +0 -7
  75. package/dist/types/components/Form/components/ObjectInput.d.ts +0 -7
  76. package/dist/types/components/Form/components/RecordInput.d.ts +0 -7
  77. package/dist/types/components/Form/components/SchemaRenderer.d.ts +0 -7
  78. package/dist/types/components/Form/components/StringInputField.d.ts +0 -20
  79. package/dist/types/components/Form/components/TagPicker.d.ts +0 -30
  80. package/dist/types/components/Form/utils/translateWrapper.d.ts +0 -6
  81. package/dist/types/components/Form/utils/validation.d.ts +0 -104
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Accordion, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading } from '@chakra-ui/react';
2
+ import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading } from '@chakra-ui/react';
3
3
  import { AiOutlineColumnWidth } from 'react-icons/ai';
4
4
  import * as React from 'react';
5
5
  import React__default, { createContext, useContext, useState, useEffect, useRef, forwardRef } from 'react';
6
- import { LuX, LuCheck, LuChevronRight, LuChevronDown } from 'react-icons/lu';
6
+ import { LuX, LuCheck, LuChevronRight } from 'react-icons/lu';
7
7
  import { MdOutlineSort, MdFilterAlt, MdSearch, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdClear, MdOutlineChecklist, MdDateRange } from 'react-icons/md';
8
8
  import { FaUpDown, FaGripLinesVertical, FaTrash } from 'react-icons/fa6';
9
9
  import { BiDownArrow, BiUpArrow, BiError } from 'react-icons/bi';
@@ -30,7 +30,6 @@ import axios from 'axios';
30
30
  import { FormProvider, useFormContext, useForm as useForm$1 } from 'react-hook-form';
31
31
  import Ajv from 'ajv';
32
32
  import addFormats from 'ajv-formats';
33
- import addErrors from 'ajv-errors';
34
33
  import dayjs from 'dayjs';
35
34
  import utc from 'dayjs/plugin/utc';
36
35
  import timezone from 'dayjs/plugin/timezone';
@@ -3644,16 +3643,6 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
3644
3643
  })] }));
3645
3644
  };
3646
3645
 
3647
- const AccordionItemTrigger = React.forwardRef(function AccordionItemTrigger(props, ref) {
3648
- const { children, indicatorPlacement = "end", ...rest } = props;
3649
- return (jsxs(Accordion.ItemTrigger, { ...rest, ref: ref, children: [indicatorPlacement === "start" && (jsx(Accordion.ItemIndicator, { rotate: { base: "-90deg", _open: "0deg" }, children: jsx(LuChevronDown, {}) })), jsx(HStack, { gap: "4", flex: "1", textAlign: "start", width: "full", children: children }), indicatorPlacement === "end" && (jsx(Accordion.ItemIndicator, { children: jsx(LuChevronDown, {}) }))] }));
3650
- });
3651
- const AccordionItemContent = React.forwardRef(function AccordionItemContent(props, ref) {
3652
- return (jsx(Accordion.ItemContent, { children: jsx(Accordion.ItemBody, { ...props, ref: ref }) }));
3653
- });
3654
- const AccordionRoot = Accordion.Root;
3655
- const AccordionItem = Accordion.Item;
3656
-
3657
3646
  //@ts-expect-error TODO: find appropriate type
3658
3647
  const SchemaFormContext = createContext({
3659
3648
  schema: {},
@@ -3673,19 +3662,23 @@ const SchemaFormContext = createContext({
3673
3662
  },
3674
3663
  requireConfirmation: false,
3675
3664
  onFormSubmit: async () => { },
3665
+ ajvResolver: async () => ({ values: {}, errors: {} }),
3676
3666
  });
3677
3667
 
3678
3668
  const useSchemaContext = () => {
3679
3669
  return useContext(SchemaFormContext);
3680
3670
  };
3681
3671
 
3672
+ const clearEmptyString = (object) => {
3673
+ return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3674
+ };
3675
+
3682
3676
  const validateData = (data, schema) => {
3683
3677
  const ajv = new Ajv({
3684
3678
  strict: false,
3685
3679
  allErrors: true,
3686
3680
  });
3687
3681
  addFormats(ajv);
3688
- addErrors(ajv);
3689
3682
  const validate = ajv.compile(schema);
3690
3683
  const validationResult = validate(data);
3691
3684
  const errors = validate.errors;
@@ -3697,8 +3690,183 @@ const validateData = (data, schema) => {
3697
3690
  };
3698
3691
  };
3699
3692
 
3700
- const clearEmptyString = (object) => {
3701
- return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3693
+ /**
3694
+ * Gets the schema node for a field by following the path from root schema
3695
+ */
3696
+ const getSchemaNodeForField = (schema, fieldPath) => {
3697
+ if (!fieldPath || fieldPath === '') {
3698
+ return schema;
3699
+ }
3700
+ const pathParts = fieldPath.split('.');
3701
+ let currentSchema = schema;
3702
+ for (const part of pathParts) {
3703
+ if (currentSchema &&
3704
+ currentSchema.properties &&
3705
+ currentSchema.properties[part] &&
3706
+ typeof currentSchema.properties[part] === 'object' &&
3707
+ currentSchema.properties[part] !== null) {
3708
+ currentSchema = currentSchema.properties[part];
3709
+ }
3710
+ else {
3711
+ return undefined;
3712
+ }
3713
+ }
3714
+ return currentSchema;
3715
+ };
3716
+ /**
3717
+ * Converts AJV error objects to react-hook-form field errors format
3718
+ */
3719
+ const convertAjvErrorsToFieldErrors = (errors, schema) => {
3720
+ if (!errors || errors.length === 0) {
3721
+ return {};
3722
+ }
3723
+ const fieldErrors = {};
3724
+ errors.forEach((error) => {
3725
+ let fieldName = '';
3726
+ // Special handling for required keyword: map to the specific missing property
3727
+ if (error.keyword === 'required') {
3728
+ const basePath = (error.instancePath || '')
3729
+ .replace(/^\//, '')
3730
+ .replace(/\//g, '.');
3731
+ const missingProperty = (error.params &&
3732
+ error.params.missingProperty);
3733
+ if (missingProperty) {
3734
+ fieldName = basePath
3735
+ ? `${basePath}.${missingProperty}`
3736
+ : missingProperty;
3737
+ }
3738
+ else {
3739
+ // Fallback to schemaPath conversion if missingProperty is unavailable
3740
+ fieldName = (error.schemaPath || '')
3741
+ .replace(/^#\//, '#.')
3742
+ .replace(/\//g, '.');
3743
+ }
3744
+ }
3745
+ else {
3746
+ const fieldPath = error.instancePath || error.schemaPath;
3747
+ if (fieldPath) {
3748
+ fieldName = fieldPath.replace(/^\//, '').replace(/\//g, '.');
3749
+ }
3750
+ }
3751
+ if (fieldName) {
3752
+ // Get the schema node for this field to check for custom error messages
3753
+ const fieldSchema = getSchemaNodeForField(schema, fieldName);
3754
+ const customMessage = fieldSchema?.errorMessages?.[error.keyword];
3755
+ // Provide helpful fallback message if no custom message is provided
3756
+ const fallbackMessage = customMessage ||
3757
+ `Missing error message for ${error.keyword}. Add errorMessages.${error.keyword} to schema for field '${fieldName}'`;
3758
+ if (error.keyword === 'required') {
3759
+ // Required errors override any existing non-required errors for this field
3760
+ fieldErrors[fieldName] = {
3761
+ type: 'required',
3762
+ keyword: error.keyword,
3763
+ params: error.params,
3764
+ message: fallbackMessage,
3765
+ };
3766
+ }
3767
+ else {
3768
+ const existing = fieldErrors[fieldName];
3769
+ if (existing) {
3770
+ // Do not override required errors
3771
+ if (existing.type === 'required') {
3772
+ return;
3773
+ }
3774
+ // Combine messages if multiple errors for same field
3775
+ existing.message = existing.message
3776
+ ? `${existing.message}; ${fallbackMessage}`
3777
+ : fallbackMessage;
3778
+ }
3779
+ else {
3780
+ fieldErrors[fieldName] = {
3781
+ type: error.keyword,
3782
+ keyword: error.keyword,
3783
+ params: error.params,
3784
+ message: fallbackMessage,
3785
+ };
3786
+ }
3787
+ }
3788
+ }
3789
+ });
3790
+ return fieldErrors;
3791
+ };
3792
+ /**
3793
+ * AJV resolver for react-hook-form
3794
+ * Integrates AJV validation with react-hook-form's validation system
3795
+ */
3796
+ /**
3797
+ * Strips null, undefined, and empty string values from an object
3798
+ */
3799
+ const stripEmptyValues = (obj) => {
3800
+ if (obj === null || obj === undefined) {
3801
+ return undefined;
3802
+ }
3803
+ if (typeof obj === 'string' && obj.trim() === '') {
3804
+ return undefined;
3805
+ }
3806
+ if (Array.isArray(obj)) {
3807
+ const filtered = obj
3808
+ .map(stripEmptyValues)
3809
+ .filter((item) => item !== undefined);
3810
+ return filtered.length > 0 ? filtered : undefined;
3811
+ }
3812
+ if (typeof obj === 'object' && obj !== null) {
3813
+ const result = {};
3814
+ let hasValues = false;
3815
+ for (const [key, value] of Object.entries(obj)) {
3816
+ const cleanedValue = stripEmptyValues(value);
3817
+ if (cleanedValue !== undefined) {
3818
+ result[key] = cleanedValue;
3819
+ hasValues = true;
3820
+ }
3821
+ }
3822
+ return hasValues ? result : undefined;
3823
+ }
3824
+ return obj;
3825
+ };
3826
+ const ajvResolver = (schema) => {
3827
+ return async (values) => {
3828
+ try {
3829
+ // Strip empty values before validation
3830
+ const cleanedValues = stripEmptyValues(values);
3831
+ // Use empty object for validation if all values were stripped
3832
+ const valuesToValidate = cleanedValues === undefined ? {} : cleanedValues;
3833
+ const { isValid, errors } = validateData(valuesToValidate, schema);
3834
+ console.debug('AJV Validation Result:', {
3835
+ isValid,
3836
+ errors,
3837
+ cleanedValues,
3838
+ valuesToValidate,
3839
+ });
3840
+ if (isValid) {
3841
+ return {
3842
+ values: (cleanedValues || {}),
3843
+ errors: {},
3844
+ };
3845
+ }
3846
+ const fieldErrors = convertAjvErrorsToFieldErrors(errors, schema);
3847
+ console.debug('AJV Validation Failed:', {
3848
+ errors,
3849
+ fieldErrors,
3850
+ cleanedValues,
3851
+ valuesToValidate,
3852
+ });
3853
+ return {
3854
+ values: {},
3855
+ errors: fieldErrors,
3856
+ };
3857
+ }
3858
+ catch (error) {
3859
+ return {
3860
+ values: {},
3861
+ errors: {
3862
+ root: {
3863
+ type: 'validation',
3864
+ message: error instanceof Error ? error.message : 'Validation failed',
3865
+ },
3866
+ },
3867
+ };
3868
+ }
3869
+ };
3702
3870
  };
3703
3871
 
3704
3872
  const idPickerSanityCheck = (column, foreign_key) => {
@@ -3740,33 +3908,16 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3740
3908
  const onSubmitSuccess = () => {
3741
3909
  setIsSuccess(true);
3742
3910
  };
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
3911
  const defaultOnSubmit = async (promise) => {
3764
3912
  try {
3913
+ console.log('onBeforeSubmit');
3765
3914
  onBeforeSubmit();
3766
3915
  await promise;
3916
+ console.log('onSubmitSuccess');
3767
3917
  onSubmitSuccess();
3768
3918
  }
3769
3919
  catch (error) {
3920
+ console.log('onSubmitError', error);
3770
3921
  onSubmitError(error);
3771
3922
  }
3772
3923
  finally {
@@ -3776,7 +3927,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3776
3927
  const defaultSubmitPromise = (data) => {
3777
3928
  const options = {
3778
3929
  method: 'POST',
3779
- url: `${requestUrl}`,
3930
+ url: `${serverUrl}`,
3780
3931
  data: clearEmptyString(data),
3781
3932
  ...requestOptions,
3782
3933
  };
@@ -3784,23 +3935,13 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3784
3935
  };
3785
3936
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
3786
3937
  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
- }
3938
+ // AJV validation is now handled by react-hook-form resolver
3939
+ // This function will only be called if validation passes
3799
3940
  if (onSubmit === undefined) {
3800
- await defaultOnSubmit(defaultSubmitPromise(data));
3941
+ await defaultOnSubmit(Promise.resolve(defaultSubmitPromise(data)));
3801
3942
  return;
3802
3943
  }
3803
- await defaultOnSubmit(onSubmit(data));
3944
+ await defaultOnSubmit(Promise.resolve(onSubmit(data)));
3804
3945
  };
3805
3946
  return (jsx(SchemaFormContext.Provider, { value: {
3806
3947
  schema,
@@ -3836,6 +3977,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3836
3977
  dateTimePickerLabels,
3837
3978
  idPickerLabels,
3838
3979
  enumPickerLabels,
3980
+ ajvResolver: ajvResolver(schema),
3839
3981
  }, children: jsx(FormProvider, { ...form, children: children }) }));
3840
3982
  };
3841
3983
 
@@ -3881,20 +4023,22 @@ const ArrayRenderer = ({ schema, column, prefix, }) => {
3881
4023
 
3882
4024
  const Field = React.forwardRef(function Field(props, ref) {
3883
4025
  const { label, children, helperText, errorText, optionalText, ...rest } = props;
3884
- return (jsxs(Field$1.Root, { ref: ref, ...rest, children: [label && (jsxs(Field$1.Label, { children: [label, jsx(Field$1.RequiredIndicator, { fallback: optionalText })] })), children, helperText && (jsx(Field$1.HelperText, { children: helperText })), errorText && (jsx(Field$1.ErrorText, { children: errorText }))] }));
4026
+ return (jsxs(Field$1.Root, { ref: ref, ...rest, children: [label && (jsxs(Field$1.Label, { children: [label, jsx(Field$1.RequiredIndicator, { color: rest.invalid && rest.required ? 'red.500' : undefined, fallback: optionalText })] })), children, helperText && (jsx(Field$1.HelperText, { children: helperText })), !!errorText && (jsxs(Field$1.ErrorText, { children: [rest.required && rest.invalid && (jsx("span", { style: { color: 'var(--chakra-colors-red-500)' }, children: "* " })), errorText] }))] }));
3885
4027
  });
3886
4028
 
3887
4029
  const BooleanPicker = ({ schema, column, prefix }) => {
3888
4030
  const { watch, formState: { errors }, setValue, } = useFormContext();
3889
4031
  const { translate } = useSchemaContext();
3890
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
4032
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
3891
4033
  const isRequired = required?.some((columnId) => columnId === column);
3892
4034
  const colLabel = `${prefix}${column}`;
3893
4035
  const value = watch(colLabel);
3894
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3895
- gridRow, children: [jsx(CheckboxCard, { checked: value, variant: "surface", onChange: () => {
3896
- setValue(colLabel, !value);
3897
- } }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4036
+ return (jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4037
+ gridRow, errorText: errors[`${colLabel}`]
4038
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
4039
+ : undefined, invalid: !!errors[colLabel], children: jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
4040
+ setValue(colLabel, !value);
4041
+ } }) }));
3898
4042
  };
3899
4043
 
3900
4044
  const CustomInput = ({ column, schema, prefix }) => {
@@ -4127,83 +4271,83 @@ const DatePicker = ({ column, schema, prefix }) => {
4127
4271
  console.error(e);
4128
4272
  }
4129
4273
  }, [selectedDate, dateFormat, colLabel, setValue]);
4130
- return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4131
- gridRow, children: [jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4132
- setOpen(true);
4133
- }, justifyContent: 'start', children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4134
- setValue(colLabel, dayjs(date).format(dateFormat));
4135
- setOpen(false);
4136
- }, labels: {
4137
- monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4138
- formI18n.translate.t(`common.month_1`, {
4139
- defaultValue: 'January',
4140
- }),
4141
- formI18n.translate.t(`common.month_2`, {
4142
- defaultValue: 'February',
4143
- }),
4144
- formI18n.translate.t(`common.month_3`, {
4145
- defaultValue: 'March',
4146
- }),
4147
- formI18n.translate.t(`common.month_4`, {
4148
- defaultValue: 'April',
4149
- }),
4150
- formI18n.translate.t(`common.month_5`, {
4151
- defaultValue: 'May',
4152
- }),
4153
- formI18n.translate.t(`common.month_6`, {
4154
- defaultValue: 'June',
4155
- }),
4156
- formI18n.translate.t(`common.month_7`, {
4157
- defaultValue: 'July',
4158
- }),
4159
- formI18n.translate.t(`common.month_8`, {
4160
- defaultValue: 'August',
4161
- }),
4162
- formI18n.translate.t(`common.month_9`, {
4163
- defaultValue: 'September',
4164
- }),
4165
- formI18n.translate.t(`common.month_10`, {
4166
- defaultValue: 'October',
4167
- }),
4168
- formI18n.translate.t(`common.month_11`, {
4169
- defaultValue: 'November',
4170
- }),
4171
- formI18n.translate.t(`common.month_12`, {
4172
- defaultValue: 'December',
4173
- }),
4174
- ],
4175
- weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4176
- formI18n.translate.t(`common.weekday_1`, {
4177
- defaultValue: 'Sun',
4178
- }),
4179
- formI18n.translate.t(`common.weekday_2`, {
4180
- defaultValue: 'Mon',
4181
- }),
4182
- formI18n.translate.t(`common.weekday_3`, {
4183
- defaultValue: 'Tue',
4184
- }),
4185
- formI18n.translate.t(`common.weekday_4`, {
4186
- defaultValue: 'Wed',
4187
- }),
4188
- formI18n.translate.t(`common.weekday_5`, {
4189
- defaultValue: 'Thu',
4190
- }),
4191
- formI18n.translate.t(`common.weekday_6`, {
4192
- defaultValue: 'Fri',
4193
- }),
4194
- formI18n.translate.t(`common.weekday_7`, {
4195
- defaultValue: 'Sat',
4196
- }),
4197
- ],
4198
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4199
- formI18n.translate.t(`common.back_button`, {
4200
- defaultValue: 'Back',
4201
- }),
4202
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4203
- formI18n.translate.t(`common.forward_button`, {
4204
- defaultValue: 'Forward',
4205
- }),
4206
- } })] }) })] }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
4274
+ return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4275
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4276
+ setOpen(true);
4277
+ }, justifyContent: 'start', children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4278
+ setValue(colLabel, dayjs(date).format(dateFormat));
4279
+ setOpen(false);
4280
+ }, labels: {
4281
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4282
+ formI18n.translate.t(`common.month_1`, {
4283
+ defaultValue: 'January',
4284
+ }),
4285
+ formI18n.translate.t(`common.month_2`, {
4286
+ defaultValue: 'February',
4287
+ }),
4288
+ formI18n.translate.t(`common.month_3`, {
4289
+ defaultValue: 'March',
4290
+ }),
4291
+ formI18n.translate.t(`common.month_4`, {
4292
+ defaultValue: 'April',
4293
+ }),
4294
+ formI18n.translate.t(`common.month_5`, {
4295
+ defaultValue: 'May',
4296
+ }),
4297
+ formI18n.translate.t(`common.month_6`, {
4298
+ defaultValue: 'June',
4299
+ }),
4300
+ formI18n.translate.t(`common.month_7`, {
4301
+ defaultValue: 'July',
4302
+ }),
4303
+ formI18n.translate.t(`common.month_8`, {
4304
+ defaultValue: 'August',
4305
+ }),
4306
+ formI18n.translate.t(`common.month_9`, {
4307
+ defaultValue: 'September',
4308
+ }),
4309
+ formI18n.translate.t(`common.month_10`, {
4310
+ defaultValue: 'October',
4311
+ }),
4312
+ formI18n.translate.t(`common.month_11`, {
4313
+ defaultValue: 'November',
4314
+ }),
4315
+ formI18n.translate.t(`common.month_12`, {
4316
+ defaultValue: 'December',
4317
+ }),
4318
+ ],
4319
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4320
+ formI18n.translate.t(`common.weekday_1`, {
4321
+ defaultValue: 'Sun',
4322
+ }),
4323
+ formI18n.translate.t(`common.weekday_2`, {
4324
+ defaultValue: 'Mon',
4325
+ }),
4326
+ formI18n.translate.t(`common.weekday_3`, {
4327
+ defaultValue: 'Tue',
4328
+ }),
4329
+ formI18n.translate.t(`common.weekday_4`, {
4330
+ defaultValue: 'Wed',
4331
+ }),
4332
+ formI18n.translate.t(`common.weekday_5`, {
4333
+ defaultValue: 'Thu',
4334
+ }),
4335
+ formI18n.translate.t(`common.weekday_6`, {
4336
+ defaultValue: 'Fri',
4337
+ }),
4338
+ formI18n.translate.t(`common.weekday_7`, {
4339
+ defaultValue: 'Sat',
4340
+ }),
4341
+ ],
4342
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4343
+ formI18n.translate.t(`common.back_button`, {
4344
+ defaultValue: 'Back',
4345
+ }),
4346
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4347
+ formI18n.translate.t(`common.forward_button`, {
4348
+ defaultValue: 'Forward',
4349
+ }),
4350
+ } })] }) })] }) }));
4207
4351
  };
4208
4352
 
4209
4353
  function filterArray(array, searchTerm) {
@@ -4238,7 +4382,9 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4238
4382
  };
4239
4383
  if (variant === 'radio') {
4240
4384
  return (jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4241
- gridRow, children: jsx(RadioGroup$1.Root, { defaultValue: "1", children: jsx(HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
4385
+ gridRow, errorText: errors[`${colLabel}`]
4386
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
4387
+ : undefined, invalid: !!errors[colLabel], children: jsx(RadioGroup$1.Root, { defaultValue: "1", children: jsx(HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
4242
4388
  return (jsxs(RadioGroup$1.Item, { onClick: () => {
4243
4389
  if (!isMultiple) {
4244
4390
  setOpenSearchResult(false);
@@ -4253,7 +4399,9 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4253
4399
  }) }) }) }));
4254
4400
  }
4255
4401
  return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4256
- gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
4402
+ gridRow, errorText: errors[`${colLabel}`]
4403
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
4404
+ : undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxs(Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
4257
4405
  const item = enumValue;
4258
4406
  if (!!item === false) {
4259
4407
  return jsx(Fragment, {});
@@ -4308,7 +4456,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4308
4456
  ? renderDisplay(item)
4309
4457
  : translate.t(removeIndex(`${colLabel}.${item}`)) }, `${colLabel}-${item}`));
4310
4458
  }) }), isDirty && (jsx(Fragment, { children: dataList.length <= 0 && (jsx(Fragment, { children: enumPickerLabels?.emptySearchResult ??
4311
- translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4459
+ translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] })] }));
4312
4460
  };
4313
4461
 
4314
4462
  function isEnteringWindow(_ref) {
@@ -4666,20 +4814,22 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
4666
4814
  const FilePicker = ({ column, schema, prefix }) => {
4667
4815
  const { setValue, formState: { errors }, watch, } = useFormContext();
4668
4816
  const { translate } = useSchemaContext();
4669
- const { required, gridColumn = "span 12", gridRow = "span 1", } = schema;
4817
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
4670
4818
  const isRequired = required?.some((columnId) => columnId === column);
4671
4819
  const currentFiles = (watch(column) ?? []);
4672
4820
  const colLabel = `${prefix}${column}`;
4673
- return (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: [jsx(FileDropzone, { onDrop: ({ files }) => {
4821
+ return (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}`]
4822
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
4823
+ : undefined, invalid: !!errors[colLabel], children: [jsx(FileDropzone, { onDrop: ({ files }) => {
4674
4824
  const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4675
4825
  setValue(colLabel, [...currentFiles, ...newFiles]);
4676
- }, placeholder: translate.t(removeIndex(`${colLabel}.fileDropzone`)) }), jsx(Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
4677
- return (jsx(Card.Root, { variant: "subtle", children: jsxs(Card.Body, { gap: "2", cursor: "pointer", onClick: () => {
4826
+ }, placeholder: translate.t(removeIndex(`${colLabel}.fileDropzone`)) }), jsx(Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file) => {
4827
+ return (jsx(Card.Root, { variant: 'subtle', children: jsxs(Card.Body, { gap: "2", cursor: 'pointer', onClick: () => {
4678
4828
  setValue(column, currentFiles.filter(({ name }) => {
4679
4829
  return name !== file.name;
4680
4830
  }));
4681
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [file.type.startsWith("image/") && (jsx(Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsx(Box, { children: file.name }), jsx(TiDeleteOutline, {})] }) }, file.name));
4682
- }) }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4831
+ }, display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', children: [file.type.startsWith('image/') && (jsx(Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsx(Box, { children: file.name }), jsx(TiDeleteOutline, {})] }) }, file.name));
4832
+ }) })] }));
4683
4833
  };
4684
4834
 
4685
4835
  const ToggleTip = React.forwardRef(function ToggleTip(props, ref) {
@@ -4868,7 +5018,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4868
5018
  return record[display_column];
4869
5019
  };
4870
5020
  return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4871
- gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow: 'wrap', gap: 1, children: [watchIds.map((id) => {
5021
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxs(Flex, { flexFlow: 'wrap', gap: 1, children: [watchIds.map((id) => {
4872
5022
  const item = idMap[id];
4873
5023
  if (item === undefined) {
4874
5024
  return (jsx(Text, { children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
@@ -4919,7 +5069,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4919
5069
  ? idPickerLabels?.emptySearchResult ??
4920
5070
  formI18n.t('empty_search_result')
4921
5071
  : idPickerLabels?.initialResults ??
4922
- formI18n.t('initial_results') })) }), jsx(PaginationRoot, { justifySelf: 'center', count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxs(HStack, { gap: "4", children: [jsx(PaginationPrevTrigger, {}), count > 0 && jsx(PaginationPageText, {}), jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
5072
+ formI18n.t('initial_results') })) }), jsx(PaginationRoot, { justifySelf: 'center', count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxs(HStack, { gap: "4", children: [jsx(PaginationPrevTrigger, {}), count > 0 && jsx(PaginationPageText, {}), jsx(PaginationNextTrigger, {})] }) })] }))] }) })] })] }));
4923
5073
  };
4924
5074
 
4925
5075
  const NumberInputRoot = React.forwardRef(function NumberInput$1(props, ref) {
@@ -4930,20 +5080,84 @@ const NumberInputField$1 = NumberInput.Input;
4930
5080
  NumberInput.Scrubber;
4931
5081
  NumberInput.Label;
4932
5082
 
5083
+ /**
5084
+ * Gets the error message for a specific field from react-hook-form errors
5085
+ * Prioritizes required errors (#.required) over field-specific validation errors
5086
+ */
5087
+ const getFieldError = (errors, fieldName) => {
5088
+ // Check for form-level required errors first (highest priority)
5089
+ const requiredError = errors['#.required'];
5090
+ if (requiredError) {
5091
+ const requiredErrorMessage = extractErrorMessage(requiredError);
5092
+ if (requiredErrorMessage) {
5093
+ return requiredErrorMessage;
5094
+ }
5095
+ }
5096
+ // If no required errors, return field-specific error
5097
+ const fieldError = errors[fieldName];
5098
+ if (fieldError) {
5099
+ const fieldErrorMessage = extractErrorMessage(fieldError);
5100
+ if (fieldErrorMessage) {
5101
+ return fieldErrorMessage;
5102
+ }
5103
+ }
5104
+ return undefined;
5105
+ };
5106
+ /**
5107
+ * Helper function to extract error message from various error formats
5108
+ * Only returns message if explicitly provided, no fallback text
5109
+ */
5110
+ const extractErrorMessage = (error) => {
5111
+ if (!error) {
5112
+ return undefined;
5113
+ }
5114
+ // If it's a simple string error
5115
+ if (typeof error === 'string') {
5116
+ return error;
5117
+ }
5118
+ // If it's an error object with a message property
5119
+ if (error && typeof error === 'object' && 'message' in error) {
5120
+ return error.message;
5121
+ }
5122
+ // If it's an array of errors, get the first one
5123
+ if (Array.isArray(error) && error.length > 0) {
5124
+ const firstError = error[0];
5125
+ if (typeof firstError === 'string') {
5126
+ return firstError;
5127
+ }
5128
+ if (firstError &&
5129
+ typeof firstError === 'object' &&
5130
+ 'message' in firstError) {
5131
+ return firstError.message;
5132
+ }
5133
+ }
5134
+ // No fallback - return undefined if no message provided
5135
+ return undefined;
5136
+ };
5137
+
4933
5138
  const NumberInputField = ({ schema, column, prefix, }) => {
4934
5139
  const { setValue, formState: { errors }, watch, } = useFormContext();
4935
5140
  const { translate } = useSchemaContext();
4936
- const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5141
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', numberStorageType = 'number', } = schema;
4937
5142
  const isRequired = required?.some((columnId) => columnId === column);
4938
5143
  const colLabel = `${prefix}${column}`;
4939
5144
  const value = watch(`${colLabel}`);
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`)) }))] }));
5145
+ const fieldError = getFieldError(errors, colLabel);
5146
+ return (jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, errorText: fieldError
5147
+ ? fieldError.includes('required')
5148
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
5149
+ : fieldError
5150
+ : undefined, invalid: !!fieldError, children: jsx(NumberInputRoot, { value: value, onValueChange: (details) => {
5151
+ // Store as string or number based on configuration, default to number
5152
+ const value = numberStorageType === 'string'
5153
+ ? details.value
5154
+ : details.valueAsNumber;
5155
+ setValue(`${colLabel}`, value);
5156
+ }, 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 }) }) }));
4943
5157
  };
4944
5158
 
4945
5159
  const ObjectInput = ({ schema, column, prefix }) => {
4946
- const { properties, gridColumn = "span 12", gridRow = "span 1", required, showLabel = true, } = schema;
5160
+ const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
4947
5161
  const { translate } = useSchemaContext();
4948
5162
  const colLabel = `${prefix}${column}`;
4949
5163
  const isRequired = required?.some((columnId) => columnId === column);
@@ -4951,29 +5165,32 @@ const ObjectInput = ({ schema, column, prefix }) => {
4951
5165
  if (properties === undefined) {
4952
5166
  throw new Error(`properties is undefined when using ObjectInput`);
4953
5167
  }
4954
- return (jsxs(Box, { gridRow, gridColumn, children: [showLabel && (jsxs(Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsx("span", { children: "*" })] })), jsx(Grid, { bgColor: { base: "colorPalette.100", _dark: "colorPalette.900" }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
4955
- base: "colorPalette.200",
4956
- _dark: "colorPalette.800",
4957
- }, gap: "4", padding: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: Object.keys(properties ?? {}).map((key) => {
5168
+ return (jsxs(Box, { gridRow, gridColumn, children: [showLabel && (jsxs(Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsx("span", { children: "*" })] })), jsx(Grid, { bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
5169
+ base: 'colorPalette.200',
5170
+ _dark: 'colorPalette.800',
5171
+ }, gap: "4", padding: '4', gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: Object.keys(properties ?? {}).map((key) => {
4958
5172
  return (
4959
5173
  // @ts-expect-error find suitable types
4960
5174
  jsx(ColumnRenderer, { column: `${key}`,
4961
5175
  prefix: `${prefix}${column}.`,
4962
- properties }, `form-${colLabel}-${key}`));
4963
- }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5176
+ properties,
5177
+ parentRequired: required }, `form-${colLabel}-${key}`));
5178
+ }) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4964
5179
  };
4965
5180
 
4966
5181
  const RecordInput$1 = ({ column, schema, prefix }) => {
4967
5182
  const { formState: { errors }, setValue, getValues, } = useFormContext();
4968
5183
  const { translate } = useSchemaContext();
4969
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5184
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
4970
5185
  const isRequired = required?.some((columnId) => columnId === column);
4971
5186
  const entries = Object.entries(getValues(column) ?? {});
4972
5187
  const [showNewEntries, setShowNewEntries] = useState(false);
4973
5188
  const [newKey, setNewKey] = useState();
4974
5189
  const [newValue, setNewValue] = useState();
4975
- return (jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
4976
- return (jsxs(Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
5190
+ return (jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: errors[`${column}`]
5191
+ ? translate.t(`${column}.field_required`)
5192
+ : undefined, invalid: !!errors[column], children: [entries.map(([key, value]) => {
5193
+ return (jsxs(Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
4977
5194
  const filtered = entries.filter(([target]) => {
4978
5195
  return target !== key;
4979
5196
  });
@@ -4983,17 +5200,17 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
4983
5200
  ...getValues(column),
4984
5201
  [key]: e.target.value,
4985
5202
  });
4986
- }, autoComplete: "off" }), jsx(IconButton, { variant: "ghost", onClick: () => {
5203
+ }, autoComplete: "off" }), jsx(IconButton, { variant: 'ghost', onClick: () => {
4987
5204
  const filtered = entries.filter(([target]) => {
4988
5205
  return target !== key;
4989
5206
  });
4990
5207
  setValue(column, Object.fromEntries([...filtered]));
4991
5208
  }, children: jsx(CgClose, {}) })] }));
4992
- }), jsx(Show, { when: showNewEntries, children: jsxs(Card.Root, { children: [jsx(Card.Body, { gap: "2", children: jsxs(Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsx(Input, { value: newKey, onChange: (e) => {
5209
+ }), jsx(Show, { when: showNewEntries, children: jsxs(Card.Root, { children: [jsx(Card.Body, { gap: "2", children: jsxs(Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsx(Input, { value: newKey, onChange: (e) => {
4993
5210
  setNewKey(e.target.value);
4994
5211
  }, autoComplete: "off" }), jsx(Input, { value: newValue, onChange: (e) => {
4995
5212
  setNewValue(e.target.value);
4996
- }, autoComplete: "off" })] }) }), jsxs(Card.Footer, { justifyContent: "flex-end", children: [jsx(IconButton, { variant: "subtle", onClick: () => {
5213
+ }, autoComplete: "off" })] }) }), jsxs(Card.Footer, { justifyContent: "flex-end", children: [jsx(IconButton, { variant: 'subtle', onClick: () => {
4997
5214
  setShowNewEntries(false);
4998
5215
  setNewKey(undefined);
4999
5216
  setNewValue(undefined);
@@ -5012,16 +5229,17 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
5012
5229
  setShowNewEntries(true);
5013
5230
  setNewKey(undefined);
5014
5231
  setNewValue(undefined);
5015
- }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
5232
+ }, children: translate.t(`${column}.addNew`) })] }));
5016
5233
  };
5017
5234
 
5018
5235
  const StringInputField = ({ column, schema, prefix, }) => {
5019
5236
  const { register, formState: { errors }, } = useFormContext();
5020
5237
  const { translate } = useSchemaContext();
5021
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5238
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5022
5239
  const isRequired = required?.some((columnId) => columnId === column);
5023
5240
  const colLabel = `${prefix}${column}`;
5024
- return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5241
+ const fieldError = getFieldError(errors, colLabel);
5242
+ return (jsx(Fragment, { children: jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: fieldError, invalid: !!fieldError, children: jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
5025
5243
  };
5026
5244
 
5027
5245
  const RadioCardItem = React.forwardRef(function RadioCardItem(props, ref) {
@@ -5207,13 +5425,18 @@ Textarea.displayName = "Textarea";
5207
5425
  const TextAreaInput = ({ column, schema, prefix, }) => {
5208
5426
  const { register, formState: { errors }, } = useFormContext();
5209
5427
  const { translate } = useSchemaContext();
5210
- const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
5428
+ const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
5211
5429
  const isRequired = required?.some((columnId) => columnId === column);
5212
5430
  const colLabel = `${prefix}${column}`;
5213
5431
  const form = useFormContext();
5214
5432
  const { setValue, watch } = form;
5433
+ const fieldError = getFieldError(errors, colLabel);
5215
5434
  const watchValue = watch(colLabel);
5216
- return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", children: [jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5435
+ return (jsx(Fragment, { children: jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
5436
+ ? fieldError.includes('required')
5437
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
5438
+ : fieldError
5439
+ : undefined, invalid: !!fieldError, children: jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
5217
5440
  };
5218
5441
 
5219
5442
  function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
@@ -5344,25 +5567,25 @@ dayjs.extend(timezone);
5344
5567
  const TimePicker = ({ column, schema, prefix }) => {
5345
5568
  const { watch, formState: { errors }, setValue, } = useFormContext();
5346
5569
  const { translate, timezone } = useSchemaContext();
5347
- const { required, gridColumn = "span 12", gridRow = "span 1", timeFormat = "HH:mm:ssZ", displayTimeFormat = "hh:mm A", } = schema;
5570
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
5348
5571
  const isRequired = required?.some((columnId) => columnId === column);
5349
5572
  const colLabel = `${prefix}${column}`;
5350
5573
  const [open, setOpen] = useState(false);
5351
5574
  const value = watch(colLabel);
5352
5575
  const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
5353
5576
  ? dayjs(`1970-01-01T${value}`).tz(timezone).format(displayTimeFormat)
5354
- : "";
5577
+ : '';
5355
5578
  // Parse the initial time parts from the time string (HH:mm:ssZ)
5356
5579
  const parseTime = (time) => {
5357
5580
  if (!time)
5358
- return { hour: 12, minute: 0, meridiem: "am" };
5581
+ return { hour: 12, minute: 0, meridiem: 'am' };
5359
5582
  const parsed = dayjs(`1970-01-01T${time}`).tz(timezone);
5360
5583
  if (!parsed.isValid()) {
5361
- return { hour: 12, minute: 0, meridiem: "am" };
5584
+ return { hour: 12, minute: 0, meridiem: 'am' };
5362
5585
  }
5363
5586
  let hour = parsed.hour();
5364
5587
  const minute = parsed.minute();
5365
- const meridiem = hour >= 12 ? "pm" : "am";
5588
+ const meridiem = hour >= 12 ? 'pm' : 'am';
5366
5589
  if (hour === 0)
5367
5590
  hour = 12;
5368
5591
  else if (hour > 12)
@@ -5383,10 +5606,15 @@ const TimePicker = ({ column, schema, prefix }) => {
5383
5606
  if (hour === null || minute === null || meridiem === null)
5384
5607
  return null;
5385
5608
  let newHour = hour;
5386
- if (meridiem === "pm" && hour !== 12) {
5609
+ if (meridiem === 'pm' && hour !== 12) {
5387
5610
  newHour = hour + 12;
5388
5611
  }
5389
- return dayjs().tz(timezone).hour(newHour).minute(minute).second(0).format(timeFormat);
5612
+ return dayjs()
5613
+ .tz(timezone)
5614
+ .hour(newHour)
5615
+ .minute(minute)
5616
+ .second(0)
5617
+ .format(timeFormat);
5390
5618
  };
5391
5619
  // Handle changes to time parts
5392
5620
  const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
@@ -5396,13 +5624,15 @@ const TimePicker = ({ column, schema, prefix }) => {
5396
5624
  const timeString = getTimeString(newHour, newMinute, newMeridiem);
5397
5625
  setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
5398
5626
  };
5399
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5400
- gridRow, children: [jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5401
- setOpen(true);
5402
- }, justifyContent: "start", children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ""] }) }), jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5403
- am: translate.t(`common.am`, { defaultValue: "AM" }),
5404
- pm: translate.t(`common.pm`, { defaultValue: "PM" }),
5405
- } }) }) }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5627
+ return (jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
5628
+ gridRow, errorText: errors[`${colLabel}`]
5629
+ ? translate.t(removeIndex(`${colLabel}.field_required`))
5630
+ : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5631
+ setOpen(true);
5632
+ }, justifyContent: 'start', children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), jsx(Popover.Positioner, { children: jsx(Popover.Content, { children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
5633
+ am: translate.t(`common.am`, { defaultValue: 'AM' }),
5634
+ pm: translate.t(`common.pm`, { defaultValue: 'PM' }),
5635
+ } }) }) }) })] }) }));
5406
5636
  };
5407
5637
 
5408
5638
  function IsoTimePicker({ hour, setHour, minute, setMinute, second, setSecond, onChange = (_newValue) => { }, }) {
@@ -5608,9 +5838,9 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
5608
5838
  const { watch, formState: { errors }, setValue, } = useFormContext();
5609
5839
  const { timezone, dateTimePickerLabels } = useSchemaContext();
5610
5840
  const formI18n = useFormI18n(column, prefix);
5611
- const { required, gridColumn = "span 12", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss",
5841
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
5612
5842
  // with timezone
5613
- dateFormat = "YYYY-MM-DD[T]HH:mm:ssZ", } = schema;
5843
+ dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
5614
5844
  const isRequired = required?.some((columnId) => columnId === column);
5615
5845
  const colLabel = formI18n.colLabel;
5616
5846
  const [open, setOpen] = useState(false);
@@ -5641,44 +5871,82 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
5641
5871
  console.error(e);
5642
5872
  }
5643
5873
  }, [selectedDate, dateFormat, colLabel, setValue]);
5644
- return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
5645
- gridRow, children: [jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5646
- setOpen(true);
5647
- }, justifyContent: "start", children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsx(PopoverContent, { minW: "450px", children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
5648
- setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
5649
- }, timezone: timezone, labels: {
5650
- monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
5651
- formI18n.translate.t(`common.month_1`, { defaultValue: "January" }),
5652
- formI18n.translate.t(`common.month_2`, { defaultValue: "February" }),
5653
- formI18n.translate.t(`common.month_3`, { defaultValue: "March" }),
5654
- formI18n.translate.t(`common.month_4`, { defaultValue: "April" }),
5655
- formI18n.translate.t(`common.month_5`, { defaultValue: "May" }),
5656
- formI18n.translate.t(`common.month_6`, { defaultValue: "June" }),
5657
- formI18n.translate.t(`common.month_7`, { defaultValue: "July" }),
5658
- formI18n.translate.t(`common.month_8`, { defaultValue: "August" }),
5659
- formI18n.translate.t(`common.month_9`, { defaultValue: "September" }),
5660
- formI18n.translate.t(`common.month_10`, { defaultValue: "October" }),
5661
- formI18n.translate.t(`common.month_11`, { defaultValue: "November" }),
5662
- formI18n.translate.t(`common.month_12`, { defaultValue: "December" }),
5663
- ],
5664
- weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
5665
- formI18n.translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
5666
- formI18n.translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
5667
- formI18n.translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
5668
- formI18n.translate.t(`common.weekday_4`, {
5669
- defaultValue: "Wed",
5670
- }),
5671
- formI18n.translate.t(`common.weekday_5`, { defaultValue: "Thu" }),
5672
- formI18n.translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
5673
- formI18n.translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
5674
- ],
5675
- backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? formI18n.translate.t(`common.back_button`, {
5676
- defaultValue: "Back",
5874
+ return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5875
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
5876
+ setOpen(true);
5877
+ }, justifyContent: 'start', children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsx(PopoverContent, { minW: '450px', children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
5878
+ setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
5879
+ }, timezone: timezone, labels: {
5880
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
5881
+ formI18n.translate.t(`common.month_1`, {
5882
+ defaultValue: 'January',
5883
+ }),
5884
+ formI18n.translate.t(`common.month_2`, {
5885
+ defaultValue: 'February',
5886
+ }),
5887
+ formI18n.translate.t(`common.month_3`, {
5888
+ defaultValue: 'March',
5889
+ }),
5890
+ formI18n.translate.t(`common.month_4`, {
5891
+ defaultValue: 'April',
5892
+ }),
5893
+ formI18n.translate.t(`common.month_5`, {
5894
+ defaultValue: 'May',
5895
+ }),
5896
+ formI18n.translate.t(`common.month_6`, {
5897
+ defaultValue: 'June',
5898
+ }),
5899
+ formI18n.translate.t(`common.month_7`, {
5900
+ defaultValue: 'July',
5901
+ }),
5902
+ formI18n.translate.t(`common.month_8`, {
5903
+ defaultValue: 'August',
5904
+ }),
5905
+ formI18n.translate.t(`common.month_9`, {
5906
+ defaultValue: 'September',
5907
+ }),
5908
+ formI18n.translate.t(`common.month_10`, {
5909
+ defaultValue: 'October',
5910
+ }),
5911
+ formI18n.translate.t(`common.month_11`, {
5912
+ defaultValue: 'November',
5913
+ }),
5914
+ formI18n.translate.t(`common.month_12`, {
5915
+ defaultValue: 'December',
5916
+ }),
5917
+ ],
5918
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
5919
+ formI18n.translate.t(`common.weekday_1`, {
5920
+ defaultValue: 'Sun',
5921
+ }),
5922
+ formI18n.translate.t(`common.weekday_2`, {
5923
+ defaultValue: 'Mon',
5924
+ }),
5925
+ formI18n.translate.t(`common.weekday_3`, {
5926
+ defaultValue: 'Tue',
5927
+ }),
5928
+ formI18n.translate.t(`common.weekday_4`, {
5929
+ defaultValue: 'Wed',
5930
+ }),
5931
+ formI18n.translate.t(`common.weekday_5`, {
5932
+ defaultValue: 'Thu',
5933
+ }),
5934
+ formI18n.translate.t(`common.weekday_6`, {
5935
+ defaultValue: 'Fri',
5936
+ }),
5937
+ formI18n.translate.t(`common.weekday_7`, {
5938
+ defaultValue: 'Sat',
5939
+ }),
5940
+ ],
5941
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
5942
+ formI18n.translate.t(`common.back_button`, {
5943
+ defaultValue: 'Back',
5677
5944
  }),
5678
- forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? formI18n.translate.t(`common.forward_button`, {
5679
- defaultValue: "Forward",
5945
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
5946
+ formI18n.translate.t(`common.forward_button`, {
5947
+ defaultValue: 'Forward',
5680
5948
  }),
5681
- } })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: formI18n.required() }))] }));
5949
+ } })] }) })] }) }));
5682
5950
  };
5683
5951
 
5684
5952
  const SchemaRenderer = ({ schema, prefix, column, }) => {
@@ -5752,13 +6020,18 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
5752
6020
  return jsx(Text, { children: "missing type" });
5753
6021
  };
5754
6022
 
5755
- const ColumnRenderer = ({ column, properties, prefix, }) => {
6023
+ const ColumnRenderer = ({ column, properties, prefix, parentRequired, }) => {
5756
6024
  const colSchema = properties[column];
5757
6025
  const colLabel = `${prefix}${column}`;
5758
6026
  if (colSchema === undefined) {
5759
6027
  throw new Error(`${colLabel} does not exist when using ColumnRenderer`);
5760
6028
  }
5761
- return jsx(SchemaRenderer, { schema: colSchema, prefix, column });
6029
+ // Merge parent's required array with the schema's required array
6030
+ const schemaWithRequired = {
6031
+ ...colSchema,
6032
+ required: parentRequired || colSchema.required,
6033
+ };
6034
+ return jsx(SchemaRenderer, { schema: schemaWithRequired, prefix, column });
5762
6035
  };
5763
6036
 
5764
6037
  const ArrayViewer = ({ schema, column, prefix }) => {
@@ -6199,15 +6472,15 @@ const SubmitButton = () => {
6199
6472
  const methods = useFormContext();
6200
6473
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6201
6474
  const onValid = (data) => {
6202
- const { isValid, errors } = validateData(data, schema);
6203
- if (!isValid) {
6204
- setError({
6205
- type: 'validation',
6206
- errors,
6207
- });
6208
- setIsError(true);
6209
- return;
6210
- }
6475
+ // const { isValid, errors } = validateData(data, schema);
6476
+ // if (!isValid) {
6477
+ // setError({
6478
+ // type: 'validation',
6479
+ // errors,
6480
+ // });
6481
+ // setIsError(true);
6482
+ // return;
6483
+ // }
6211
6484
  // If validation passes, check if confirmation is required
6212
6485
  if (requireConfirmation) {
6213
6486
  // Show confirmation (existing behavior)
@@ -6232,10 +6505,6 @@ const FormBody = () => {
6232
6505
  const { showSubmitButton, showResetButton } = displayConfig;
6233
6506
  const methods = useFormContext();
6234
6507
  const { properties } = schema;
6235
- // Custom error renderer for validation errors with i18n support
6236
- const renderValidationErrors = (validationErrors) => {
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))) }));
6238
- };
6239
6508
  const renderColumns = ({ order, keys, ignore, include, }) => {
6240
6509
  const included = include.length > 0 ? include : keys;
6241
6510
  const not_exist = included.filter((columnA) => !order.some((columnB) => columnA === columnB));
@@ -6275,19 +6544,17 @@ const FormBody = () => {
6275
6544
  setIsConfirming(false);
6276
6545
  }, variant: 'subtle', children: translate.t('cancel') }), jsx(Button$1, { onClick: () => {
6277
6546
  onFormSubmit(validatedData);
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)}` })] }) }) })] })] })) })) }))] }));
6547
+ }, 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 && customErrorRenderer && customErrorRenderer(error)] }));
6280
6548
  }
6281
6549
  return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
6282
6550
  return (jsx(ColumnRenderer
6283
6551
  // @ts-expect-error find suitable types
6284
6552
  , {
6285
6553
  // @ts-expect-error find suitable types
6286
- properties: properties, prefix: ``, column }, `form-input-${column}`));
6554
+ properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
6287
6555
  }) }), jsxs(Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
6288
6556
  methods.reset();
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)}` })] }) }) })] })] })) })) }))] }));
6557
+ }, variant: 'subtle', children: translate.t('reset') })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
6291
6558
  };
6292
6559
 
6293
6560
  const FormTitle = () => {
@@ -6300,12 +6567,15 @@ const DefaultForm = ({ formConfig, }) => {
6300
6567
  return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
6301
6568
  };
6302
6569
 
6303
- const useForm = ({ preLoadedValues, keyPrefix, namespace }) => {
6570
+ const useForm = ({ preLoadedValues, keyPrefix, namespace, schema, }) => {
6304
6571
  const form = useForm$1({
6305
6572
  values: preLoadedValues,
6573
+ resolver: schema ? ajvResolver(schema) : undefined,
6574
+ mode: 'onBlur',
6575
+ reValidateMode: 'onBlur',
6306
6576
  });
6307
6577
  const [idMap, setIdMap] = useState({});
6308
- const translate = useTranslation(namespace || "", { keyPrefix });
6578
+ const translate = useTranslation(namespace || '', { keyPrefix });
6309
6579
  return {
6310
6580
  form,
6311
6581
  idMap,
@@ -6375,15 +6645,15 @@ const buildErrorMessages = (config) => {
6375
6645
  }
6376
6646
  // Add global fallback error messages
6377
6647
  const globalKeys = [
6378
- "minLength",
6379
- "maxLength",
6380
- "pattern",
6381
- "minimum",
6382
- "maximum",
6383
- "multipleOf",
6384
- "format",
6385
- "type",
6386
- "enum",
6648
+ 'minLength',
6649
+ 'maxLength',
6650
+ 'pattern',
6651
+ 'minimum',
6652
+ 'maximum',
6653
+ 'multipleOf',
6654
+ 'format',
6655
+ 'type',
6656
+ 'enum',
6387
6657
  ];
6388
6658
  globalKeys.forEach((key) => {
6389
6659
  if (config[key]) {
@@ -6392,6 +6662,46 @@ const buildErrorMessages = (config) => {
6392
6662
  });
6393
6663
  return result;
6394
6664
  };
6665
+ /**
6666
+ * Converts buildErrorMessages result to ajv-errors compatible format
6667
+ */
6668
+ const convertToAjvErrorsFormat = (errorMessages) => {
6669
+ const result = {};
6670
+ // Convert required field errors
6671
+ if (errorMessages.required) {
6672
+ result.required = errorMessages.required;
6673
+ }
6674
+ // Convert properties errors to ajv-errors format
6675
+ if (errorMessages.properties) {
6676
+ result.properties = {};
6677
+ Object.keys(errorMessages.properties).forEach((fieldName) => {
6678
+ const fieldErrors = errorMessages.properties[fieldName];
6679
+ result.properties[fieldName] = {};
6680
+ Object.keys(fieldErrors).forEach((keyword) => {
6681
+ result.properties[fieldName][keyword] =
6682
+ fieldErrors[keyword];
6683
+ });
6684
+ });
6685
+ }
6686
+ // Add global fallback errors
6687
+ const globalKeys = [
6688
+ 'minLength',
6689
+ 'maxLength',
6690
+ 'pattern',
6691
+ 'minimum',
6692
+ 'maximum',
6693
+ 'multipleOf',
6694
+ 'format',
6695
+ 'type',
6696
+ 'enum',
6697
+ ];
6698
+ globalKeys.forEach((key) => {
6699
+ if (errorMessages[key]) {
6700
+ result[key] = errorMessages[key];
6701
+ }
6702
+ });
6703
+ return result;
6704
+ };
6395
6705
  /**
6396
6706
  * Helper function to build required field errors
6397
6707
  *
@@ -6434,10 +6744,10 @@ const buildErrorMessages = (config) => {
6434
6744
  * // Result: { username: "user.username.field_required", email: "user.email.field_required" }
6435
6745
  * ```
6436
6746
  */
6437
- const buildRequiredErrors = (fields, messageOrGenerator, keyPrefix = "") => {
6747
+ const buildRequiredErrors = (fields, messageOrGenerator, keyPrefix = '') => {
6438
6748
  const result = {};
6439
6749
  fields.forEach((field) => {
6440
- if (typeof messageOrGenerator === "function") {
6750
+ if (typeof messageOrGenerator === 'function') {
6441
6751
  const message = messageOrGenerator(field);
6442
6752
  result[field] = keyPrefix ? `${keyPrefix}.${message}` : message;
6443
6753
  }
@@ -6508,11 +6818,14 @@ const buildFieldErrors = (config) => {
6508
6818
  * ```
6509
6819
  */
6510
6820
  const createErrorMessage = (required, properties, globalFallbacks) => {
6511
- return buildErrorMessages({
6821
+ const config = {
6512
6822
  required,
6513
6823
  properties,
6514
- ...globalFallbacks,
6515
- });
6824
+ };
6825
+ if (globalFallbacks) {
6826
+ Object.assign(config, globalFallbacks);
6827
+ }
6828
+ return buildErrorMessages(config);
6516
6829
  };
6517
6830
 
6518
6831
  const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) => {
@@ -6531,4 +6844,4 @@ const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) =
6531
6844
  }
6532
6845
  };
6533
6846
 
6534
- export { CardHeader, DataDisplay, DataTable, DataTableServer, DefaultCardTitle, DefaultForm, DefaultTable, DensityToggleButton, EditSortingButton, EmptyState$1 as EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, createErrorMessage, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
6847
+ export { CardHeader, DataDisplay, DataTable, DataTableServer, DefaultCardTitle, DefaultForm, DefaultTable, DensityToggleButton, EditSortingButton, EmptyState$1 as EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };