@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.
- package/dist/index.d.ts +133 -126
- package/dist/index.js +567 -253
- package/dist/index.mjs +569 -256
- package/dist/types/components/Form/SchemaFormContext.d.ts +3 -2
- package/dist/types/components/Form/components/fields/BooleanPicker.d.ts +1 -1
- package/dist/types/components/Form/components/fields/ColumnRenderer.d.ts +3 -2
- package/dist/types/components/Form/components/fields/DateTimePicker.d.ts +1 -1
- package/dist/types/components/Form/components/fields/FilePicker.d.ts +1 -1
- package/dist/types/components/Form/components/fields/ObjectInput.d.ts +1 -1
- package/dist/types/components/Form/components/fields/RecordInput.d.ts +1 -1
- package/dist/types/components/Form/components/fields/StringInputField.d.ts +1 -1
- package/dist/types/components/Form/components/fields/TextAreaInput.d.ts +1 -1
- package/dist/types/components/Form/components/fields/TimePicker.d.ts +1 -1
- package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +3 -0
- package/dist/types/components/Form/useForm.d.ts +4 -2
- package/dist/types/components/Form/utils/ajvResolver.d.ts +13 -0
- package/dist/types/components/Form/utils/buildErrorMessages.d.ts +5 -1
- package/dist/types/components/Form/utils/getFieldError.d.ts +6 -0
- package/dist/types/components/Form/utils/useFormI18n.d.ts +1 -1
- package/dist/types/components/Form/utils/validateData.d.ts +2 -2
- package/dist/types/components/ui/field.d.ts +3 -3
- package/package.json +1 -1
- package/dist/types/components/Controls/DensityFeature.d.ts +0 -23
- package/dist/types/components/Controls/DensityToggleButton.d.ts +0 -6
- package/dist/types/components/Controls/EditFilterButton.d.ts +0 -9
- package/dist/types/components/Controls/EditOrderButton.d.ts +0 -7
- package/dist/types/components/Controls/EditSortingButton.d.ts +0 -7
- package/dist/types/components/Controls/EditViewButton.d.ts +0 -7
- package/dist/types/components/Controls/FilterDialog.d.ts +0 -5
- package/dist/types/components/Controls/PageSizeControl.d.ts +0 -4
- package/dist/types/components/Controls/Pagination.d.ts +0 -1
- package/dist/types/components/Controls/ResetFilteringButton.d.ts +0 -4
- package/dist/types/components/Controls/ResetSelectionButton.d.ts +0 -4
- package/dist/types/components/Controls/ResetSortingButton.d.ts +0 -4
- package/dist/types/components/Controls/RowCountText.d.ts +0 -1
- package/dist/types/components/Controls/SelectAllRowsToggle.d.ts +0 -8
- package/dist/types/components/Controls/TablePagination.d.ts +0 -1
- package/dist/types/components/Controls/ViewDialog.d.ts +0 -5
- package/dist/types/components/DataTable/CardHeader.d.ts +0 -13
- package/dist/types/components/DataTable/DataDisplay.d.ts +0 -6
- package/dist/types/components/DataTable/ReloadButton.d.ts +0 -5
- package/dist/types/components/DataTable/Table.d.ts +0 -10
- package/dist/types/components/DataTable/TableBody.d.ts +0 -21
- package/dist/types/components/DataTable/TableCardContainer.d.ts +0 -7
- package/dist/types/components/DataTable/TableCards.d.ts +0 -11
- package/dist/types/components/DataTable/TableComponent.d.ts +0 -6
- package/dist/types/components/DataTable/TableControls.d.ts +0 -21
- package/dist/types/components/DataTable/TableFilter.d.ts +0 -1
- package/dist/types/components/DataTable/TableFilterTags.d.ts +0 -1
- package/dist/types/components/DataTable/TableFilters.d.ts +0 -1
- package/dist/types/components/DataTable/TableFooter.d.ts +0 -9
- package/dist/types/components/DataTable/TableHeader.d.ts +0 -13
- package/dist/types/components/DataTable/TableLoadingComponent.d.ts +0 -5
- package/dist/types/components/DataTable/TableOrderer.d.ts +0 -1
- package/dist/types/components/DataTable/TableSelector.d.ts +0 -1
- package/dist/types/components/DataTable/TableSorter.d.ts +0 -1
- package/dist/types/components/DataTable/TableViewer.d.ts +0 -1
- package/dist/types/components/DataTable/TextCell.d.ts +0 -10
- package/dist/types/components/DataTable/components/EmptyState.d.ts +0 -5
- package/dist/types/components/DataTable/components/ErrorAlert.d.ts +0 -4
- package/dist/types/components/DataTable/components/RecordDisplay.d.ts +0 -9
- package/dist/types/components/DataTable/components/TextCell.d.ts +0 -10
- package/dist/types/components/Filter/DateRangeFilter.d.ts +0 -9
- package/dist/types/components/Filter/FilterOptions.d.ts +0 -4
- package/dist/types/components/Form/Form.d.ts +0 -36
- package/dist/types/components/Form/components/ArrayRenderer.d.ts +0 -7
- package/dist/types/components/Form/components/BooleanPicker.d.ts +0 -7
- package/dist/types/components/Form/components/ColumnRenderer.d.ts +0 -7
- package/dist/types/components/Form/components/DatePicker.d.ts +0 -7
- package/dist/types/components/Form/components/EnumPicker.d.ts +0 -8
- package/dist/types/components/Form/components/FilePicker.d.ts +0 -5
- package/dist/types/components/Form/components/IdPicker.d.ts +0 -8
- package/dist/types/components/Form/components/IdViewer.d.ts +0 -5
- package/dist/types/components/Form/components/NumberInputField.d.ts +0 -7
- package/dist/types/components/Form/components/ObjectInput.d.ts +0 -7
- package/dist/types/components/Form/components/RecordInput.d.ts +0 -7
- package/dist/types/components/Form/components/SchemaRenderer.d.ts +0 -7
- package/dist/types/components/Form/components/StringInputField.d.ts +0 -20
- package/dist/types/components/Form/components/TagPicker.d.ts +0 -30
- package/dist/types/components/Form/utils/translateWrapper.d.ts +0 -6
- 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,
|
|
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
|
|
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
|
-
|
|
3701
|
-
|
|
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: `${
|
|
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
|
-
//
|
|
3788
|
-
|
|
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 && (
|
|
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 =
|
|
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 (
|
|
3895
|
-
gridRow,
|
|
3896
|
-
|
|
3897
|
-
|
|
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 (
|
|
4131
|
-
gridRow, children:
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
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,
|
|
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,
|
|
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`)) })) }))] })] }) })] })
|
|
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 =
|
|
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 ??
|
|
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:
|
|
4677
|
-
return (jsx(Card.Root, { variant:
|
|
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:
|
|
4682
|
-
}) })
|
|
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, {})] }) })] }))] }) })] })
|
|
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
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
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 =
|
|
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:
|
|
4955
|
-
base:
|
|
4956
|
-
_dark:
|
|
4957
|
-
}, gap: "4", padding:
|
|
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
|
|
4963
|
-
|
|
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 =
|
|
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:
|
|
4976
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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`) })
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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:
|
|
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 =
|
|
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:
|
|
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:
|
|
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 ?
|
|
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 ===
|
|
5609
|
+
if (meridiem === 'pm' && hour !== 12) {
|
|
5387
5610
|
newHour = hour + 12;
|
|
5388
5611
|
}
|
|
5389
|
-
return dayjs()
|
|
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 (
|
|
5400
|
-
gridRow,
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
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 =
|
|
5841
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
|
|
5612
5842
|
// with timezone
|
|
5613
|
-
dateFormat =
|
|
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 (
|
|
5645
|
-
gridRow, children:
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
defaultValue:
|
|
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
|
-
|
|
5679
|
-
|
|
5945
|
+
forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
|
|
5946
|
+
formI18n.translate.t(`common.forward_button`, {
|
|
5947
|
+
defaultValue: 'Forward',
|
|
5680
5948
|
}),
|
|
5681
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
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 &&
|
|
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 &&
|
|
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 ||
|
|
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
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
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 ===
|
|
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
|
-
|
|
6821
|
+
const config = {
|
|
6512
6822
|
required,
|
|
6513
6823
|
properties,
|
|
6514
|
-
|
|
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 };
|