@bsol-oss/react-datatable5 12.0.0-beta.63 → 12.0.0-beta.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -253,7 +253,7 @@ interface DataResponse<T = unknown> extends Result<T> {
253
253
  }
254
254
  declare const useDataTableServer: <TData>({ url, default: { sorting: defaultSorting, pagination: defaultPagination, rowSelection: defaultRowSelection, columnFilters: defaultColumnFilters, columnOrder: defaultColumnOrder, columnVisibility: defaultColumnVisibility, globalFilter: defaultGlobalFilter, density: defaultDensity, }, keyPrefix, }: UseDataTableServerProps) => UseDataTableServerReturn<TData>;
255
255
 
256
- interface DataTableServerProps<TData extends DataResponse = DataResponse<unknown>> {
256
+ interface DataTableServerProps<TData = unknown> {
257
257
  children: ReactNode | ReactNode[];
258
258
  /**
259
259
  * Column definitions for the table.
@@ -282,10 +282,10 @@ interface DataTableServerProps<TData extends DataResponse = DataResponse<unknown
282
282
  setColumnOrder: OnChangeFn<ColumnOrderState>;
283
283
  setDensity: OnChangeFn<DensityState>;
284
284
  setColumnVisibility: OnChangeFn<VisibilityState>;
285
- query: UseQueryResult<TData>;
285
+ query: UseQueryResult<DataResponse<TData>>;
286
286
  url: string;
287
287
  translate: UseTranslationResponse<any, any>;
288
- tableLabel: DataTableLabel;
288
+ tableLabel?: DataTableLabel;
289
289
  }
290
290
  /**
291
291
  * DataTableServer will create a context to hold all values to
@@ -298,7 +298,7 @@ interface DataTableServerProps<TData extends DataResponse = DataResponse<unknown
298
298
  *
299
299
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
300
300
  */
301
- declare function DataTableServer<TData extends DataResponse = DataResponse<unknown>>({ columns, enableRowSelection, enableMultiRowSelection, enableSubRowSelection, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel, }: DataTableServerProps<TData>): react_jsx_runtime.JSX.Element;
301
+ declare function DataTableServer<TData = unknown>({ columns, enableRowSelection, enableMultiRowSelection, enableSubRowSelection, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel, }: DataTableServerProps<TData>): react_jsx_runtime.JSX.Element;
302
302
 
303
303
  interface TableControlsProps {
304
304
  totalText?: string;
@@ -547,6 +547,11 @@ interface FormRootProps<TData extends FieldValues> {
547
547
  requestOptions?: AxiosRequestConfig;
548
548
  getUpdatedData?: () => TData | Promise<TData> | void;
549
549
  customErrorRenderer?: (error: unknown) => ReactNode;
550
+ displayConfig?: {
551
+ showSubmitButton?: boolean;
552
+ showResetButton?: boolean;
553
+ showTitle?: boolean;
554
+ };
550
555
  }
551
556
  interface CustomJSONSchema7Definition extends JSONSchema7 {
552
557
  variant: string;
@@ -563,13 +568,13 @@ declare const idPickerSanityCheck: (column: string, foreign_key?: {
563
568
  column?: string | undefined;
564
569
  display_column?: string | undefined;
565
570
  } | undefined) => void;
566
- declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
571
+ declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, displayConfig, }: FormRootProps<TData>) => react_jsx_runtime.JSX.Element;
567
572
 
568
573
  interface DefaultFormProps<TData extends FieldValues> {
569
574
  formConfig: Omit<FormRootProps<TData>, "children">;
570
575
  showTitle?: boolean;
571
576
  }
572
- declare const DefaultForm: <TData extends FieldValues>({ formConfig, showTitle, }: DefaultFormProps<TData>) => react_jsx_runtime.JSX.Element;
577
+ declare const DefaultForm: <TData extends FieldValues>({ formConfig, }: DefaultFormProps<TData>) => react_jsx_runtime.JSX.Element;
573
578
 
574
579
  declare const FormTitle: () => react_jsx_runtime.JSX.Element;
575
580
 
package/dist/index.js CHANGED
@@ -29,13 +29,13 @@ var gr = require('react-icons/gr');
29
29
  var reactI18next = require('react-i18next');
30
30
  var axios = require('axios');
31
31
  var reactHookForm = require('react-hook-form');
32
+ var Ajv = require('ajv');
33
+ var addFormats = require('ajv-formats');
34
+ var addErrors = require('ajv-errors');
32
35
  var dayjs = require('dayjs');
33
36
  var utc = require('dayjs/plugin/utc');
34
37
  var timezone = require('dayjs/plugin/timezone');
35
38
  var ti = require('react-icons/ti');
36
- var Ajv = require('ajv');
37
- var addFormats = require('ajv-formats');
38
- var addErrors = require('ajv-errors');
39
39
 
40
40
  function _interopNamespaceDefault(e) {
41
41
  var n = Object.create(null);
@@ -3693,6 +3693,11 @@ const SchemaFormContext = React.createContext({
3693
3693
  rowNumber: 0,
3694
3694
  requestOptions: {},
3695
3695
  timezone: 'Asia/Hong_Kong',
3696
+ displayConfig: {
3697
+ showSubmitButton: true,
3698
+ showResetButton: true,
3699
+ showTitle: true,
3700
+ },
3696
3701
  });
3697
3702
 
3698
3703
  const useSchemaContext = () => {
@@ -3703,6 +3708,23 @@ const clearEmptyString = (object) => {
3703
3708
  return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3704
3709
  };
3705
3710
 
3711
+ const validateData = (data, schema) => {
3712
+ const ajv = new Ajv({
3713
+ strict: false,
3714
+ allErrors: true,
3715
+ });
3716
+ addFormats(ajv);
3717
+ addErrors(ajv);
3718
+ const validate = ajv.compile(schema);
3719
+ const validationResult = validate(data);
3720
+ const errors = validate.errors;
3721
+ return {
3722
+ isValid: validationResult,
3723
+ validate,
3724
+ errors,
3725
+ };
3726
+ };
3727
+
3706
3728
  const idPickerSanityCheck = (column, foreign_key) => {
3707
3729
  if (!!foreign_key == false) {
3708
3730
  throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
@@ -3718,7 +3740,11 @@ const idPickerSanityCheck = (column, foreign_key) => {
3718
3740
  throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
3719
3741
  }
3720
3742
  };
3721
- const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, }) => {
3743
+ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, displayConfig = {
3744
+ showSubmitButton: true,
3745
+ showResetButton: true,
3746
+ showTitle: true,
3747
+ }, }) => {
3722
3748
  const [isSuccess, setIsSuccess] = React.useState(false);
3723
3749
  const [isError, setIsError] = React.useState(false);
3724
3750
  const [isSubmiting, setIsSubmiting] = React.useState(false);
@@ -3752,6 +3778,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3752
3778
  setError,
3753
3779
  getUpdatedData,
3754
3780
  customErrorRenderer,
3781
+ displayConfig,
3755
3782
  }, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
3756
3783
  };
3757
3784
 
@@ -5942,16 +5969,12 @@ const SubmitButton = () => {
5942
5969
  const methods = reactHookForm.useFormContext();
5943
5970
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5944
5971
  const onValid = (data) => {
5945
- // Validate data using AJV before proceeding to confirmation
5946
- const validate = new Ajv({
5947
- strict: false,
5948
- allErrors: true,
5949
- }).compile(schema);
5950
- const validationResult = validate(data);
5951
- // @ts-expect-error TODO: find appropriate type
5952
- const errors = validationResult.errors;
5953
- if (errors && errors.length > 0) {
5954
- setError(errors);
5972
+ const { isValid, errors } = validateData(data, schema);
5973
+ if (!isValid) {
5974
+ setError({
5975
+ type: "validation",
5976
+ errors,
5977
+ });
5955
5978
  setIsError(true);
5956
5979
  return;
5957
5980
  }
@@ -5966,7 +5989,8 @@ const SubmitButton = () => {
5966
5989
  };
5967
5990
 
5968
5991
  const FormBody = () => {
5969
- const { schema, requestUrl, order, ignore, include, onSubmit, rowNumber, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, } = useSchemaContext();
5992
+ 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();
5993
+ const { showSubmitButton, showResetButton } = displayConfig;
5970
5994
  const methods = reactHookForm.useFormContext();
5971
5995
  const { properties } = schema;
5972
5996
  const onBeforeSubmit = () => {
@@ -5982,24 +6006,11 @@ const FormBody = () => {
5982
6006
  const onSubmitSuccess = () => {
5983
6007
  setIsSuccess(true);
5984
6008
  };
5985
- // Enhanced validation function using AJV with i18n support
5986
6009
  const validateFormData = (data) => {
5987
6010
  try {
5988
- const ajv = new Ajv({
5989
- strict: false,
5990
- allErrors: true,
5991
- });
5992
- addFormats(ajv);
5993
- addErrors(ajv);
5994
- const validate = ajv.compile(schema);
5995
- const validationResult = validate(data);
5996
- const errors = validate.errors;
5997
- console.log({
5998
- isValid: validationResult,
5999
- errors,
6000
- }, "plkdfs");
6011
+ const { isValid, errors } = validateData(data, schema);
6001
6012
  return {
6002
- isValid: validationResult,
6013
+ isValid,
6003
6014
  errors,
6004
6015
  };
6005
6016
  }
@@ -6059,10 +6070,7 @@ const FormBody = () => {
6059
6070
  };
6060
6071
  // Custom error renderer for validation errors with i18n support
6061
6072
  const renderValidationErrors = (validationErrors) => {
6062
- return (jsxRuntime.jsx(AccordionRoot, { backgroundColor: {
6063
- base: "red.50",
6064
- _dark: "red.950",
6065
- }, p: "4", colorPalette: "red", collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "validation-errors", children: [jsxRuntime.jsx(AccordionItemTrigger, { children: translate.t("validation_error") }), jsxRuntime.jsx(AccordionItemContent, { display: "flex", flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxRuntime.jsxs(react.AlertRoot, { status: "error", display: "flex", alignItems: "center", children: [jsxRuntime.jsx(react.AlertIndicator, {}), jsxRuntime.jsx(react.AlertContent, { children: jsxRuntime.jsx(react.AlertDescription, { children: err.message }) })] }))) })] }) }));
6073
+ return (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxRuntime.jsxs(react.Alert.Root, { status: "error", display: "flex", alignItems: "center", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Description, { children: err.message }) })] }, index))) }));
6066
6074
  };
6067
6075
  const renderColumns = ({ order, keys, ignore, include, }) => {
6068
6076
  const included = include.length > 0 ? include : keys;
@@ -6078,7 +6086,7 @@ const FormBody = () => {
6078
6086
  include,
6079
6087
  });
6080
6088
  if (isSuccess) {
6081
- 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.Title, { children: translate.t("submit_success") })] }), jsxRuntime.jsx(react.Flex, { justifyContent: "end", children: jsxRuntime.jsx(react.Button, { onClick: async () => {
6089
+ 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 () => {
6082
6090
  setIsError(false);
6083
6091
  setIsSubmiting(false);
6084
6092
  setIsSuccess(false);
@@ -6100,7 +6108,7 @@ const FormBody = () => {
6100
6108
  }, variant: "subtle", children: translate.t("cancel") }), jsxRuntime.jsx(react.Button, { onClick: () => {
6101
6109
  onFormSubmit(validatedData);
6102
6110
  }, children: translate.t("confirm") })] }), isSubmiting && (jsxRuntime.jsx(react.Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsxRuntime.jsx(react.Center, { h: "full", children: jsxRuntime.jsx(react.Spinner, { color: "teal.500" }) }) })), isError && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: error?.type === "validation" &&
6103
- error?.errors ? (renderValidationErrors(error.errors)) : (jsxRuntime.jsx(react.Alert.Root, { status: "error", children: jsxRuntime.jsx(react.Alert.Title, { children: jsxRuntime.jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "b", children: [jsxRuntime.jsxs(AccordionItemTrigger, { children: [jsxRuntime.jsx(react.Alert.Indicator, {}), `${error}`] }), jsxRuntime.jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) }) })) })) }))] }));
6111
+ error?.errors ? (renderValidationErrors(error.errors)) : (jsxRuntime.jsxs(react.Alert.Root, { status: "error", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsxs(react.Alert.Content, { children: [jsxRuntime.jsx(react.Alert.Title, { children: "Error" }), jsxRuntime.jsx(react.Alert.Description, { children: jsxRuntime.jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "b", children: [jsxRuntime.jsx(AccordionItemTrigger, { children: `${error}` }), jsxRuntime.jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) })] })] })) })) }))] }));
6104
6112
  }
6105
6113
  return (jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: ordered.map((column) => {
6106
6114
  return (jsxRuntime.jsx(ColumnRenderer
@@ -6108,10 +6116,10 @@ const FormBody = () => {
6108
6116
  , {
6109
6117
  // @ts-expect-error find suitable types
6110
6118
  properties: properties, prefix: ``, column }, `form-input-${column}`));
6111
- }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [jsxRuntime.jsx(react.Button, { onClick: () => {
6119
+ }) }), jsxRuntime.jsxs(react.Flex, { justifyContent: "end", gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
6112
6120
  methods.reset();
6113
- }, variant: "subtle", children: translate.t("reset") }), jsxRuntime.jsx(SubmitButton, {})] }), isError && error?.type === "validation" && (jsxRuntime.jsx(react.Box, { mt: 4, children: error?.errors &&
6114
- renderValidationErrors(error.errors) }))] }));
6121
+ }, variant: "subtle", children: translate.t("reset") })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: error?.type === "validation" &&
6122
+ error?.errors ? (renderValidationErrors(error.errors)) : (jsxRuntime.jsxs(react.Alert.Root, { status: "error", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsxs(react.Alert.Content, { children: [jsxRuntime.jsx(react.Alert.Title, { children: "Error" }), jsxRuntime.jsx(react.Alert.Description, { children: jsxRuntime.jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxRuntime.jsxs(AccordionItem, { value: "b", children: [jsxRuntime.jsx(AccordionItemTrigger, { children: `${error}` }), jsxRuntime.jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) })] })] })) })) }))] }));
6115
6123
  };
6116
6124
 
6117
6125
  const FormTitle = () => {
@@ -6119,7 +6127,8 @@ const FormTitle = () => {
6119
6127
  return jsxRuntime.jsx(react.Heading, { children: translate.t("title") });
6120
6128
  };
6121
6129
 
6122
- const DefaultForm = ({ formConfig, showTitle = true, }) => {
6130
+ const DefaultForm = ({ formConfig, }) => {
6131
+ const { showTitle } = formConfig.displayConfig ?? {};
6123
6132
  return (jsxRuntime.jsx(FormRoot, { ...formConfig, children: jsxRuntime.jsxs(react.Grid, { gap: "2", children: [showTitle && jsxRuntime.jsx(FormTitle, {}), jsxRuntime.jsx(FormBody, {})] }) }));
6124
6133
  };
6125
6134
 
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Accordion, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center, AlertRoot, AlertIndicator, AlertContent, AlertDescription, Heading } from '@chakra-ui/react';
2
+ import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Accordion, 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';
@@ -28,13 +28,13 @@ import { GrAscend, GrDescend } from 'react-icons/gr';
28
28
  import { useTranslation } from 'react-i18next';
29
29
  import axios from 'axios';
30
30
  import { FormProvider, useFormContext, useForm as useForm$1 } from 'react-hook-form';
31
+ import Ajv from 'ajv';
32
+ import addFormats from 'ajv-formats';
33
+ import addErrors from 'ajv-errors';
31
34
  import dayjs from 'dayjs';
32
35
  import utc from 'dayjs/plugin/utc';
33
36
  import timezone from 'dayjs/plugin/timezone';
34
37
  import { TiDeleteOutline } from 'react-icons/ti';
35
- import Ajv from 'ajv';
36
- import addFormats from 'ajv-formats';
37
- import addErrors from 'ajv-errors';
38
38
 
39
39
  const DataTableContext = createContext({
40
40
  table: {},
@@ -3673,6 +3673,11 @@ const SchemaFormContext = createContext({
3673
3673
  rowNumber: 0,
3674
3674
  requestOptions: {},
3675
3675
  timezone: 'Asia/Hong_Kong',
3676
+ displayConfig: {
3677
+ showSubmitButton: true,
3678
+ showResetButton: true,
3679
+ showTitle: true,
3680
+ },
3676
3681
  });
3677
3682
 
3678
3683
  const useSchemaContext = () => {
@@ -3683,6 +3688,23 @@ const clearEmptyString = (object) => {
3683
3688
  return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
3684
3689
  };
3685
3690
 
3691
+ const validateData = (data, schema) => {
3692
+ const ajv = new Ajv({
3693
+ strict: false,
3694
+ allErrors: true,
3695
+ });
3696
+ addFormats(ajv);
3697
+ addErrors(ajv);
3698
+ const validate = ajv.compile(schema);
3699
+ const validationResult = validate(data);
3700
+ const errors = validate.errors;
3701
+ return {
3702
+ isValid: validationResult,
3703
+ validate,
3704
+ errors,
3705
+ };
3706
+ };
3707
+
3686
3708
  const idPickerSanityCheck = (column, foreign_key) => {
3687
3709
  if (!!foreign_key == false) {
3688
3710
  throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
@@ -3698,7 +3720,11 @@ const idPickerSanityCheck = (column, foreign_key) => {
3698
3720
  throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
3699
3721
  }
3700
3722
  };
3701
- const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, }) => {
3723
+ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, children, order = [], ignore = [], include = [], onSubmit = undefined, rowNumber = undefined, requestOptions = {}, getUpdatedData = () => { }, customErrorRenderer, displayConfig = {
3724
+ showSubmitButton: true,
3725
+ showResetButton: true,
3726
+ showTitle: true,
3727
+ }, }) => {
3702
3728
  const [isSuccess, setIsSuccess] = useState(false);
3703
3729
  const [isError, setIsError] = useState(false);
3704
3730
  const [isSubmiting, setIsSubmiting] = useState(false);
@@ -3732,6 +3758,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
3732
3758
  setError,
3733
3759
  getUpdatedData,
3734
3760
  customErrorRenderer,
3761
+ displayConfig,
3735
3762
  }, children: jsx(FormProvider, { ...form, children: children }) }));
3736
3763
  };
3737
3764
 
@@ -5922,16 +5949,12 @@ const SubmitButton = () => {
5922
5949
  const methods = useFormContext();
5923
5950
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5924
5951
  const onValid = (data) => {
5925
- // Validate data using AJV before proceeding to confirmation
5926
- const validate = new Ajv({
5927
- strict: false,
5928
- allErrors: true,
5929
- }).compile(schema);
5930
- const validationResult = validate(data);
5931
- // @ts-expect-error TODO: find appropriate type
5932
- const errors = validationResult.errors;
5933
- if (errors && errors.length > 0) {
5934
- setError(errors);
5952
+ const { isValid, errors } = validateData(data, schema);
5953
+ if (!isValid) {
5954
+ setError({
5955
+ type: "validation",
5956
+ errors,
5957
+ });
5935
5958
  setIsError(true);
5936
5959
  return;
5937
5960
  }
@@ -5946,7 +5969,8 @@ const SubmitButton = () => {
5946
5969
  };
5947
5970
 
5948
5971
  const FormBody = () => {
5949
- const { schema, requestUrl, order, ignore, include, onSubmit, rowNumber, translate, requestOptions, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, setError, getUpdatedData, customErrorRenderer, } = useSchemaContext();
5972
+ 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();
5973
+ const { showSubmitButton, showResetButton } = displayConfig;
5950
5974
  const methods = useFormContext();
5951
5975
  const { properties } = schema;
5952
5976
  const onBeforeSubmit = () => {
@@ -5962,24 +5986,11 @@ const FormBody = () => {
5962
5986
  const onSubmitSuccess = () => {
5963
5987
  setIsSuccess(true);
5964
5988
  };
5965
- // Enhanced validation function using AJV with i18n support
5966
5989
  const validateFormData = (data) => {
5967
5990
  try {
5968
- const ajv = new Ajv({
5969
- strict: false,
5970
- allErrors: true,
5971
- });
5972
- addFormats(ajv);
5973
- addErrors(ajv);
5974
- const validate = ajv.compile(schema);
5975
- const validationResult = validate(data);
5976
- const errors = validate.errors;
5977
- console.log({
5978
- isValid: validationResult,
5979
- errors,
5980
- }, "plkdfs");
5991
+ const { isValid, errors } = validateData(data, schema);
5981
5992
  return {
5982
- isValid: validationResult,
5993
+ isValid,
5983
5994
  errors,
5984
5995
  };
5985
5996
  }
@@ -6039,10 +6050,7 @@ const FormBody = () => {
6039
6050
  };
6040
6051
  // Custom error renderer for validation errors with i18n support
6041
6052
  const renderValidationErrors = (validationErrors) => {
6042
- return (jsx(AccordionRoot, { backgroundColor: {
6043
- base: "red.50",
6044
- _dark: "red.950",
6045
- }, p: "4", colorPalette: "red", collapsible: true, defaultValue: [], children: jsxs(AccordionItem, { value: "validation-errors", children: [jsx(AccordionItemTrigger, { children: translate.t("validation_error") }), jsx(AccordionItemContent, { display: "flex", flexFlow: "column", gap: "2", children: validationErrors.map((err, index) => (jsxs(AlertRoot, { status: "error", display: "flex", alignItems: "center", children: [jsx(AlertIndicator, {}), jsx(AlertContent, { children: jsx(AlertDescription, { children: err.message }) })] }))) })] }) }));
6053
+ 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))) }));
6046
6054
  };
6047
6055
  const renderColumns = ({ order, keys, ignore, include, }) => {
6048
6056
  const included = include.length > 0 ? include : keys;
@@ -6058,7 +6066,7 @@ const FormBody = () => {
6058
6066
  include,
6059
6067
  });
6060
6068
  if (isSuccess) {
6061
- return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Title, { children: translate.t("submit_success") })] }), jsx(Flex, { justifyContent: "end", children: jsx(Button$1, { onClick: async () => {
6069
+ return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Content, { children: jsx(Alert.Title, { children: translate.t("submit_success") }) })] }), jsx(Flex, { justifyContent: "end", children: jsx(Button$1, { onClick: async () => {
6062
6070
  setIsError(false);
6063
6071
  setIsSubmiting(false);
6064
6072
  setIsSuccess(false);
@@ -6080,7 +6088,7 @@ const FormBody = () => {
6080
6088
  }, variant: "subtle", children: translate.t("cancel") }), jsx(Button$1, { onClick: () => {
6081
6089
  onFormSubmit(validatedData);
6082
6090
  }, children: translate.t("confirm") })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && (jsx(Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsx(Fragment, { children: error?.type === "validation" &&
6083
- error?.errors ? (renderValidationErrors(error.errors)) : (jsx(Alert.Root, { status: "error", children: jsx(Alert.Title, { children: jsx(AccordionRoot, { collapsible: true, defaultValue: [], children: jsxs(AccordionItem, { value: "b", children: [jsxs(AccordionItemTrigger, { children: [jsx(Alert.Indicator, {}), `${error}`] }), jsx(AccordionItemContent, { children: `${JSON.stringify(error)}` })] }) }) }) })) })) }))] }));
6091
+ 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)}` })] }) }) })] })] })) })) }))] }));
6084
6092
  }
6085
6093
  return (jsxs(Flex, { flexFlow: "column", gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: ordered.map((column) => {
6086
6094
  return (jsx(ColumnRenderer
@@ -6088,10 +6096,10 @@ const FormBody = () => {
6088
6096
  , {
6089
6097
  // @ts-expect-error find suitable types
6090
6098
  properties: properties, prefix: ``, column }, `form-input-${column}`));
6091
- }) }), jsxs(Flex, { justifyContent: "end", gap: "2", children: [jsx(Button$1, { onClick: () => {
6099
+ }) }), jsxs(Flex, { justifyContent: "end", gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
6092
6100
  methods.reset();
6093
- }, variant: "subtle", children: translate.t("reset") }), jsx(SubmitButton, {})] }), isError && error?.type === "validation" && (jsx(Box, { mt: 4, children: error?.errors &&
6094
- renderValidationErrors(error.errors) }))] }));
6101
+ }, variant: "subtle", children: translate.t("reset") })), showSubmitButton && jsx(SubmitButton, {})] }), isError && (jsx(Fragment, { children: customErrorRenderer ? (customErrorRenderer(error)) : (jsx(Fragment, { children: error?.type === "validation" &&
6102
+ 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)}` })] }) }) })] })] })) })) }))] }));
6095
6103
  };
6096
6104
 
6097
6105
  const FormTitle = () => {
@@ -6099,7 +6107,8 @@ const FormTitle = () => {
6099
6107
  return jsx(Heading, { children: translate.t("title") });
6100
6108
  };
6101
6109
 
6102
- const DefaultForm = ({ formConfig, showTitle = true, }) => {
6110
+ const DefaultForm = ({ formConfig, }) => {
6111
+ const { showTitle } = formConfig.displayConfig ?? {};
6103
6112
  return (jsx(FormRoot, { ...formConfig, children: jsxs(Grid, { gap: "2", children: [showTitle && jsx(FormTitle, {}), jsx(FormBody, {})] }) }));
6104
6113
  };
6105
6114
 
@@ -5,7 +5,7 @@ import { DensityState } from "./controls/DensityFeature";
5
5
  import { DataTableLabel } from "./context/DataTableContext";
6
6
  import { DataResponse } from "./useDataTableServer";
7
7
  import { UseTranslationResponse } from "react-i18next";
8
- export interface DataTableServerProps<TData extends DataResponse = DataResponse<unknown>> {
8
+ export interface DataTableServerProps<TData = unknown> {
9
9
  children: ReactNode | ReactNode[];
10
10
  /**
11
11
  * Column definitions for the table.
@@ -34,10 +34,10 @@ export interface DataTableServerProps<TData extends DataResponse = DataResponse<
34
34
  setColumnOrder: OnChangeFn<ColumnOrderState>;
35
35
  setDensity: OnChangeFn<DensityState>;
36
36
  setColumnVisibility: OnChangeFn<VisibilityState>;
37
- query: UseQueryResult<TData>;
37
+ query: UseQueryResult<DataResponse<TData>>;
38
38
  url: string;
39
39
  translate: UseTranslationResponse<any, any>;
40
- tableLabel: DataTableLabel;
40
+ tableLabel?: DataTableLabel;
41
41
  }
42
42
  /**
43
43
  * DataTableServer will create a context to hold all values to
@@ -50,4 +50,4 @@ export interface DataTableServerProps<TData extends DataResponse = DataResponse<
50
50
  *
51
51
  * @link https://tanstack.com/table/latest/docs/guide/column-defs
52
52
  */
53
- export declare function DataTableServer<TData extends DataResponse = DataResponse<unknown>>({ columns, enableRowSelection, enableMultiRowSelection, enableSubRowSelection, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel, }: DataTableServerProps<TData>): import("react/jsx-runtime").JSX.Element;
53
+ export declare function DataTableServer<TData = unknown>({ columns, enableRowSelection, enableMultiRowSelection, enableSubRowSelection, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel, }: DataTableServerProps<TData>): import("react/jsx-runtime").JSX.Element;
@@ -31,5 +31,10 @@ export interface SchemaFormContext<TData extends FieldValues> {
31
31
  getUpdatedData: () => TData | Promise<TData>;
32
32
  customErrorRenderer?: (error: unknown) => ReactNode;
33
33
  timezone?: string;
34
+ displayConfig: {
35
+ showSubmitButton?: boolean;
36
+ showResetButton?: boolean;
37
+ showTitle?: boolean;
38
+ };
34
39
  }
35
40
  export declare const SchemaFormContext: import("react").Context<SchemaFormContext<unknown>>;
@@ -4,4 +4,4 @@ export interface DefaultFormProps<TData extends FieldValues> {
4
4
  formConfig: Omit<FormRootProps<TData>, "children">;
5
5
  showTitle?: boolean;
6
6
  }
7
- export declare const DefaultForm: <TData extends FieldValues>({ formConfig, showTitle, }: DefaultFormProps<TData>) => import("react/jsx-runtime").JSX.Element;
7
+ export declare const DefaultForm: <TData extends FieldValues>({ formConfig, }: DefaultFormProps<TData>) => import("react/jsx-runtime").JSX.Element;
@@ -22,6 +22,11 @@ export interface FormRootProps<TData extends FieldValues> {
22
22
  requestOptions?: AxiosRequestConfig;
23
23
  getUpdatedData?: () => TData | Promise<TData> | void;
24
24
  customErrorRenderer?: (error: unknown) => ReactNode;
25
+ displayConfig?: {
26
+ showSubmitButton?: boolean;
27
+ showResetButton?: boolean;
28
+ showTitle?: boolean;
29
+ };
25
30
  }
26
31
  export interface CustomJSONSchema7Definition extends JSONSchema7 {
27
32
  variant: string;
@@ -38,4 +43,4 @@ export declare const idPickerSanityCheck: (column: string, foreign_key?: {
38
43
  column?: string | undefined;
39
44
  display_column?: string | undefined;
40
45
  } | undefined) => void;
41
- export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
46
+ export declare const FormRoot: <TData extends FieldValues>({ schema, idMap, setIdMap, form, serverUrl, translate, children, order, ignore, include, onSubmit, rowNumber, requestOptions, getUpdatedData, customErrorRenderer, displayConfig, }: FormRootProps<TData>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { ErrorObject, ValidateFunction } from "ajv";
2
+ import { JSONSchema7 } from "json-schema";
3
+ type ValidateDataResult = {
4
+ isValid: boolean;
5
+ validate: ValidateFunction;
6
+ errors: ErrorObject<string, Record<string, any>, unknown>[] | null | undefined;
7
+ };
8
+ export declare const validateData: (data: unknown, schema: JSONSchema7) => ValidateDataResult;
9
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsol-oss/react-datatable5",
3
- "version": "12.0.0-beta.63",
3
+ "version": "12.0.0-beta.64",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -75,8 +75,8 @@
75
75
  "@typescript-eslint/parser": "^7.2.0",
76
76
  "@vitejs/plugin-react": "^4.2.1",
77
77
  "ajv": "^8.12.0",
78
- "ajv-formats": "^3.0.1",
79
78
  "ajv-errors": "^3.0.0",
79
+ "ajv-formats": "^3.0.1",
80
80
  "eslint": "^8.57.0",
81
81
  "eslint-plugin-react-hooks": "^4.6.0",
82
82
  "eslint-plugin-react-refresh": "^0.4.6",