@bsol-oss/react-datatable5 12.0.0-beta.21 → 12.0.0-beta.23

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
@@ -10,10 +10,10 @@ import { UseTranslationResponse } from 'react-i18next';
10
10
  import { RankingInfo } from '@tanstack/match-sorter-utils';
11
11
  import { UseQueryResult } from '@tanstack/react-query';
12
12
  import { JSONSchema7 } from 'json-schema';
13
- import { ForeignKeyProps } from '@/components/Form/components/fields/StringInputField';
13
+ import { ForeignKeyProps as ForeignKeyProps$1 } from '@/components/Form/components/fields/StringInputField';
14
14
  import { AxiosRequestConfig } from 'axios';
15
15
  import * as react_hook_form from 'react-hook-form';
16
- import { FieldValues, UseFormReturn, SubmitHandler } from 'react-hook-form';
16
+ import { UseFormReturn, FieldValues, SubmitHandler } from 'react-hook-form';
17
17
  import { RenderProps, Props } from '@bsol-oss/dayzed-react19';
18
18
 
19
19
  interface DensityToggleButtonProps {
@@ -171,7 +171,7 @@ interface DataTableContext<TData = unknown> extends DataTableProps {
171
171
  globalFilter: string;
172
172
  setGlobalFilter: OnChangeFn<string>;
173
173
  type: "client" | "server";
174
- translate: UseTranslationResponse<any, any>;
174
+ translate: UseTranslationResponse<any, unknown>;
175
175
  }
176
176
  declare const DataTableContext: React$1.Context<DataTableContext<unknown>>;
177
177
 
@@ -445,8 +445,34 @@ declare const FilterOptions: ({ column }: FilterOptionsProps) => react_jsx_runti
445
445
 
446
446
  declare const GlobalFilter: () => react_jsx_runtime.JSX.Element;
447
447
 
448
+ interface ForeignKeyProps {
449
+ column: string;
450
+ table: string;
451
+ display_column: string;
452
+ }
453
+
454
+ interface CustomJSONSchema7 extends JSONSchema7 {
455
+ gridColumn?: string;
456
+ gridRow?: string;
457
+ foreign_key?: ForeignKeyProps;
458
+ variant?: string;
459
+ renderDisplay?: (item: unknown) => ReactNode;
460
+ inputRender?: (props: {
461
+ column: string;
462
+ schema: CustomJSONSchema7;
463
+ prefix: string;
464
+ formContext: UseFormReturn;
465
+ }) => ReactNode;
466
+ inputViewerRender?: (props: {
467
+ column: string;
468
+ schema: CustomJSONSchema7;
469
+ prefix: string;
470
+ formContext: UseFormReturn;
471
+ }) => ReactNode;
472
+ }
473
+
448
474
  interface FormRootProps<TData extends FieldValues> {
449
- schema: JSONSchema7;
475
+ schema: CustomJSONSchema7;
450
476
  serverUrl: string;
451
477
  requestUrl?: string;
452
478
  idMap: Record<string, object>;
@@ -469,7 +495,7 @@ interface CustomJSONSchema7Definition extends JSONSchema7 {
469
495
  display_column: string;
470
496
  gridColumn: string;
471
497
  gridRow: string;
472
- foreign_key: ForeignKeyProps;
498
+ foreign_key: ForeignKeyProps$1;
473
499
  children: ReactNode;
474
500
  }
475
501
  declare const idPickerSanityCheck: (column: string, foreign_key?: {
package/dist/index.js CHANGED
@@ -57,6 +57,39 @@ const DataTableContext = React.createContext({
57
57
  setGlobalFilter: () => { },
58
58
  type: "client",
59
59
  translate: {},
60
+ data: [],
61
+ columns: [],
62
+ columnOrder: [],
63
+ columnFilters: [],
64
+ density: "sm",
65
+ sorting: [],
66
+ setPagination: function () {
67
+ throw new Error("Function not implemented.");
68
+ },
69
+ setSorting: function () {
70
+ throw new Error("Function not implemented.");
71
+ },
72
+ setColumnFilters: function () {
73
+ throw new Error("Function not implemented.");
74
+ },
75
+ setRowSelection: function () {
76
+ throw new Error("Function not implemented.");
77
+ },
78
+ setColumnOrder: function () {
79
+ throw new Error("Function not implemented.");
80
+ },
81
+ setDensity: function () {
82
+ throw new Error("Function not implemented.");
83
+ },
84
+ setColumnVisibility: function () {
85
+ throw new Error("Function not implemented.");
86
+ },
87
+ pagination: {
88
+ pageIndex: 0,
89
+ pageSize: 10,
90
+ },
91
+ rowSelection: {},
92
+ columnVisibility: {},
60
93
  });
61
94
 
62
95
  const useDataTableContext = () => {
@@ -2441,8 +2474,8 @@ react.CheckboxCard.Indicator;
2441
2474
  function ColumnCard({ columnId }) {
2442
2475
  const ref = React.useRef(null);
2443
2476
  const [dragging, setDragging] = React.useState(false); // NEW
2444
- const { table } = useDataTableContext();
2445
- const displayName = columnId;
2477
+ const { table, translate } = useDataTableContext();
2478
+ const displayName = translate.t(columnId);
2446
2479
  const column = table.getColumn(columnId);
2447
2480
  invariant(column);
2448
2481
  React.useEffect(() => {
@@ -3658,6 +3691,18 @@ const BooleanPicker = ({ schema, column, prefix }) => {
3658
3691
  } }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
3659
3692
  };
3660
3693
 
3694
+ const CustomInput = ({ column, schema, prefix }) => {
3695
+ const formContext = reactHookForm.useFormContext();
3696
+ const { inputRender } = schema;
3697
+ return (inputRender &&
3698
+ inputRender({
3699
+ column,
3700
+ schema,
3701
+ prefix,
3702
+ formContext,
3703
+ }));
3704
+ };
3705
+
3661
3706
  const monthNamesShort = [
3662
3707
  "Jan",
3663
3708
  "Feb",
@@ -3755,9 +3800,9 @@ const DatePicker = ({ column, schema, prefix }) => {
3755
3800
  const selectedDate = watch(colLabel);
3756
3801
  const formatedDate = dayjs(selectedDate).format("YYYY-MM-DD");
3757
3802
  return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3758
- gridRow, children: [jsxRuntime.jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { size: "sm", variant: "outline", onClick: () => {
3803
+ 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: () => {
3759
3804
  setOpen(true);
3760
- }, children: selectedDate !== undefined ? `${formatedDate}` : "" }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1
3805
+ }, justifyContent: "start", children: [jsxRuntime.jsx(md.MdDateRange, {}), selectedDate !== undefined ? `${formatedDate}` : ""] }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1
3761
3806
  // @ts-expect-error TODO: find appropriate types
3762
3807
  , {
3763
3808
  // @ts-expect-error TODO: find appropriate types
@@ -3782,7 +3827,7 @@ function filterArray(array, searchTerm) {
3782
3827
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3783
3828
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
3784
3829
  const { translate } = useSchemaContext();
3785
- const { required } = schema;
3830
+ const { required, variant } = schema;
3786
3831
  const isRequired = required?.some((columnId) => columnId === column);
3787
3832
  const { gridColumn, gridRow, renderDisplay } = schema;
3788
3833
  const [searchText, setSearchText] = React.useState();
@@ -3799,6 +3844,22 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3799
3844
  setSearchText(event.target.value);
3800
3845
  setLimit(10);
3801
3846
  };
3847
+ if (variant === "radio") {
3848
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3849
+ gridRow, children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? "").map((item) => {
3850
+ return (jsxRuntime.jsxs(react.RadioGroup.Item, { onClick: () => {
3851
+ if (!isMultiple) {
3852
+ setOpenSearchResult(false);
3853
+ setValue(colLabel, item);
3854
+ return;
3855
+ }
3856
+ const newSet = new Set([...(watchEnums ?? []), item]);
3857
+ setValue(colLabel, [...newSet]);
3858
+ }, value: item, children: [jsxRuntime.jsx(react.RadioGroup.ItemHiddenInput, {}), jsxRuntime.jsx(react.RadioGroup.ItemIndicator, {}), jsxRuntime.jsx(react.RadioGroup.ItemText, { children: !!renderDisplay === true
3859
+ ? renderDisplay(item)
3860
+ : translate.t(removeIndex(`${colLabel}.${item}`)) })] }, `${colLabel}-${item}`));
3861
+ }) }) }) }));
3862
+ }
3802
3863
  return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3803
3864
  gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
3804
3865
  const item = enumValue;
@@ -3814,7 +3875,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3814
3875
  setOpenSearchResult(true);
3815
3876
  }, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
3816
3877
  setOpenSearchResult(true);
3817
- }, children: watchEnum === undefined
3878
+ }, justifyContent: "start", children: watchEnum === undefined
3818
3879
  ? ""
3819
3880
  : translate.t(removeIndex(`${colLabel}.${watchEnum}`)) })), 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, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(`${column}.type_to_search`), onChange: (event) => {
3820
3881
  onSearchChange(event);
@@ -4204,7 +4265,7 @@ const FilePicker = ({ column, schema, prefix }) => {
4204
4265
  setValue(column, currentFiles.filter(({ name }) => {
4205
4266
  return name !== file.name;
4206
4267
  }));
4207
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
4268
+ }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [file.type.startsWith("image/") && (jsxRuntime.jsx(react.Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
4208
4269
  }) }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4209
4270
  };
4210
4271
 
@@ -4337,7 +4398,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4337
4398
  setOpenSearchResult(true);
4338
4399
  }, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
4339
4400
  setOpenSearchResult(true);
4340
- }, children: 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, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(removeIndex(`${colLabel}.typeToSearch`)), onChange: (event) => {
4401
+ }, justifyContent: "start", children: 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, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: translate.t(removeIndex(`${colLabel}.typeToSearch`)), onChange: (event) => {
4341
4402
  onSearchChange(event);
4342
4403
  setOpenSearchResult(true);
4343
4404
  }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), (searchText?.length ?? 0) > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [isFetching && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isFetching" }), isLoading && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isLoading" }), isPending && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isPending" }), (isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, {}), isError && (jsxRuntime.jsx(react.Icon, { color: "red.400", children: jsxRuntime.jsx(bi.BiError, {}) })), jsxRuntime.jsx(react.Text, { justifySelf: "center", children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` }), jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children:
@@ -4357,7 +4418,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4357
4418
  item[column_ref],
4358
4419
  ]);
4359
4420
  setValue(colLabel, [...newSet]);
4360
- }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected ? { color: "colorPalette.400/50" } : {}), children: !!renderDisplay === true
4421
+ }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
4422
+ ? { color: "colorPalette.400/50" }
4423
+ : {}), children: !!renderDisplay === true
4361
4424
  ? renderDisplay(item)
4362
4425
  : item[display_column] }, item[column_ref]));
4363
4426
  }) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(react.Text, { children: translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] }), jsxRuntime.jsx(PaginationRoot, { justifySelf: "center", count: count, pageSize: 10, 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: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
@@ -4557,9 +4620,124 @@ const TagPicker = ({ column, schema, prefix }) => {
4557
4620
  }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
4558
4621
  };
4559
4622
 
4623
+ const TextAreaInput = ({ column, schema, prefix, }) => {
4624
+ const { register, formState: { errors }, } = reactHookForm.useFormContext();
4625
+ const { translate } = useSchemaContext();
4626
+ const { required, gridColumn, gridRow } = schema;
4627
+ const isRequired = required?.some((columnId) => columnId === column);
4628
+ const colLabel = `${prefix}${column}`;
4629
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsxRuntime.jsx(react.Textarea, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
4630
+ };
4631
+
4632
+ function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
4633
+ am: "am",
4634
+ pm: "pm",
4635
+ }, onChange = () => { }, }) {
4636
+ const hours = Array.from({ length: 12 }, (_, i) => {
4637
+ const hour = i + 1;
4638
+ return hour.toString().padStart(2, "0");
4639
+ });
4640
+ const minutes = Array.from({ length: 60 }, (_, i) => {
4641
+ return i.toString().padStart(2, "0");
4642
+ });
4643
+ const hoursCollection = react.createListCollection({
4644
+ items: hours.map((hour) => ({
4645
+ value: hour,
4646
+ label: hour,
4647
+ })),
4648
+ });
4649
+ const minutesCollection = react.createListCollection({
4650
+ items: minutes.map((hour) => ({
4651
+ value: hour,
4652
+ label: hour,
4653
+ })),
4654
+ });
4655
+ const meridiemsCollection = react.createListCollection({
4656
+ items: ["am", "pm"].map((hour) => ({
4657
+ value: hour,
4658
+ label: meridiemLabel[hour] ?? hour,
4659
+ })),
4660
+ });
4661
+ return (jsxRuntime.jsxs(react.Grid, { templateColumns: "auto auto", gap: "4", children: [jsxRuntime.jsxs(react.Flex, { justifyContent: "center", alignItems: "center", gap: "2", children: [jsxRuntime.jsxs(react.Select.Root, { value: [`${hour.toString().padStart(2, "0")}`], onValueChange: (e) => {
4662
+ setHour(parseInt(e.value[0]));
4663
+ onChange({ hour: parseInt(e.value[0]), minute, meridiem });
4664
+ }, collection: hoursCollection, positioning: { sameWidth: true, placement: "bottom" }, children: [jsxRuntime.jsx(react.Select.HiddenSelect, {}), jsxRuntime.jsx(react.Select.Control, { children: jsxRuntime.jsx(react.Select.Trigger, { children: jsxRuntime.jsx(react.Select.ValueText, { placeholder: "Hour" }) }) }), jsxRuntime.jsx(react.Select.Positioner, { children: jsxRuntime.jsx(react.Select.Content, { width: "full", children: hoursCollection.items.map(({ value: hour }) => (jsxRuntime.jsxs(react.Select.Item, { item: hour, children: [hour, jsxRuntime.jsx(react.Select.ItemIndicator, {})] }, hour))) }) })] }), jsxRuntime.jsx(react.Text, { children: ":" }), jsxRuntime.jsxs(react.Select.Root, { value: [`${minute.toString().padStart(2, "0")}`], onValueChange: (e) => {
4665
+ setMinute(parseInt(e.value[0]));
4666
+ onChange({ hour, minute: parseInt(e.value[0]), meridiem });
4667
+ }, collection: minutesCollection, positioning: { sameWidth: true, placement: "bottom" }, children: [jsxRuntime.jsx(react.Select.HiddenSelect, {}), jsxRuntime.jsx(react.Select.Control, { children: jsxRuntime.jsx(react.Select.Trigger, { children: jsxRuntime.jsx(react.Select.ValueText, { placeholder: "Minute" }) }) }), jsxRuntime.jsx(react.Select.Positioner, { children: jsxRuntime.jsx(react.Select.Content, { width: "full", children: minutes.map((minute) => (jsxRuntime.jsxs(react.Select.Item, { item: minute, children: [minute, jsxRuntime.jsx(react.Select.ItemIndicator, {})] }, minute))) }) })] })] }), jsxRuntime.jsxs(react.Select.Root, { value: [meridiem], onValueChange: (e) => {
4668
+ setMeridiem(e.value[0]);
4669
+ onChange({ hour, minute, meridiem: e.value[0] });
4670
+ }, collection: meridiemsCollection, positioning: { sameWidth: true, placement: "bottom" }, children: [jsxRuntime.jsx(react.Select.HiddenSelect, {}), jsxRuntime.jsx(react.Select.Control, { children: jsxRuntime.jsx(react.Select.Trigger, { children: jsxRuntime.jsx(react.Select.ValueText, { placeholder: "am/pm" }) }) }), jsxRuntime.jsx(react.Select.Positioner, { children: jsxRuntime.jsx(react.Select.Content, { width: "full", children: meridiemsCollection.items.map(({ value: hour, label }) => (jsxRuntime.jsxs(react.Select.Item, { item: hour, children: [label, jsxRuntime.jsx(react.Select.ItemIndicator, {})] }, hour))) }) })] })] }));
4671
+ }
4672
+
4673
+ const TimePicker = ({ column, schema, prefix }) => {
4674
+ const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4675
+ const { translate } = useSchemaContext();
4676
+ const { required, gridColumn, gridRow } = schema;
4677
+ const isRequired = required?.some((columnId) => columnId === column);
4678
+ const colLabel = `${prefix}${column}`;
4679
+ const [open, setOpen] = React.useState(false);
4680
+ const value = watch(colLabel);
4681
+ const formatedTime = dayjs(value).format("hh:mm A");
4682
+ // Parse the initial time parts from the ISO time string (HH:mm:ss)
4683
+ const parseTime = (isoTime) => {
4684
+ if (!isoTime)
4685
+ return { hour: 12, minute: 0, meridiem: "am" };
4686
+ const parsed = dayjs(isoTime);
4687
+ if (!parsed.isValid())
4688
+ return { hour: 12, minute: 0, meridiem: "am" };
4689
+ let hour = parsed.hour();
4690
+ const minute = parsed.minute();
4691
+ const meridiem = hour >= 12 ? "pm" : "am";
4692
+ if (hour === 0)
4693
+ hour = 12;
4694
+ else if (hour > 12)
4695
+ hour -= 12;
4696
+ return { hour, minute, meridiem };
4697
+ };
4698
+ const initialTime = parseTime(value);
4699
+ const [hour, setHour] = React.useState(initialTime.hour);
4700
+ const [minute, setMinute] = React.useState(initialTime.minute);
4701
+ const [meridiem, setMeridiem] = React.useState(initialTime.meridiem);
4702
+ React.useEffect(() => {
4703
+ const { hour, minute, meridiem } = parseTime(value);
4704
+ setHour(hour);
4705
+ setMinute(minute);
4706
+ setMeridiem(meridiem);
4707
+ }, [value]);
4708
+ // Convert hour, minute, meridiem to 24-hour ISO time string
4709
+ const toIsoTime = (hour, minute, meridiem) => {
4710
+ let h = hour;
4711
+ if (meridiem === "am" && hour === 12)
4712
+ h = 0;
4713
+ else if (meridiem === "pm" && hour < 12)
4714
+ h = hour + 12;
4715
+ return dayjs().hour(h).minute(minute).second(0).toISOString();
4716
+ };
4717
+ // Handle changes to time parts
4718
+ const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
4719
+ setHour(newHour);
4720
+ setMinute(newMinute);
4721
+ setMeridiem(newMeridiem);
4722
+ const isoTime = toIsoTime(newHour, newMinute, newMeridiem);
4723
+ setValue(colLabel, isoTime, { shouldValidate: true, shouldDirty: true });
4724
+ };
4725
+ const containerRef = React.useRef(null);
4726
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4727
+ gridRow, children: [jsxRuntime.jsxs(react.Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4728
+ setOpen(true);
4729
+ }, justifyContent: "start", children: [jsxRuntime.jsx(io.IoMdClock, {}), value !== undefined ? `${formatedTime}` : ""] }) }), jsxRuntime.jsx(react.Portal, { children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { ref: containerRef, children: jsxRuntime.jsx(react.Popover.Body, { children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
4730
+ am: translate.t(removeIndex(`${colLabel}.am`)),
4731
+ pm: translate.t(removeIndex(`${colLabel}.pm`)),
4732
+ } }) }) }) }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4733
+ };
4734
+
4560
4735
  const SchemaRenderer = ({ schema, prefix, column, }) => {
4561
4736
  const colSchema = schema;
4562
4737
  const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
4738
+ if (variant === "custom-input") {
4739
+ return jsxRuntime.jsx(CustomInput, { schema: colSchema, prefix, column });
4740
+ }
4563
4741
  if (type === "string") {
4564
4742
  if ((schema.enum ?? []).length > 0) {
4565
4743
  return jsxRuntime.jsx(EnumPicker, { schema: colSchema, prefix, column });
@@ -4571,6 +4749,12 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
4571
4749
  if (variant === "date-picker") {
4572
4750
  return jsxRuntime.jsx(DatePicker, { schema: colSchema, prefix, column });
4573
4751
  }
4752
+ if (variant === "time-picker") {
4753
+ return jsxRuntime.jsx(TimePicker, { schema: colSchema, prefix, column });
4754
+ }
4755
+ if (variant === "text-area") {
4756
+ return jsxRuntime.jsx(TextAreaInput, { schema: colSchema, prefix, column });
4757
+ }
4574
4758
  return jsxRuntime.jsx(StringInputField, { schema: colSchema, prefix, column });
4575
4759
  }
4576
4760
  if (type === "number" || type === "integer") {
@@ -4641,6 +4825,18 @@ const BooleanViewer = ({ schema, column, prefix, }) => {
4641
4825
  : translate.t(removeIndex(`${colLabel}.false`)) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4642
4826
  };
4643
4827
 
4828
+ const CustomViewer = ({ column, schema, prefix }) => {
4829
+ const formContext = reactHookForm.useFormContext();
4830
+ const { inputViewerRender } = schema;
4831
+ return (inputViewerRender &&
4832
+ inputViewerRender({
4833
+ column,
4834
+ schema,
4835
+ prefix,
4836
+ formContext,
4837
+ }));
4838
+ };
4839
+
4644
4840
  const DateViewer = ({ column, schema, prefix }) => {
4645
4841
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4646
4842
  const { translate } = useSchemaContext();
@@ -4674,22 +4870,15 @@ const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
4674
4870
  };
4675
4871
 
4676
4872
  const FileViewer = ({ column, schema, prefix }) => {
4677
- const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4873
+ const { watch } = reactHookForm.useFormContext();
4678
4874
  const { translate } = useSchemaContext();
4679
4875
  const { required, gridColumn, gridRow } = schema;
4680
4876
  const isRequired = required?.some((columnId) => columnId === column);
4681
4877
  const currentFiles = (watch(column) ?? []);
4682
4878
  const colLabel = `${prefix}${column}`;
4683
- return (jsxRuntime.jsxs(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4684
- const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4685
- setValue(colLabel, [...currentFiles, ...newFiles]);
4686
- }, placeholder: translate.t(`${colLabel}.fileDropzone`) }), jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
4687
- return (jsxRuntime.jsx(react.Card.Root, { variant: "subtle", children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", cursor: "pointer", onClick: () => {
4688
- setValue(column, currentFiles.filter(({ name }) => {
4689
- return name !== file.name;
4690
- }));
4691
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
4692
- }) }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4879
+ return (jsxRuntime.jsx(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
4880
+ return (jsxRuntime.jsx(react.Card.Root, { variant: "subtle", children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [file.type.startsWith("image/") && (jsxRuntime.jsx(react.Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsxRuntime.jsx(react.Box, { children: file.name })] }) }, file.name));
4881
+ }) }) }));
4693
4882
  };
4694
4883
 
4695
4884
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
@@ -4803,6 +4992,16 @@ const RecordInput = ({ column, schema, prefix }) => {
4803
4992
  }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4804
4993
  };
4805
4994
 
4995
+ const StringViewer = ({ column, schema, prefix, }) => {
4996
+ const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4997
+ const { translate } = useSchemaContext();
4998
+ const { required, gridColumn, gridRow } = schema;
4999
+ const isRequired = required?.some((columnId) => columnId === column);
5000
+ const colLabel = `${prefix}${column}`;
5001
+ const value = watch(colLabel);
5002
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsxRuntime.jsx(react.Text, { children: value }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5003
+ };
5004
+
4806
5005
  const TagViewer = ({ column, schema, prefix }) => {
4807
5006
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
4808
5007
  const { serverUrl } = useSchemaContext();
@@ -4888,19 +5087,35 @@ const TagViewer = ({ column, schema, prefix }) => {
4888
5087
  }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
4889
5088
  };
4890
5089
 
4891
- const StringViewer = ({ column, schema, prefix, }) => {
5090
+ const TextAreaViewer = ({ column, schema, prefix, }) => {
4892
5091
  const { watch, formState: { errors }, } = reactHookForm.useFormContext();
4893
5092
  const { translate } = useSchemaContext();
4894
5093
  const { required, gridColumn, gridRow } = schema;
4895
5094
  const isRequired = required?.some((columnId) => columnId === column);
4896
5095
  const colLabel = `${prefix}${column}`;
4897
5096
  const value = watch(colLabel);
4898
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsxRuntime.jsx(react.Text, { children: value }), errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5097
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsxRuntime.jsx(react.Text, { whiteSpace: "pre-wrap", children: value }), " ", errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5098
+ };
5099
+
5100
+ const TimeViewer = ({ column, schema, prefix }) => {
5101
+ const { watch, formState: { errors }, } = reactHookForm.useFormContext();
5102
+ const { translate } = useSchemaContext();
5103
+ const { required, gridColumn, gridRow } = schema;
5104
+ const isRequired = required?.some((columnId) => columnId === column);
5105
+ const colLabel = `${prefix}${column}`;
5106
+ const selectedDate = watch(colLabel);
5107
+ return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5108
+ gridRow, children: [jsxRuntime.jsx(react.Text, { children: selectedDate !== undefined
5109
+ ? dayjs(selectedDate).format("hh:mm A")
5110
+ : "" }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4899
5111
  };
4900
5112
 
4901
5113
  const SchemaViewer = ({ schema, prefix, column, }) => {
4902
5114
  const colSchema = schema;
4903
5115
  const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
5116
+ if (variant === "custom-input") {
5117
+ return jsxRuntime.jsx(CustomViewer, { schema: colSchema, prefix, column });
5118
+ }
4904
5119
  if (type === "string") {
4905
5120
  if ((schema.enum ?? []).length > 0) {
4906
5121
  return jsxRuntime.jsx(EnumViewer, { schema: colSchema, prefix, column });
@@ -4912,6 +5127,12 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
4912
5127
  if (variant === "date-picker") {
4913
5128
  return jsxRuntime.jsx(DateViewer, { schema: colSchema, prefix, column });
4914
5129
  }
5130
+ if (variant === "time-picker") {
5131
+ return jsxRuntime.jsx(TimeViewer, { schema: colSchema, prefix, column });
5132
+ }
5133
+ if (variant === "text-area") {
5134
+ return jsxRuntime.jsx(TextAreaViewer, { schema: colSchema, prefix, column });
5135
+ }
4915
5136
  return jsxRuntime.jsx(StringViewer, { schema: colSchema, prefix, column });
4916
5137
  }
4917
5138
  if (type === "number" || type === "integer") {
package/dist/index.mjs CHANGED
@@ -1,16 +1,16 @@
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, Tooltip as Tooltip$1, Group, InputElement, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Accordion, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading } from '@chakra-ui/react';
2
+ import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Tooltip as Tooltip$1, Group, InputElement, 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, Textarea, createListCollection, Select, 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 } from 'react';
6
6
  import { LuX, LuCheck, LuChevronRight, LuChevronDown } from 'react-icons/lu';
7
- import { MdOutlineSort, MdFilterAlt, MdSearch, MdClose, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdClear, MdOutlineChecklist } from 'react-icons/md';
7
+ import { MdOutlineSort, MdFilterAlt, MdSearch, MdClose, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdClear, MdOutlineChecklist, MdDateRange } from 'react-icons/md';
8
8
  import { FaUpDown, FaGripLinesVertical } from 'react-icons/fa6';
9
9
  import { BiDownArrow, BiUpArrow, BiError } from 'react-icons/bi';
10
10
  import { CgClose } from 'react-icons/cg';
11
11
  import Dayzed from '@bsol-oss/dayzed-react19';
12
12
  import { HiMiniEllipsisHorizontal, HiChevronLeft, HiChevronRight } from 'react-icons/hi2';
13
- import { IoMdEye, IoMdCheckbox } from 'react-icons/io';
13
+ import { IoMdEye, IoMdCheckbox, IoMdClock } from 'react-icons/io';
14
14
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
15
15
  import { bind, bindAll } from 'bind-event-listener';
16
16
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
@@ -37,6 +37,39 @@ const DataTableContext = createContext({
37
37
  setGlobalFilter: () => { },
38
38
  type: "client",
39
39
  translate: {},
40
+ data: [],
41
+ columns: [],
42
+ columnOrder: [],
43
+ columnFilters: [],
44
+ density: "sm",
45
+ sorting: [],
46
+ setPagination: function () {
47
+ throw new Error("Function not implemented.");
48
+ },
49
+ setSorting: function () {
50
+ throw new Error("Function not implemented.");
51
+ },
52
+ setColumnFilters: function () {
53
+ throw new Error("Function not implemented.");
54
+ },
55
+ setRowSelection: function () {
56
+ throw new Error("Function not implemented.");
57
+ },
58
+ setColumnOrder: function () {
59
+ throw new Error("Function not implemented.");
60
+ },
61
+ setDensity: function () {
62
+ throw new Error("Function not implemented.");
63
+ },
64
+ setColumnVisibility: function () {
65
+ throw new Error("Function not implemented.");
66
+ },
67
+ pagination: {
68
+ pageIndex: 0,
69
+ pageSize: 10,
70
+ },
71
+ rowSelection: {},
72
+ columnVisibility: {},
40
73
  });
41
74
 
42
75
  const useDataTableContext = () => {
@@ -2421,8 +2454,8 @@ CheckboxCard$1.Indicator;
2421
2454
  function ColumnCard({ columnId }) {
2422
2455
  const ref = useRef(null);
2423
2456
  const [dragging, setDragging] = useState(false); // NEW
2424
- const { table } = useDataTableContext();
2425
- const displayName = columnId;
2457
+ const { table, translate } = useDataTableContext();
2458
+ const displayName = translate.t(columnId);
2426
2459
  const column = table.getColumn(columnId);
2427
2460
  invariant(column);
2428
2461
  useEffect(() => {
@@ -3638,6 +3671,18 @@ const BooleanPicker = ({ schema, column, prefix }) => {
3638
3671
  } }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
3639
3672
  };
3640
3673
 
3674
+ const CustomInput = ({ column, schema, prefix }) => {
3675
+ const formContext = useFormContext();
3676
+ const { inputRender } = schema;
3677
+ return (inputRender &&
3678
+ inputRender({
3679
+ column,
3680
+ schema,
3681
+ prefix,
3682
+ formContext,
3683
+ }));
3684
+ };
3685
+
3641
3686
  const monthNamesShort = [
3642
3687
  "Jan",
3643
3688
  "Feb",
@@ -3735,9 +3780,9 @@ const DatePicker = ({ column, schema, prefix }) => {
3735
3780
  const selectedDate = watch(colLabel);
3736
3781
  const formatedDate = dayjs(selectedDate).format("YYYY-MM-DD");
3737
3782
  return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3738
- gridRow, children: [jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsx(Button, { size: "sm", variant: "outline", onClick: () => {
3783
+ gridRow, children: [jsxs(PopoverRoot, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
3739
3784
  setOpen(true);
3740
- }, children: selectedDate !== undefined ? `${formatedDate}` : "" }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1
3785
+ }, justifyContent: "start", children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${formatedDate}` : ""] }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1
3741
3786
  // @ts-expect-error TODO: find appropriate types
3742
3787
  , {
3743
3788
  // @ts-expect-error TODO: find appropriate types
@@ -3762,7 +3807,7 @@ function filterArray(array, searchTerm) {
3762
3807
  const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3763
3808
  const { watch, formState: { errors }, setValue, } = useFormContext();
3764
3809
  const { translate } = useSchemaContext();
3765
- const { required } = schema;
3810
+ const { required, variant } = schema;
3766
3811
  const isRequired = required?.some((columnId) => columnId === column);
3767
3812
  const { gridColumn, gridRow, renderDisplay } = schema;
3768
3813
  const [searchText, setSearchText] = useState();
@@ -3779,6 +3824,22 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3779
3824
  setSearchText(event.target.value);
3780
3825
  setLimit(10);
3781
3826
  };
3827
+ if (variant === "radio") {
3828
+ return (jsx(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3829
+ gridRow, children: jsx(RadioGroup$1.Root, { defaultValue: "1", children: jsx(HStack, { gap: "6", children: filterArray(dataList, searchText ?? "").map((item) => {
3830
+ return (jsxs(RadioGroup$1.Item, { onClick: () => {
3831
+ if (!isMultiple) {
3832
+ setOpenSearchResult(false);
3833
+ setValue(colLabel, item);
3834
+ return;
3835
+ }
3836
+ const newSet = new Set([...(watchEnums ?? []), item]);
3837
+ setValue(colLabel, [...newSet]);
3838
+ }, value: item, children: [jsx(RadioGroup$1.ItemHiddenInput, {}), jsx(RadioGroup$1.ItemIndicator, {}), jsx(RadioGroup$1.ItemText, { children: !!renderDisplay === true
3839
+ ? renderDisplay(item)
3840
+ : translate.t(removeIndex(`${colLabel}.${item}`)) })] }, `${colLabel}-${item}`));
3841
+ }) }) }) }));
3842
+ }
3782
3843
  return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
3783
3844
  gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
3784
3845
  const item = enumValue;
@@ -3794,7 +3855,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
3794
3855
  setOpenSearchResult(true);
3795
3856
  }, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
3796
3857
  setOpenSearchResult(true);
3797
- }, children: watchEnum === undefined
3858
+ }, justifyContent: "start", children: watchEnum === undefined
3798
3859
  ? ""
3799
3860
  : translate.t(removeIndex(`${colLabel}.${watchEnum}`)) })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(`${column}.type_to_search`), onChange: (event) => {
3800
3861
  onSearchChange(event);
@@ -4184,7 +4245,7 @@ const FilePicker = ({ column, schema, prefix }) => {
4184
4245
  setValue(column, currentFiles.filter(({ name }) => {
4185
4246
  return name !== file.name;
4186
4247
  }));
4187
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsx(Box, { children: file.name }), jsx(TiDeleteOutline, {})] }) }, file.name));
4248
+ }, 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));
4188
4249
  }) }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4189
4250
  };
4190
4251
 
@@ -4317,7 +4378,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4317
4378
  setOpenSearchResult(true);
4318
4379
  }, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
4319
4380
  setOpenSearchResult(true);
4320
- }, children: getPickedValue() })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(removeIndex(`${colLabel}.typeToSearch`)), onChange: (event) => {
4381
+ }, justifyContent: "start", children: getPickedValue() })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: translate.t(removeIndex(`${colLabel}.typeToSearch`)), onChange: (event) => {
4321
4382
  onSearchChange(event);
4322
4383
  setOpenSearchResult(true);
4323
4384
  }, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), (searchText?.length ?? 0) > 0 && (jsxs(Fragment, { children: [isFetching && jsx(Fragment, { children: "isFetching" }), isLoading && jsx(Fragment, { children: "isLoading" }), isPending && jsx(Fragment, { children: "isPending" }), (isFetching || isLoading || isPending) && jsx(Spinner, {}), isError && (jsx(Icon, { color: "red.400", children: jsx(BiError, {}) })), jsx(Text, { justifySelf: "center", children: `${translate.t(removeIndex(`${colLabel}.total`))} ${count}, ${translate.t(removeIndex(`${colLabel}.showing`))} ${limit}` }), jsxs(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsx(Flex, { flexFlow: "column wrap", children:
@@ -4337,7 +4398,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
4337
4398
  item[column_ref],
4338
4399
  ]);
4339
4400
  setValue(colLabel, [...newSet]);
4340
- }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected ? { color: "colorPalette.400/50" } : {}), children: !!renderDisplay === true
4401
+ }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
4402
+ ? { color: "colorPalette.400/50" }
4403
+ : {}), children: !!renderDisplay === true
4341
4404
  ? renderDisplay(item)
4342
4405
  : item[display_column] }, item[column_ref]));
4343
4406
  }) }), isDirty && (jsx(Fragment, { children: dataList.length <= 0 && (jsx(Text, { children: translate.t(removeIndex(`${colLabel}.empty_search_result`)) })) }))] }), jsx(PaginationRoot, { justifySelf: "center", count: count, pageSize: 10, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxs(HStack, { gap: "4", children: [jsx(PaginationPrevTrigger, {}), count > 0 && jsx(PaginationPageText, {}), jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
@@ -4537,9 +4600,124 @@ const TagPicker = ({ column, schema, prefix }) => {
4537
4600
  }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
4538
4601
  };
4539
4602
 
4603
+ const TextAreaInput = ({ column, schema, prefix, }) => {
4604
+ const { register, formState: { errors }, } = useFormContext();
4605
+ const { translate } = useSchemaContext();
4606
+ const { required, gridColumn, gridRow } = schema;
4607
+ const isRequired = required?.some((columnId) => columnId === column);
4608
+ const colLabel = `${prefix}${column}`;
4609
+ return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Textarea, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
4610
+ };
4611
+
4612
+ function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
4613
+ am: "am",
4614
+ pm: "pm",
4615
+ }, onChange = () => { }, }) {
4616
+ const hours = Array.from({ length: 12 }, (_, i) => {
4617
+ const hour = i + 1;
4618
+ return hour.toString().padStart(2, "0");
4619
+ });
4620
+ const minutes = Array.from({ length: 60 }, (_, i) => {
4621
+ return i.toString().padStart(2, "0");
4622
+ });
4623
+ const hoursCollection = createListCollection({
4624
+ items: hours.map((hour) => ({
4625
+ value: hour,
4626
+ label: hour,
4627
+ })),
4628
+ });
4629
+ const minutesCollection = createListCollection({
4630
+ items: minutes.map((hour) => ({
4631
+ value: hour,
4632
+ label: hour,
4633
+ })),
4634
+ });
4635
+ const meridiemsCollection = createListCollection({
4636
+ items: ["am", "pm"].map((hour) => ({
4637
+ value: hour,
4638
+ label: meridiemLabel[hour] ?? hour,
4639
+ })),
4640
+ });
4641
+ return (jsxs(Grid, { templateColumns: "auto auto", gap: "4", children: [jsxs(Flex, { justifyContent: "center", alignItems: "center", gap: "2", children: [jsxs(Select.Root, { value: [`${hour.toString().padStart(2, "0")}`], onValueChange: (e) => {
4642
+ setHour(parseInt(e.value[0]));
4643
+ onChange({ hour: parseInt(e.value[0]), minute, meridiem });
4644
+ }, collection: hoursCollection, positioning: { sameWidth: true, placement: "bottom" }, children: [jsx(Select.HiddenSelect, {}), jsx(Select.Control, { children: jsx(Select.Trigger, { children: jsx(Select.ValueText, { placeholder: "Hour" }) }) }), jsx(Select.Positioner, { children: jsx(Select.Content, { width: "full", children: hoursCollection.items.map(({ value: hour }) => (jsxs(Select.Item, { item: hour, children: [hour, jsx(Select.ItemIndicator, {})] }, hour))) }) })] }), jsx(Text, { children: ":" }), jsxs(Select.Root, { value: [`${minute.toString().padStart(2, "0")}`], onValueChange: (e) => {
4645
+ setMinute(parseInt(e.value[0]));
4646
+ onChange({ hour, minute: parseInt(e.value[0]), meridiem });
4647
+ }, collection: minutesCollection, positioning: { sameWidth: true, placement: "bottom" }, children: [jsx(Select.HiddenSelect, {}), jsx(Select.Control, { children: jsx(Select.Trigger, { children: jsx(Select.ValueText, { placeholder: "Minute" }) }) }), jsx(Select.Positioner, { children: jsx(Select.Content, { width: "full", children: minutes.map((minute) => (jsxs(Select.Item, { item: minute, children: [minute, jsx(Select.ItemIndicator, {})] }, minute))) }) })] })] }), jsxs(Select.Root, { value: [meridiem], onValueChange: (e) => {
4648
+ setMeridiem(e.value[0]);
4649
+ onChange({ hour, minute, meridiem: e.value[0] });
4650
+ }, collection: meridiemsCollection, positioning: { sameWidth: true, placement: "bottom" }, children: [jsx(Select.HiddenSelect, {}), jsx(Select.Control, { children: jsx(Select.Trigger, { children: jsx(Select.ValueText, { placeholder: "am/pm" }) }) }), jsx(Select.Positioner, { children: jsx(Select.Content, { width: "full", children: meridiemsCollection.items.map(({ value: hour, label }) => (jsxs(Select.Item, { item: hour, children: [label, jsx(Select.ItemIndicator, {})] }, hour))) }) })] })] }));
4651
+ }
4652
+
4653
+ const TimePicker = ({ column, schema, prefix }) => {
4654
+ const { watch, formState: { errors }, setValue, } = useFormContext();
4655
+ const { translate } = useSchemaContext();
4656
+ const { required, gridColumn, gridRow } = schema;
4657
+ const isRequired = required?.some((columnId) => columnId === column);
4658
+ const colLabel = `${prefix}${column}`;
4659
+ const [open, setOpen] = useState(false);
4660
+ const value = watch(colLabel);
4661
+ const formatedTime = dayjs(value).format("hh:mm A");
4662
+ // Parse the initial time parts from the ISO time string (HH:mm:ss)
4663
+ const parseTime = (isoTime) => {
4664
+ if (!isoTime)
4665
+ return { hour: 12, minute: 0, meridiem: "am" };
4666
+ const parsed = dayjs(isoTime);
4667
+ if (!parsed.isValid())
4668
+ return { hour: 12, minute: 0, meridiem: "am" };
4669
+ let hour = parsed.hour();
4670
+ const minute = parsed.minute();
4671
+ const meridiem = hour >= 12 ? "pm" : "am";
4672
+ if (hour === 0)
4673
+ hour = 12;
4674
+ else if (hour > 12)
4675
+ hour -= 12;
4676
+ return { hour, minute, meridiem };
4677
+ };
4678
+ const initialTime = parseTime(value);
4679
+ const [hour, setHour] = useState(initialTime.hour);
4680
+ const [minute, setMinute] = useState(initialTime.minute);
4681
+ const [meridiem, setMeridiem] = useState(initialTime.meridiem);
4682
+ useEffect(() => {
4683
+ const { hour, minute, meridiem } = parseTime(value);
4684
+ setHour(hour);
4685
+ setMinute(minute);
4686
+ setMeridiem(meridiem);
4687
+ }, [value]);
4688
+ // Convert hour, minute, meridiem to 24-hour ISO time string
4689
+ const toIsoTime = (hour, minute, meridiem) => {
4690
+ let h = hour;
4691
+ if (meridiem === "am" && hour === 12)
4692
+ h = 0;
4693
+ else if (meridiem === "pm" && hour < 12)
4694
+ h = hour + 12;
4695
+ return dayjs().hour(h).minute(minute).second(0).toISOString();
4696
+ };
4697
+ // Handle changes to time parts
4698
+ const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
4699
+ setHour(newHour);
4700
+ setMinute(newMinute);
4701
+ setMeridiem(newMeridiem);
4702
+ const isoTime = toIsoTime(newHour, newMinute, newMeridiem);
4703
+ setValue(colLabel, isoTime, { shouldValidate: true, shouldDirty: true });
4704
+ };
4705
+ const containerRef = useRef(null);
4706
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
4707
+ gridRow, children: [jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
4708
+ setOpen(true);
4709
+ }, justifyContent: "start", children: [jsx(IoMdClock, {}), value !== undefined ? `${formatedTime}` : ""] }) }), jsx(Portal, { children: jsx(Popover.Positioner, { children: jsx(Popover.Content, { ref: containerRef, children: jsx(Popover.Body, { children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
4710
+ am: translate.t(removeIndex(`${colLabel}.am`)),
4711
+ pm: translate.t(removeIndex(`${colLabel}.pm`)),
4712
+ } }) }) }) }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4713
+ };
4714
+
4540
4715
  const SchemaRenderer = ({ schema, prefix, column, }) => {
4541
4716
  const colSchema = schema;
4542
4717
  const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
4718
+ if (variant === "custom-input") {
4719
+ return jsx(CustomInput, { schema: colSchema, prefix, column });
4720
+ }
4543
4721
  if (type === "string") {
4544
4722
  if ((schema.enum ?? []).length > 0) {
4545
4723
  return jsx(EnumPicker, { schema: colSchema, prefix, column });
@@ -4551,6 +4729,12 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
4551
4729
  if (variant === "date-picker") {
4552
4730
  return jsx(DatePicker, { schema: colSchema, prefix, column });
4553
4731
  }
4732
+ if (variant === "time-picker") {
4733
+ return jsx(TimePicker, { schema: colSchema, prefix, column });
4734
+ }
4735
+ if (variant === "text-area") {
4736
+ return jsx(TextAreaInput, { schema: colSchema, prefix, column });
4737
+ }
4554
4738
  return jsx(StringInputField, { schema: colSchema, prefix, column });
4555
4739
  }
4556
4740
  if (type === "number" || type === "integer") {
@@ -4621,6 +4805,18 @@ const BooleanViewer = ({ schema, column, prefix, }) => {
4621
4805
  : translate.t(removeIndex(`${colLabel}.false`)) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4622
4806
  };
4623
4807
 
4808
+ const CustomViewer = ({ column, schema, prefix }) => {
4809
+ const formContext = useFormContext();
4810
+ const { inputViewerRender } = schema;
4811
+ return (inputViewerRender &&
4812
+ inputViewerRender({
4813
+ column,
4814
+ schema,
4815
+ prefix,
4816
+ formContext,
4817
+ }));
4818
+ };
4819
+
4624
4820
  const DateViewer = ({ column, schema, prefix }) => {
4625
4821
  const { watch, formState: { errors }, } = useFormContext();
4626
4822
  const { translate } = useSchemaContext();
@@ -4654,22 +4850,15 @@ const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
4654
4850
  };
4655
4851
 
4656
4852
  const FileViewer = ({ column, schema, prefix }) => {
4657
- const { setValue, formState: { errors }, watch, } = useFormContext();
4853
+ const { watch } = useFormContext();
4658
4854
  const { translate } = useSchemaContext();
4659
4855
  const { required, gridColumn, gridRow } = schema;
4660
4856
  const isRequired = required?.some((columnId) => columnId === column);
4661
4857
  const currentFiles = (watch(column) ?? []);
4662
4858
  const colLabel = `${prefix}${column}`;
4663
- return (jsxs(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: [jsx(FileDropzone, { onDrop: ({ files }) => {
4664
- const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4665
- setValue(colLabel, [...currentFiles, ...newFiles]);
4666
- }, placeholder: translate.t(`${colLabel}.fileDropzone`) }), jsx(Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
4667
- return (jsx(Card.Root, { variant: "subtle", children: jsxs(Card.Body, { gap: "2", cursor: "pointer", onClick: () => {
4668
- setValue(column, currentFiles.filter(({ name }) => {
4669
- return name !== file.name;
4670
- }));
4671
- }, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsx(Box, { children: file.name }), jsx(TiDeleteOutline, {})] }) }, file.name));
4672
- }) }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
4859
+ return (jsx(Field, { label: `${translate.t(`${colLabel}.field_label`)}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", display: "grid", gridTemplateRows: "auto 1fr auto", alignItems: "stretch", children: jsx(Flex, { flexFlow: "column", gap: 1, children: currentFiles.map((file) => {
4860
+ return (jsx(Card.Root, { variant: "subtle", children: jsxs(Card.Body, { gap: "2", 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 })] }) }, file.name));
4861
+ }) }) }));
4673
4862
  };
4674
4863
 
4675
4864
  const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
@@ -4783,6 +4972,16 @@ const RecordInput = ({ column, schema, prefix }) => {
4783
4972
  }, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4784
4973
  };
4785
4974
 
4975
+ const StringViewer = ({ column, schema, prefix, }) => {
4976
+ const { watch, formState: { errors }, } = useFormContext();
4977
+ const { translate } = useSchemaContext();
4978
+ const { required, gridColumn, gridRow } = schema;
4979
+ const isRequired = required?.some((columnId) => columnId === column);
4980
+ const colLabel = `${prefix}${column}`;
4981
+ const value = watch(colLabel);
4982
+ return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Text, { children: value }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
4983
+ };
4984
+
4786
4985
  const TagViewer = ({ column, schema, prefix }) => {
4787
4986
  const { watch, formState: { errors }, setValue, } = useFormContext();
4788
4987
  const { serverUrl } = useSchemaContext();
@@ -4868,19 +5067,35 @@ const TagViewer = ({ column, schema, prefix }) => {
4868
5067
  }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
4869
5068
  };
4870
5069
 
4871
- const StringViewer = ({ column, schema, prefix, }) => {
5070
+ const TextAreaViewer = ({ column, schema, prefix, }) => {
4872
5071
  const { watch, formState: { errors }, } = useFormContext();
4873
5072
  const { translate } = useSchemaContext();
4874
5073
  const { required, gridColumn, gridRow } = schema;
4875
5074
  const isRequired = required?.some((columnId) => columnId === column);
4876
5075
  const colLabel = `${prefix}${column}`;
4877
5076
  const value = watch(colLabel);
4878
- return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Text, { children: value }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5077
+ return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Text, { whiteSpace: "pre-wrap", children: value }), " ", errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
5078
+ };
5079
+
5080
+ const TimeViewer = ({ column, schema, prefix }) => {
5081
+ const { watch, formState: { errors }, } = useFormContext();
5082
+ const { translate } = useSchemaContext();
5083
+ const { required, gridColumn, gridRow } = schema;
5084
+ const isRequired = required?.some((columnId) => columnId === column);
5085
+ const colLabel = `${prefix}${column}`;
5086
+ const selectedDate = watch(colLabel);
5087
+ return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
5088
+ gridRow, children: [jsx(Text, { children: selectedDate !== undefined
5089
+ ? dayjs(selectedDate).format("hh:mm A")
5090
+ : "" }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
4879
5091
  };
4880
5092
 
4881
5093
  const SchemaViewer = ({ schema, prefix, column, }) => {
4882
5094
  const colSchema = schema;
4883
5095
  const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
5096
+ if (variant === "custom-input") {
5097
+ return jsx(CustomViewer, { schema: colSchema, prefix, column });
5098
+ }
4884
5099
  if (type === "string") {
4885
5100
  if ((schema.enum ?? []).length > 0) {
4886
5101
  return jsx(EnumViewer, { schema: colSchema, prefix, column });
@@ -4892,6 +5107,12 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
4892
5107
  if (variant === "date-picker") {
4893
5108
  return jsx(DateViewer, { schema: colSchema, prefix, column });
4894
5109
  }
5110
+ if (variant === "time-picker") {
5111
+ return jsx(TimeViewer, { schema: colSchema, prefix, column });
5112
+ }
5113
+ if (variant === "text-area") {
5114
+ return jsx(TextAreaViewer, { schema: colSchema, prefix, column });
5115
+ }
4895
5116
  return jsx(StringViewer, { schema: colSchema, prefix, column });
4896
5117
  }
4897
5118
  if (type === "number" || type === "integer") {
@@ -7,6 +7,6 @@ export interface DataTableContext<TData = unknown> extends DataTableProps {
7
7
  globalFilter: string;
8
8
  setGlobalFilter: OnChangeFn<string>;
9
9
  type: "client" | "server";
10
- translate: UseTranslationResponse<any, any>;
10
+ translate: UseTranslationResponse<any, unknown>;
11
11
  }
12
12
  export declare const DataTableContext: import("react").Context<DataTableContext<unknown>>;
@@ -4,8 +4,9 @@ import { JSONSchema7 } from "json-schema";
4
4
  import { Dispatch, ReactNode, SetStateAction } from "react";
5
5
  import { FieldValues, SubmitHandler, UseFormReturn } from "react-hook-form";
6
6
  import { UseTranslationResponse } from "react-i18next";
7
+ import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
7
8
  export interface FormRootProps<TData extends FieldValues> {
8
- schema: JSONSchema7;
9
+ schema: CustomJSONSchema7;
9
10
  serverUrl: string;
10
11
  requestUrl?: string;
11
12
  idMap: Record<string, object>;
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
3
+ export interface DatePickerProps {
4
+ column: string;
5
+ schema: CustomJSONSchema7;
6
+ prefix: string;
7
+ }
8
+ export declare const CustomInput: ({ column, schema, prefix }: DatePickerProps) => import("react").ReactNode;
@@ -0,0 +1,12 @@
1
+ import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
2
+ export interface TextAreaInputProps {
3
+ column: string;
4
+ schema: CustomJSONSchema7;
5
+ prefix: string;
6
+ }
7
+ export interface ForeignKeyProps {
8
+ column: string;
9
+ table: string;
10
+ display_column: string;
11
+ }
12
+ export declare const TextAreaInput: ({ column, schema, prefix, }: TextAreaInputProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
2
+ export interface DatePickerProps {
3
+ column: string;
4
+ schema: CustomJSONSchema7;
5
+ prefix: string;
6
+ }
7
+ export declare const TimePicker: ({ column, schema, prefix }: DatePickerProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,25 @@
1
1
  import { JSONSchema7 } from "json-schema";
2
2
  import { ReactNode } from "react";
3
3
  import { ForeignKeyProps } from "../fields/StringInputField";
4
+ import { UseFormReturn } from "react-hook-form";
4
5
  export interface CustomJSONSchema7 extends JSONSchema7 {
5
6
  gridColumn?: string;
6
7
  gridRow?: string;
7
8
  foreign_key?: ForeignKeyProps;
8
9
  variant?: string;
9
- renderDisplay: (item: unknown) => ReactNode;
10
+ renderDisplay?: (item: unknown) => ReactNode;
11
+ inputRender?: (props: {
12
+ column: string;
13
+ schema: CustomJSONSchema7;
14
+ prefix: string;
15
+ formContext: UseFormReturn;
16
+ }) => ReactNode;
17
+ inputViewerRender?: (props: {
18
+ column: string;
19
+ schema: CustomJSONSchema7;
20
+ prefix: string;
21
+ formContext: UseFormReturn;
22
+ }) => ReactNode;
10
23
  }
11
24
  export interface TagPickerProps {
12
25
  column: string;
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
3
+ export interface DatePickerProps {
4
+ column: string;
5
+ schema: CustomJSONSchema7;
6
+ prefix: string;
7
+ }
8
+ export declare const CustomViewer: ({ column, schema, prefix }: DatePickerProps) => import("react").ReactNode;
@@ -0,0 +1,12 @@
1
+ import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
2
+ export interface TextAreaViewerProps {
3
+ column: string;
4
+ schema: CustomJSONSchema7;
5
+ prefix: string;
6
+ }
7
+ export interface ForeignKeyProps {
8
+ column: string;
9
+ table: string;
10
+ display_column: string;
11
+ }
12
+ export declare const TextAreaViewer: ({ column, schema, prefix, }: TextAreaViewerProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { CustomJSONSchema7 } from "../types/CustomJSONSchema7";
2
+ export interface TimeViewerProps {
3
+ column: string;
4
+ schema: CustomJSONSchema7;
5
+ prefix: string;
6
+ }
7
+ export declare const TimeViewer: ({ column, schema, prefix }: TimeViewerProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ interface TimePickerProps {
2
+ hour: number;
3
+ setHour: (hour: number) => void;
4
+ minute: number;
5
+ setMinute: (minute: number) => void;
6
+ meridiem: "am" | "pm";
7
+ setMeridiem: (meridiem: "am" | "pm") => void;
8
+ onChange?: (newValue: {
9
+ hour: number;
10
+ minute: number;
11
+ meridiem: "am" | "pm";
12
+ }) => void;
13
+ meridiemLabel?: {
14
+ am: string;
15
+ pm: string;
16
+ };
17
+ }
18
+ export declare function TimePicker({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel, onChange, }: TimePickerProps): import("react/jsx-runtime").JSX.Element;
19
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsol-oss/react-datatable5",
3
- "version": "12.0.0-beta.21",
3
+ "version": "12.0.0-beta.23",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",