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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3677,8 +3677,8 @@ const AccordionItem = react.Accordion.Item;
3677
3677
  //@ts-expect-error TODO: find appropriate type
3678
3678
  const SchemaFormContext = React.createContext({
3679
3679
  schema: {},
3680
- serverUrl: "",
3681
- requestUrl: "",
3680
+ serverUrl: '',
3681
+ requestUrl: '',
3682
3682
  order: [],
3683
3683
  ignore: [],
3684
3684
  include: [],
@@ -3734,11 +3734,11 @@ const idPickerSanityCheck = (column, foreign_key) => {
3734
3734
  throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
3735
3735
  }
3736
3736
  };
3737
- const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, displayConfig = {
3737
+ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, customSuccessRenderer, displayConfig = {
3738
3738
  showSubmitButton: true,
3739
3739
  showResetButton: true,
3740
3740
  showTitle: true,
3741
- }, }) => {
3741
+ }, dateTimePickerLabels, idPickerLabels, enumPickerLabels, }) => {
3742
3742
  const [isSuccess, setIsSuccess] = React.useState(false);
3743
3743
  const [isError, setIsError] = React.useState(false);
3744
3744
  const [isSubmiting, setIsSubmiting] = React.useState(false);
@@ -3772,7 +3772,11 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3772
3772
  setError,
3773
3773
  getUpdatedData,
3774
3774
  customErrorRenderer,
3775
+ customSuccessRenderer,
3775
3776
  displayConfig,
3777
+ dateTimePickerLabels,
3778
+ idPickerLabels,
3779
+ enumPickerLabels,
3776
3780
  }, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
3777
3781
  };
3778
3782
 
@@ -4031,14 +4035,16 @@ dayjs.extend(utc);
4031
4035
  dayjs.extend(timezone);
4032
4036
  const DatePicker = ({ column, schema, prefix }) => {
4033
4037
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4034
- const { timezone } = useSchemaContext();
4038
+ const { timezone, dateTimePickerLabels } = useSchemaContext();
4035
4039
  const formI18n = useFormI18n(column, prefix);
4036
- const { required, gridColumn = "span 12", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD", dateFormat = "YYYY-MM-DD", } = schema;
4040
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
4037
4041
  const isRequired = required?.some((columnId) => columnId === column);
4038
4042
  const colLabel = formI18n.colLabel;
4039
4043
  const [open, setOpen] = React.useState(false);
4040
4044
  const selectedDate = watch(colLabel);
4041
- const displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
4045
+ const displayDate = dayjs(selectedDate)
4046
+ .tz(timezone)
4047
+ .format(displayDateFormat);
4042
4048
  React.useEffect(() => {
4043
4049
  try {
4044
4050
  if (selectedDate) {
@@ -4062,45 +4068,83 @@ const DatePicker = ({ column, schema, prefix }) => {
4062
4068
  console.error(e);
4063
4069
  }
4064
4070
  }, [selectedDate, dateFormat, colLabel, setValue]);
4065
- return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
4071
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4066
4072
  gridRow, children: [jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4067
4073
  setOpen(true);
4068
- }, justifyContent: "start", children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4074
+ }, justifyContent: 'start', children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ''] }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1, { selected: new Date(selectedDate), onDateSelected: ({ date }) => {
4069
4075
  setValue(colLabel, dayjs(date).format(dateFormat));
4070
4076
  setOpen(false);
4071
4077
  }, labels: {
4072
- monthNamesShort: [
4073
- formI18n.translate.t(`common.month_1`, { defaultValue: "January" }),
4074
- formI18n.translate.t(`common.month_2`, { defaultValue: "February" }),
4075
- formI18n.translate.t(`common.month_3`, { defaultValue: "March" }),
4076
- formI18n.translate.t(`common.month_4`, { defaultValue: "April" }),
4077
- formI18n.translate.t(`common.month_5`, { defaultValue: "May" }),
4078
- formI18n.translate.t(`common.month_6`, { defaultValue: "June" }),
4079
- formI18n.translate.t(`common.month_7`, { defaultValue: "July" }),
4080
- formI18n.translate.t(`common.month_8`, { defaultValue: "August" }),
4081
- formI18n.translate.t(`common.month_9`, { defaultValue: "September" }),
4082
- formI18n.translate.t(`common.month_10`, { defaultValue: "October" }),
4083
- formI18n.translate.t(`common.month_11`, { defaultValue: "November" }),
4084
- formI18n.translate.t(`common.month_12`, { defaultValue: "December" }),
4078
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
4079
+ formI18n.translate.t(`common.month_1`, {
4080
+ defaultValue: 'January',
4081
+ }),
4082
+ formI18n.translate.t(`common.month_2`, {
4083
+ defaultValue: 'February',
4084
+ }),
4085
+ formI18n.translate.t(`common.month_3`, {
4086
+ defaultValue: 'March',
4087
+ }),
4088
+ formI18n.translate.t(`common.month_4`, {
4089
+ defaultValue: 'April',
4090
+ }),
4091
+ formI18n.translate.t(`common.month_5`, {
4092
+ defaultValue: 'May',
4093
+ }),
4094
+ formI18n.translate.t(`common.month_6`, {
4095
+ defaultValue: 'June',
4096
+ }),
4097
+ formI18n.translate.t(`common.month_7`, {
4098
+ defaultValue: 'July',
4099
+ }),
4100
+ formI18n.translate.t(`common.month_8`, {
4101
+ defaultValue: 'August',
4102
+ }),
4103
+ formI18n.translate.t(`common.month_9`, {
4104
+ defaultValue: 'September',
4105
+ }),
4106
+ formI18n.translate.t(`common.month_10`, {
4107
+ defaultValue: 'October',
4108
+ }),
4109
+ formI18n.translate.t(`common.month_11`, {
4110
+ defaultValue: 'November',
4111
+ }),
4112
+ formI18n.translate.t(`common.month_12`, {
4113
+ defaultValue: 'December',
4114
+ }),
4085
4115
  ],
4086
- weekdayNamesShort: [
4087
- formI18n.translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
4088
- formI18n.translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
4089
- formI18n.translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
4116
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
4117
+ formI18n.translate.t(`common.weekday_1`, {
4118
+ defaultValue: 'Sun',
4119
+ }),
4120
+ formI18n.translate.t(`common.weekday_2`, {
4121
+ defaultValue: 'Mon',
4122
+ }),
4123
+ formI18n.translate.t(`common.weekday_3`, {
4124
+ defaultValue: 'Tue',
4125
+ }),
4090
4126
  formI18n.translate.t(`common.weekday_4`, {
4091
- defaultValue: "Wed",
4127
+ defaultValue: 'Wed',
4128
+ }),
4129
+ formI18n.translate.t(`common.weekday_5`, {
4130
+ defaultValue: 'Thu',
4131
+ }),
4132
+ formI18n.translate.t(`common.weekday_6`, {
4133
+ defaultValue: 'Fri',
4134
+ }),
4135
+ formI18n.translate.t(`common.weekday_7`, {
4136
+ defaultValue: 'Sat',
4092
4137
  }),
4093
- formI18n.translate.t(`common.weekday_5`, { defaultValue: "Thu" }),
4094
- formI18n.translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
4095
- formI18n.translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
4096
4138
  ],
4097
- backButtonLabel: formI18n.translate.t(`common.back_button`, {
4098
- defaultValue: "Back",
4099
- }),
4100
- forwardButtonLabel: formI18n.translate.t(`common.forward_button`, {
4101
- defaultValue: "Forward",
4102
- }),
4103
- } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
4139
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ??
4140
+ formI18n.translate.t(`common.back_button`, {
4141
+ defaultValue: 'Back',
4142
+ }),
4143
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ??
4144
+ formI18n.translate.t(`common.forward_button`, {
4145
+ defaultValue: 'Forward',
4146
+ }),
4147
+ } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
4104
4148
  };
4105
4149
 
4106
4150
  function filterArray(array, searchTerm) {
@@ -4115,10 +4159,10 @@ function filterArray(array, searchTerm) {
4115
4159
 
4116
4160
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
4117
4161
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4118
- const { translate } = useSchemaContext();
4162
+ const { translate, enumPickerLabels } = useSchemaContext();
4119
4163
  const { required, variant } = schema;
4120
4164
  const isRequired = required?.some((columnId) => columnId === column);
4121
- const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
4165
+ const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
4122
4166
  const [searchText, setSearchText] = React.useState();
4123
4167
  const [limit, setLimit] = React.useState(10);
4124
4168
  const [openSearchResult, setOpenSearchResult] = React.useState();
@@ -4133,9 +4177,9 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4133
4177
  setSearchText(event.target.value);
4134
4178
  setLimit(10);
4135
4179
  };
4136
- if (variant === "radio") {
4137
- return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4138
- gridRow, children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? "").map((item) => {
4180
+ if (variant === 'radio') {
4181
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4182
+ gridRow, children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
4139
4183
  return (jsxRuntime.jsxs(react.RadioGroup.Item, { onClick: () => {
4140
4184
  if (!isMultiple) {
4141
4185
  setOpenSearchResult(false);
@@ -4149,8 +4193,8 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4149
4193
  : translate.t(removeIndex(`${colLabel}.${item}`)) })] }, `${colLabel}-${item}`));
4150
4194
  }) }) }) }));
4151
4195
  }
4152
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4153
- gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
4196
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4197
+ gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
4154
4198
  const item = enumValue;
4155
4199
  if (!!item === false) {
4156
4200
  return jsxRuntime.jsx(jsxRuntime.Fragment, {});
@@ -4160,18 +4204,20 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4160
4204
  }, children: !!renderDisplay === true
4161
4205
  ? renderDisplay(item)
4162
4206
  : translate.t(removeIndex(`${colLabel}.${item}`)) }, item));
4163
- }), jsxRuntime.jsx(Tag, { size: "lg", cursor: "pointer", onClick: () => {
4207
+ }), jsxRuntime.jsx(Tag, { size: "lg", cursor: 'pointer', onClick: () => {
4164
4208
  setOpenSearchResult(true);
4165
- }, children: translate.t(removeIndex(`${colLabel}.add_more`)) }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
4209
+ }, children: enumPickerLabels?.addMore ??
4210
+ translate.t(removeIndex(`${colLabel}.add_more`)) }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: 'outline', onClick: () => {
4166
4211
  setOpenSearchResult(true);
4167
- }, justifyContent: "start", children: !!watchEnum === false
4168
- ? ""
4169
- : translate.t(removeIndex(`${colLabel}.${watchEnum ?? "null"}`)) })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
4212
+ }, justifyContent: 'start', children: !!watchEnum === false
4213
+ ? ''
4214
+ : translate.t(removeIndex(`${colLabel}.${watchEnum ?? 'null'}`)) })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: 'bottom-start' }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: 'grid', gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: enumPickerLabels?.typeToSearch ??
4215
+ translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
4170
4216
  onSearchChange(event);
4171
4217
  setOpenSearchResult(true);
4172
- }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), showTotalAndLimit && (jsxRuntime.jsx(react.Text, { children: `${translate.t(removeIndex(`${colLabel}.total`))}: ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` })), jsxRuntime.jsxs(react.Grid, { overflow: "auto", maxHeight: "20rem", children: [jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children: dataList
4218
+ }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), showTotalAndLimit && (jsxRuntime.jsx(react.Text, { children: `${enumPickerLabels?.total ?? translate.t(removeIndex(`${colLabel}.total`))}: ${count}, ${enumPickerLabels?.showing ?? translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` })), jsxRuntime.jsxs(react.Grid, { overflow: 'auto', maxHeight: '20rem', children: [jsxRuntime.jsx(react.Flex, { flexFlow: 'column wrap', children: dataList
4173
4219
  .filter((item) => {
4174
- const searchTerm = (searchText || "").toLowerCase();
4220
+ const searchTerm = (searchText || '').toLowerCase();
4175
4221
  if (!searchTerm)
4176
4222
  return true;
4177
4223
  // Check if the original enum value contains the search text
@@ -4191,7 +4237,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4191
4237
  const selected = isMultiple
4192
4238
  ? watchEnums.some((enumValue) => item === enumValue)
4193
4239
  : watchEnum == item;
4194
- return (jsxRuntime.jsx(react.Box, { cursor: "pointer", onClick: () => {
4240
+ return (jsxRuntime.jsx(react.Box, { cursor: 'pointer', onClick: () => {
4195
4241
  if (!isMultiple) {
4196
4242
  setOpenSearchResult(false);
4197
4243
  setValue(colLabel, item);
@@ -4199,10 +4245,11 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
4199
4245
  }
4200
4246
  const newSet = new Set([...(watchEnums ?? []), item]);
4201
4247
  setValue(colLabel, [...newSet]);
4202
- }, ...(selected ? { color: "colorPalette.400/50" } : {}), children: !!renderDisplay === true
4248
+ }, ...(selected ? { color: 'colorPalette.400/50' } : {}), children: !!renderDisplay === true
4203
4249
  ? renderDisplay(item)
4204
4250
  : translate.t(removeIndex(`${colLabel}.${item}`)) }, `${colLabel}-${item}`));
4205
- }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4251
+ }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: enumPickerLabels?.emptySearchResult ??
4252
+ translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] })] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4206
4253
  };
4207
4254
 
4208
4255
  function isEnteringWindow(_ref) {
@@ -4615,12 +4662,12 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
4615
4662
 
4616
4663
  const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4617
4664
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4618
- const { serverUrl, idMap, setIdMap, schema: parentSchema, } = useSchemaContext();
4665
+ const { serverUrl, idMap, setIdMap, schema: parentSchema, idPickerLabels, } = useSchemaContext();
4619
4666
  const formI18n = useFormI18n(column, prefix);
4620
- const { required, gridColumn = "span 12", gridRow = "span 1", renderDisplay, foreign_key, } = schema;
4667
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
4621
4668
  const isRequired = required?.some((columnId) => columnId === column);
4622
4669
  const { table, column: column_ref, display_column, customQueryFn, } = foreign_key;
4623
- const [searchText, setSearchText] = React.useState("");
4670
+ const [searchText, setSearchText] = React.useState('');
4624
4671
  const [limit, setLimit] = React.useState(10);
4625
4672
  const [openSearchResult, setOpenSearchResult] = React.useState();
4626
4673
  const [page, setPage] = React.useState(0);
@@ -4634,7 +4681,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4634
4681
  queryFn: async () => {
4635
4682
  if (customQueryFn) {
4636
4683
  const { data, idMap } = await customQueryFn({
4637
- searching: searchText ?? "",
4684
+ searching: searchText ?? '',
4638
4685
  limit: limit,
4639
4686
  offset: page * limit,
4640
4687
  });
@@ -4645,7 +4692,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4645
4692
  }
4646
4693
  const data = await getTableData({
4647
4694
  serverUrl,
4648
- searching: searchText ?? "",
4695
+ searching: searchText ?? '',
4649
4696
  in_table: table,
4650
4697
  limit: limit,
4651
4698
  offset: page * limit,
@@ -4675,7 +4722,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4675
4722
  queryFn: async () => {
4676
4723
  if (customQueryFn) {
4677
4724
  const { data, idMap } = await customQueryFn({
4678
- searching: watchIds.join(","),
4725
+ searching: watchIds.join(','),
4679
4726
  limit: isMultiple ? watchIds.length : 1,
4680
4727
  offset: 0,
4681
4728
  });
@@ -4687,7 +4734,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4687
4734
  if (!watchId && (!watchIds || watchIds.length === 0)) {
4688
4735
  return { data: [] };
4689
4736
  }
4690
- const searchValue = isMultiple ? watchIds.join(",") : watchId;
4737
+ const searchValue = isMultiple ? watchIds.join(',') : watchId;
4691
4738
  const data = await getTableData({
4692
4739
  serverUrl,
4693
4740
  searching: searchValue,
@@ -4724,7 +4771,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4724
4771
  React.useEffect(() => {
4725
4772
  if (openSearchResult) {
4726
4773
  // Reset search text when opening the popover
4727
- setSearchText("");
4774
+ setSearchText('');
4728
4775
  // Reset page to first page
4729
4776
  setPage(0);
4730
4777
  // Fetch initial data
@@ -4750,44 +4797,44 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4750
4797
  const count = data?.count ?? 0;
4751
4798
  const getPickedValue = () => {
4752
4799
  if (Object.keys(idMap).length <= 0) {
4753
- return "";
4800
+ return '';
4754
4801
  }
4755
4802
  const record = idMap[watchId];
4756
4803
  if (record === undefined) {
4757
- return "";
4804
+ return '';
4758
4805
  }
4759
4806
  if (!!renderDisplay === true) {
4760
4807
  return renderDisplay(record);
4761
4808
  }
4762
4809
  return record[display_column];
4763
4810
  };
4764
- return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: "stretch", gridColumn,
4765
- gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: 1, children: [watchIds.map((id) => {
4811
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4812
+ gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchIds.map((id) => {
4766
4813
  const item = idMap[id];
4767
4814
  if (item === undefined) {
4768
- return (jsxRuntime.jsx(react.Text, { children: formI18n.t('undefined') }, id));
4815
+ return (jsxRuntime.jsx(react.Text, { children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
4769
4816
  }
4770
4817
  return (jsxRuntime.jsx(Tag, { closable: true, onClick: () => {
4771
4818
  setValue(colLabel, watchIds.filter((itemId) => itemId !== item[column_ref]));
4772
4819
  }, children: !!renderDisplay === true
4773
4820
  ? renderDisplay(item)
4774
4821
  : item[display_column] }, id));
4775
- }), jsxRuntime.jsx(Tag, { cursor: "pointer", onClick: () => {
4822
+ }), jsxRuntime.jsx(Tag, { cursor: 'pointer', onClick: () => {
4776
4823
  setOpenSearchResult(true);
4777
- }, children: formI18n.t('add_more') })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
4824
+ }, children: idPickerLabels?.addMore ?? formI18n.t('add_more') })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: 'outline', onClick: () => {
4778
4825
  setOpenSearchResult(true);
4779
- }, justifyContent: "start", children: queryDefault.isLoading ? jsxRuntime.jsx(react.Spinner, { size: "sm" }) : getPickedValue() })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: formI18n.t('type_to_search'), onChange: onSearchChange, autoComplete: "off", ref: ref, value: searchText }), jsxRuntime.jsx(PopoverTitle, {}), openSearchResult && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, {}), isError && (jsxRuntime.jsx(react.Icon, { color: "red.400", children: jsxRuntime.jsx(bi.BiError, {}) })), jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", children: [jsxRuntime.jsx(InfoTip, { children: `${formI18n.t('total')} ${count}, ${formI18n.t('showing')} ${limit} ${formI18n.t('per_page', { defaultValue: 'per page' })}` }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxRuntime.jsxs(react.Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/", " ", count > 0
4826
+ }, justifyContent: 'start', children: queryDefault.isLoading ? jsxRuntime.jsx(react.Spinner, { size: "sm" }) : getPickedValue() })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: 'bottom-start', strategy: 'fixed' }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: 'grid', gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: idPickerLabels?.typeToSearch ?? formI18n.t('type_to_search'), onChange: onSearchChange, autoComplete: "off", ref: ref, value: searchText }), jsxRuntime.jsx(PopoverTitle, {}), openSearchResult && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, {}), isError && (jsxRuntime.jsx(react.Icon, { color: 'red.400', children: jsxRuntime.jsx(bi.BiError, {}) })), jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxRuntime.jsxs(react.Flex, { alignItems: "center", gap: "2", children: [jsxRuntime.jsx(InfoTip, { children: `${idPickerLabels?.total ?? formI18n.t('total')} ${count}, ${idPickerLabels?.showing ?? formI18n.t('showing')} ${limit} ${idPickerLabels?.perPage ?? formI18n.t('per_page', { defaultValue: 'per page' })}` }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", fontWeight: "bold", children: [count, jsxRuntime.jsxs(react.Text, { as: "span", fontSize: "xs", ml: "1", color: "gray.500", children: ["/", ' ', count > 0
4780
4827
  ? `${page * limit + 1}-${Math.min((page + 1) * limit, count)}`
4781
- : "0"] })] })] }), jsxRuntime.jsx(react.Box, { children: jsxRuntime.jsxs("select", { value: limit, onChange: handleLimitChange, style: {
4782
- padding: "4px 8px",
4783
- borderRadius: "4px",
4784
- border: "1px solid #ccc",
4785
- fontSize: "14px",
4786
- }, children: [jsxRuntime.jsx("option", { value: "5", children: "5" }), jsxRuntime.jsx("option", { value: "10", children: "10" }), jsxRuntime.jsx("option", { value: "20", children: "20" }), jsxRuntime.jsx("option", { value: "30", children: "30" })] }) })] }), jsxRuntime.jsx(react.Grid, { overflowY: "auto", children: dataList.length > 0 ? (jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", gap: 1, children: dataList.map((item) => {
4828
+ : '0'] })] })] }), jsxRuntime.jsx(react.Box, { children: jsxRuntime.jsxs("select", { value: limit, onChange: handleLimitChange, style: {
4829
+ padding: '4px 8px',
4830
+ borderRadius: '4px',
4831
+ border: '1px solid #ccc',
4832
+ fontSize: '14px',
4833
+ }, children: [jsxRuntime.jsx("option", { value: "5", children: "5" }), jsxRuntime.jsx("option", { value: "10", children: "10" }), jsxRuntime.jsx("option", { value: "20", children: "20" }), jsxRuntime.jsx("option", { value: "30", children: "30" })] }) })] }), jsxRuntime.jsx(react.Grid, { overflowY: 'auto', children: dataList.length > 0 ? (jsxRuntime.jsx(react.Flex, { flexFlow: 'column wrap', gap: 1, children: dataList.map((item) => {
4787
4834
  const selected = isMultiple
4788
4835
  ? watchIds.some((id) => item[column_ref] === id)
4789
4836
  : watchId === item[column_ref];
4790
- return (jsxRuntime.jsx(react.Box, { cursor: "pointer", onClick: () => {
4837
+ return (jsxRuntime.jsx(react.Box, { cursor: 'pointer', onClick: () => {
4791
4838
  if (!isMultiple) {
4792
4839
  setOpenSearchResult(false);
4793
4840
  setValue(colLabel, item[column_ref]);
@@ -4803,15 +4850,17 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4803
4850
  setValue(colLabel, [...newSet]);
4804
4851
  }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
4805
4852
  ? {
4806
- color: "colorPalette.400/50",
4807
- fontWeight: "bold",
4853
+ color: 'colorPalette.400/50',
4854
+ fontWeight: 'bold',
4808
4855
  }
4809
4856
  : {}), children: !!renderDisplay === true
4810
4857
  ? renderDisplay(item)
4811
4858
  : item[display_column] }, item[column_ref]));
4812
4859
  }) })) : (jsxRuntime.jsx(react.Text, { children: searchText
4813
- ? formI18n.t('empty_search_result')
4814
- : formI18n.t('initial_results') })) }), jsxRuntime.jsx(PaginationRoot, { justifySelf: "center", count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxRuntime.jsxs(react.HStack, { gap: "4", children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), count > 0 && jsxRuntime.jsx(PaginationPageText, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
4860
+ ? idPickerLabels?.emptySearchResult ??
4861
+ formI18n.t('empty_search_result')
4862
+ : idPickerLabels?.initialResults ??
4863
+ formI18n.t('initial_results') })) }), jsxRuntime.jsx(PaginationRoot, { justifySelf: 'center', count: count, pageSize: limit, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxRuntime.jsxs(react.HStack, { gap: "4", children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), count > 0 && jsxRuntime.jsx(PaginationPageText, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
4815
4864
  };
4816
4865
 
4817
4866
  const NumberInputRoot = React__namespace.forwardRef(function NumberInput(props, ref) {
@@ -5498,7 +5547,7 @@ dayjs.extend(utc);
5498
5547
  dayjs.extend(timezone);
5499
5548
  const DateTimePicker = ({ column, schema, prefix, }) => {
5500
5549
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5501
- const { timezone } = useSchemaContext();
5550
+ const { timezone, dateTimePickerLabels } = useSchemaContext();
5502
5551
  const formI18n = useFormI18n(column, prefix);
5503
5552
  const { required, gridColumn = "span 12", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss",
5504
5553
  // with timezone
@@ -5539,7 +5588,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
5539
5588
  }, justifyContent: "start", children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${displayDate}` : ""] }) }), jsxRuntime.jsx(PopoverContent, { minW: "450px", children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DateTimePicker$1, { value: selectedDate, onChange: (date) => {
5540
5589
  setValue(colLabel, dayjs(date).tz(timezone).format(dateFormat));
5541
5590
  }, timezone: timezone, labels: {
5542
- monthNamesShort: [
5591
+ monthNamesShort: dateTimePickerLabels?.monthNamesShort ?? [
5543
5592
  formI18n.translate.t(`common.month_1`, { defaultValue: "January" }),
5544
5593
  formI18n.translate.t(`common.month_2`, { defaultValue: "February" }),
5545
5594
  formI18n.translate.t(`common.month_3`, { defaultValue: "March" }),
@@ -5553,7 +5602,7 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
5553
5602
  formI18n.translate.t(`common.month_11`, { defaultValue: "November" }),
5554
5603
  formI18n.translate.t(`common.month_12`, { defaultValue: "December" }),
5555
5604
  ],
5556
- weekdayNamesShort: [
5605
+ weekdayNamesShort: dateTimePickerLabels?.weekdayNamesShort ?? [
5557
5606
  formI18n.translate.t(`common.weekday_1`, { defaultValue: "Sun" }),
5558
5607
  formI18n.translate.t(`common.weekday_2`, { defaultValue: "Mon" }),
5559
5608
  formI18n.translate.t(`common.weekday_3`, { defaultValue: "Tue" }),
@@ -5564,10 +5613,10 @@ const DateTimePicker = ({ column, schema, prefix, }) => {
5564
5613
  formI18n.translate.t(`common.weekday_6`, { defaultValue: "Fri" }),
5565
5614
  formI18n.translate.t(`common.weekday_7`, { defaultValue: "Sat" }),
5566
5615
  ],
5567
- backButtonLabel: formI18n.translate.t(`common.back_button`, {
5616
+ backButtonLabel: dateTimePickerLabels?.backButtonLabel ?? formI18n.translate.t(`common.back_button`, {
5568
5617
  defaultValue: "Back",
5569
5618
  }),
5570
- forwardButtonLabel: formI18n.translate.t(`common.forward_button`, {
5619
+ forwardButtonLabel: dateTimePickerLabels?.forwardButtonLabel ?? formI18n.translate.t(`common.forward_button`, {
5571
5620
  defaultValue: "Forward",
5572
5621
  }),
5573
5622
  } })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: formI18n.required() }))] }));
@@ -6093,7 +6142,7 @@ const SubmitButton = () => {
6093
6142
  };
6094
6143
 
6095
6144
  const FormBody = () => {
6096
- const { schema, requestUrl, order, ignore, include, onSubmit, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, displayConfig, } = useSchemaContext();
6145
+ const { schema, requestUrl, order, ignore, include, onSubmit, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, } = useSchemaContext();
6097
6146
  const { showSubmitButton, showResetButton } = displayConfig;
6098
6147
  const methods = reactHookForm.useFormContext();
6099
6148
  const { properties } = schema;
@@ -6190,15 +6239,19 @@ const FormBody = () => {
6190
6239
  include,
6191
6240
  });
6192
6241
  if (isSuccess) {
6193
- return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Title, { children: translate.t("submit_success") }) })] }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { onClick: async () => {
6194
- setIsError(false);
6195
- setIsSubmiting(false);
6196
- setIsSuccess(false);
6197
- setIsConfirming(false);
6198
- setValidatedData(undefined);
6199
- const data = await getUpdatedData();
6200
- methods.reset(data);
6201
- }, formNoValidate: true, children: translate.t("submit_again") }) })] }));
6242
+ const resetHandler = async () => {
6243
+ setIsError(false);
6244
+ setIsSubmiting(false);
6245
+ setIsSuccess(false);
6246
+ setIsConfirming(false);
6247
+ setValidatedData(undefined);
6248
+ const data = await getUpdatedData();
6249
+ methods.reset(data);
6250
+ };
6251
+ if (customSuccessRenderer) {
6252
+ return customSuccessRenderer(resetHandler);
6253
+ }
6254
+ return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Title, { children: translate.t("submit_success") }) })] }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { onClick: resetHandler, formNoValidate: true, children: translate.t("submit_again") }) })] }));
6202
6255
  }
6203
6256
  if (isConfirming) {
6204
6257
  return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: 4, gridTemplateColumns: "repeat(12, 1fr)", gridTemplateRows: "repeat(12, max-content)", autoFlow: "row", children: ordered.map((column) => {
@@ -6236,12 +6289,12 @@ const DefaultForm = ({ formConfig, }) => {
6236
6289
  return (jsxRuntime.jsx(FormRoot, { ...formConfig, children: jsxRuntime.jsxs(react.Grid, { gap: "2", children: [showTitle && jsxRuntime.jsx(FormTitle, {}), jsxRuntime.jsx(FormBody, {})] }) }));
6237
6290
  };
6238
6291
 
6239
- const useForm = ({ preLoadedValues, keyPrefix }) => {
6292
+ const useForm = ({ preLoadedValues, keyPrefix, namespace }) => {
6240
6293
  const form = reactHookForm.useForm({
6241
6294
  values: preLoadedValues,
6242
6295
  });
6243
6296
  const [idMap, setIdMap] = React.useState({});
6244
- const translate = reactI18next.useTranslation("", { keyPrefix });
6297
+ const translate = reactI18next.useTranslation(namespace || "", { keyPrefix });
6245
6298
  return {
6246
6299
  form,
6247
6300
  idMap,
@@ -6250,6 +6303,207 @@ const useForm = ({ preLoadedValues, keyPrefix }) => {
6250
6303
  };
6251
6304
  };
6252
6305
 
6306
+ /**
6307
+ * Type definitions for error message configuration
6308
+ */
6309
+ /**
6310
+ * Schema-level error message builder
6311
+ *
6312
+ * Builds a complete errorMessage object compatible with ajv-errors plugin.
6313
+ * Supports both i18n translation keys and plain string messages.
6314
+ *
6315
+ * @param config - Error message configuration
6316
+ * @returns Complete errorMessage object for JSON Schema
6317
+ *
6318
+ * @example
6319
+ * ```typescript
6320
+ * // Simple required field errors
6321
+ * const errorMessage = buildErrorMessages({
6322
+ * required: {
6323
+ * username: "Username is required",
6324
+ * email: "user.email.field_required" // i18n key
6325
+ * }
6326
+ * });
6327
+ *
6328
+ * // With validation rules
6329
+ * const errorMessage = buildErrorMessages({
6330
+ * required: {
6331
+ * password: "Password is required"
6332
+ * },
6333
+ * properties: {
6334
+ * password: {
6335
+ * minLength: "Password must be at least 8 characters",
6336
+ * pattern: "Password must contain letters and numbers"
6337
+ * },
6338
+ * age: {
6339
+ * minimum: "Must be 18 or older",
6340
+ * maximum: "Must be under 120"
6341
+ * }
6342
+ * }
6343
+ * });
6344
+ *
6345
+ * // With global fallbacks
6346
+ * const errorMessage = buildErrorMessages({
6347
+ * required: {
6348
+ * email: "Email is required"
6349
+ * },
6350
+ * minLength: "This field is too short", // applies to all fields
6351
+ * minimum: "Value is too small"
6352
+ * });
6353
+ * ```
6354
+ */
6355
+ const buildErrorMessages = (config) => {
6356
+ const result = {};
6357
+ // Add required field errors
6358
+ if (config.required && Object.keys(config.required).length > 0) {
6359
+ result.required = config.required;
6360
+ }
6361
+ // Add field-specific validation errors
6362
+ if (config.properties && Object.keys(config.properties).length > 0) {
6363
+ result.properties = config.properties;
6364
+ }
6365
+ // Add global fallback error messages
6366
+ const globalKeys = [
6367
+ "minLength",
6368
+ "maxLength",
6369
+ "pattern",
6370
+ "minimum",
6371
+ "maximum",
6372
+ "multipleOf",
6373
+ "format",
6374
+ "type",
6375
+ "enum",
6376
+ ];
6377
+ globalKeys.forEach((key) => {
6378
+ if (config[key]) {
6379
+ result[key] = config[key];
6380
+ }
6381
+ });
6382
+ return result;
6383
+ };
6384
+ /**
6385
+ * Helper function to build required field errors
6386
+ *
6387
+ * Simplifies creating required field error messages, especially useful
6388
+ * for generating i18n translation keys following a pattern.
6389
+ *
6390
+ * @param fields - Array of required field names
6391
+ * @param messageOrGenerator - Either a string template or function to generate messages
6392
+ * @returns Required field error configuration
6393
+ *
6394
+ * @example
6395
+ * ```typescript
6396
+ * // Plain string messages
6397
+ * const required = buildRequiredErrors(
6398
+ * ["username", "email", "password"],
6399
+ * (field) => `${field} is required`
6400
+ * );
6401
+ * // Result: { username: "username is required", email: "email is required", ... }
6402
+ *
6403
+ * // i18n translation keys
6404
+ * const required = buildRequiredErrors(
6405
+ * ["username", "email"],
6406
+ * (field) => `user.${field}.field_required`
6407
+ * );
6408
+ * // Result: { username: "user.username.field_required", email: "user.email.field_required" }
6409
+ *
6410
+ * // Same message for all fields
6411
+ * const required = buildRequiredErrors(
6412
+ * ["username", "email"],
6413
+ * "This field is required"
6414
+ * );
6415
+ * // Result: { username: "This field is required", email: "This field is required" }
6416
+ *
6417
+ * // With keyPrefix for i18n
6418
+ * const required = buildRequiredErrors(
6419
+ * ["username", "email"],
6420
+ * (field) => `${field}.field_required`,
6421
+ * "user"
6422
+ * );
6423
+ * // Result: { username: "user.username.field_required", email: "user.email.field_required" }
6424
+ * ```
6425
+ */
6426
+ const buildRequiredErrors = (fields, messageOrGenerator, keyPrefix = "") => {
6427
+ const result = {};
6428
+ fields.forEach((field) => {
6429
+ if (typeof messageOrGenerator === "function") {
6430
+ const message = messageOrGenerator(field);
6431
+ result[field] = keyPrefix ? `${keyPrefix}.${message}` : message;
6432
+ }
6433
+ else {
6434
+ result[field] = messageOrGenerator;
6435
+ }
6436
+ });
6437
+ return result;
6438
+ };
6439
+ /**
6440
+ * Helper function to build field-specific validation errors
6441
+ *
6442
+ * Creates property-specific error messages for multiple fields at once.
6443
+ *
6444
+ * @param config - Maps field names to their validation error configurations
6445
+ * @returns Properties error configuration
6446
+ *
6447
+ * @example
6448
+ * ```typescript
6449
+ * const properties = buildFieldErrors({
6450
+ * username: {
6451
+ * minLength: "Username must be at least 3 characters",
6452
+ * pattern: "Username can only contain letters and numbers"
6453
+ * },
6454
+ * age: {
6455
+ * minimum: "Must be 18 or older",
6456
+ * maximum: "Must be under 120"
6457
+ * },
6458
+ * email: {
6459
+ * format: "Please enter a valid email address"
6460
+ * }
6461
+ * });
6462
+ * ```
6463
+ */
6464
+ const buildFieldErrors = (config) => {
6465
+ return config;
6466
+ };
6467
+ /**
6468
+ * Helper function to create a complete error message configuration in one call
6469
+ *
6470
+ * Convenient wrapper that combines required and validation errors.
6471
+ *
6472
+ * @param required - Required field error messages
6473
+ * @param properties - Field-specific validation error messages
6474
+ * @param globalFallbacks - Global fallback error messages
6475
+ * @returns Complete error message configuration
6476
+ *
6477
+ * @example
6478
+ * ```typescript
6479
+ * const errorMessage = createErrorMessage(
6480
+ * {
6481
+ * username: "Username is required",
6482
+ * email: "Email is required"
6483
+ * },
6484
+ * {
6485
+ * username: {
6486
+ * minLength: "Username must be at least 3 characters"
6487
+ * },
6488
+ * email: {
6489
+ * format: "Please enter a valid email"
6490
+ * }
6491
+ * },
6492
+ * {
6493
+ * minLength: "This field is too short",
6494
+ * format: "Invalid format"
6495
+ * }
6496
+ * );
6497
+ * ```
6498
+ */
6499
+ const createErrorMessage = (required, properties, globalFallbacks) => {
6500
+ return buildErrorMessages({
6501
+ required,
6502
+ properties,
6503
+ ...globalFallbacks,
6504
+ });
6505
+ };
6506
+
6253
6507
  const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) => {
6254
6508
  if (!selectable) {
6255
6509
  return [...selectedDates];
@@ -6307,6 +6561,10 @@ exports.TableSorter = TableSorter;
6307
6561
  exports.TableViewer = TableViewer;
6308
6562
  exports.TextCell = TextCell;
6309
6563
  exports.ViewDialog = ViewDialog;
6564
+ exports.buildErrorMessages = buildErrorMessages;
6565
+ exports.buildFieldErrors = buildFieldErrors;
6566
+ exports.buildRequiredErrors = buildRequiredErrors;
6567
+ exports.createErrorMessage = createErrorMessage;
6310
6568
  exports.getColumns = getColumns;
6311
6569
  exports.getMultiDates = getMultiDates;
6312
6570
  exports.getRangeDates = getRangeDates;