@bsol-oss/react-datatable5 12.0.0-beta.21 → 12.0.0-beta.22
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 +30 -4
- package/dist/index.js +165 -18
- package/dist/index.mjs +168 -21
- package/dist/types/components/Form/components/core/FormRoot.d.ts +2 -1
- package/dist/types/components/Form/components/fields/CustomInput.d.ts +8 -0
- package/dist/types/components/Form/components/fields/TimePicker.d.ts +7 -0
- package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +14 -1
- package/dist/types/components/Form/components/viewers/CustomViewer.d.ts +8 -0
- package/dist/types/components/TimePicker/TimePicker.d.ts +19 -0
- package/package.json +1 -1
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 {
|
|
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 {
|
|
@@ -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:
|
|
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
|
@@ -3658,6 +3658,18 @@ const BooleanPicker = ({ schema, column, prefix }) => {
|
|
|
3658
3658
|
} }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
3659
3659
|
};
|
|
3660
3660
|
|
|
3661
|
+
const CustomInput = ({ column, schema, prefix }) => {
|
|
3662
|
+
const formContext = reactHookForm.useFormContext();
|
|
3663
|
+
const { inputRender } = schema;
|
|
3664
|
+
return (inputRender &&
|
|
3665
|
+
inputRender({
|
|
3666
|
+
column,
|
|
3667
|
+
schema,
|
|
3668
|
+
prefix,
|
|
3669
|
+
formContext,
|
|
3670
|
+
}));
|
|
3671
|
+
};
|
|
3672
|
+
|
|
3661
3673
|
const monthNamesShort = [
|
|
3662
3674
|
"Jan",
|
|
3663
3675
|
"Feb",
|
|
@@ -3755,9 +3767,9 @@ const DatePicker = ({ column, schema, prefix }) => {
|
|
|
3755
3767
|
const selectedDate = watch(colLabel);
|
|
3756
3768
|
const formatedDate = dayjs(selectedDate).format("YYYY-MM-DD");
|
|
3757
3769
|
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.
|
|
3770
|
+
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
3771
|
setOpen(true);
|
|
3760
|
-
}, children: selectedDate !== undefined ? `${formatedDate}` : "" }) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(DatePicker$1
|
|
3772
|
+
}, 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
3773
|
// @ts-expect-error TODO: find appropriate types
|
|
3762
3774
|
, {
|
|
3763
3775
|
// @ts-expect-error TODO: find appropriate types
|
|
@@ -3782,7 +3794,7 @@ function filterArray(array, searchTerm) {
|
|
|
3782
3794
|
const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
3783
3795
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
3784
3796
|
const { translate } = useSchemaContext();
|
|
3785
|
-
const { required } = schema;
|
|
3797
|
+
const { required, variant } = schema;
|
|
3786
3798
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
3787
3799
|
const { gridColumn, gridRow, renderDisplay } = schema;
|
|
3788
3800
|
const [searchText, setSearchText] = React.useState();
|
|
@@ -3799,6 +3811,22 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
|
3799
3811
|
setSearchText(event.target.value);
|
|
3800
3812
|
setLimit(10);
|
|
3801
3813
|
};
|
|
3814
|
+
if (variant === "radio") {
|
|
3815
|
+
return (jsxRuntime.jsx(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
|
|
3816
|
+
gridRow, children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? "").map((item) => {
|
|
3817
|
+
return (jsxRuntime.jsxs(react.RadioGroup.Item, { onClick: () => {
|
|
3818
|
+
if (!isMultiple) {
|
|
3819
|
+
setOpenSearchResult(false);
|
|
3820
|
+
setValue(colLabel, item);
|
|
3821
|
+
return;
|
|
3822
|
+
}
|
|
3823
|
+
const newSet = new Set([...(watchEnums ?? []), item]);
|
|
3824
|
+
setValue(colLabel, [...newSet]);
|
|
3825
|
+
}, value: item, children: [jsxRuntime.jsx(react.RadioGroup.ItemHiddenInput, {}), jsxRuntime.jsx(react.RadioGroup.ItemIndicator, {}), jsxRuntime.jsx(react.RadioGroup.ItemText, { children: !!renderDisplay === true
|
|
3826
|
+
? renderDisplay(item)
|
|
3827
|
+
: translate.t(removeIndex(`${colLabel}.${item}`)) })] }, `${colLabel}-${item}`));
|
|
3828
|
+
}) }) }) }));
|
|
3829
|
+
}
|
|
3802
3830
|
return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
|
|
3803
3831
|
gridRow, children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
|
|
3804
3832
|
const item = enumValue;
|
|
@@ -3814,7 +3842,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
|
3814
3842
|
setOpenSearchResult(true);
|
|
3815
3843
|
}, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
|
|
3816
3844
|
setOpenSearchResult(true);
|
|
3817
|
-
}, children: watchEnum === undefined
|
|
3845
|
+
}, justifyContent: "start", children: watchEnum === undefined
|
|
3818
3846
|
? ""
|
|
3819
3847
|
: 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
3848
|
onSearchChange(event);
|
|
@@ -4204,7 +4232,7 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
4204
4232
|
setValue(column, currentFiles.filter(({ name }) => {
|
|
4205
4233
|
return name !== file.name;
|
|
4206
4234
|
}));
|
|
4207
|
-
}, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsxRuntime.jsx(react.Box, { children: file.name }), jsxRuntime.jsx(ti.TiDeleteOutline, {})] }) }, file.name));
|
|
4235
|
+
}, 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
4236
|
}) }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
4209
4237
|
};
|
|
4210
4238
|
|
|
@@ -4337,7 +4365,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4337
4365
|
setOpenSearchResult(true);
|
|
4338
4366
|
}, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
|
|
4339
4367
|
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) => {
|
|
4368
|
+
}, 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
4369
|
onSearchChange(event);
|
|
4342
4370
|
setOpenSearchResult(true);
|
|
4343
4371
|
}, 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 +4385,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4357
4385
|
item[column_ref],
|
|
4358
4386
|
]);
|
|
4359
4387
|
setValue(colLabel, [...newSet]);
|
|
4360
|
-
}, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
|
|
4388
|
+
}, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
|
|
4389
|
+
? { color: "colorPalette.400/50" }
|
|
4390
|
+
: {}), children: !!renderDisplay === true
|
|
4361
4391
|
? renderDisplay(item)
|
|
4362
4392
|
: item[display_column] }, item[column_ref]));
|
|
4363
4393
|
}) }), 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 +4587,115 @@ const TagPicker = ({ column, schema, prefix }) => {
|
|
|
4557
4587
|
}), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
|
|
4558
4588
|
};
|
|
4559
4589
|
|
|
4590
|
+
function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
|
|
4591
|
+
am: "am",
|
|
4592
|
+
pm: "pm",
|
|
4593
|
+
}, onChange = () => { }, }) {
|
|
4594
|
+
const hours = Array.from({ length: 12 }, (_, i) => {
|
|
4595
|
+
const hour = i + 1;
|
|
4596
|
+
return hour.toString().padStart(2, "0");
|
|
4597
|
+
});
|
|
4598
|
+
const minutes = Array.from({ length: 60 }, (_, i) => {
|
|
4599
|
+
return i.toString().padStart(2, "0");
|
|
4600
|
+
});
|
|
4601
|
+
const hoursCollection = react.createListCollection({
|
|
4602
|
+
items: hours.map((hour) => ({
|
|
4603
|
+
value: hour,
|
|
4604
|
+
label: hour,
|
|
4605
|
+
})),
|
|
4606
|
+
});
|
|
4607
|
+
const minutesCollection = react.createListCollection({
|
|
4608
|
+
items: minutes.map((hour) => ({
|
|
4609
|
+
value: hour,
|
|
4610
|
+
label: hour,
|
|
4611
|
+
})),
|
|
4612
|
+
});
|
|
4613
|
+
const meridiemsCollection = react.createListCollection({
|
|
4614
|
+
items: ["am", "pm"].map((hour) => ({
|
|
4615
|
+
value: hour,
|
|
4616
|
+
label: meridiemLabel[hour] ?? hour,
|
|
4617
|
+
})),
|
|
4618
|
+
});
|
|
4619
|
+
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) => {
|
|
4620
|
+
setHour(parseInt(e.value[0]));
|
|
4621
|
+
onChange({ hour: parseInt(e.value[0]), minute, meridiem });
|
|
4622
|
+
}, 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) => {
|
|
4623
|
+
setMinute(parseInt(e.value[0]));
|
|
4624
|
+
onChange({ hour, minute: parseInt(e.value[0]), meridiem });
|
|
4625
|
+
}, 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) => {
|
|
4626
|
+
setMeridiem(e.value[0]);
|
|
4627
|
+
onChange({ hour, minute, meridiem: e.value[0] });
|
|
4628
|
+
}, 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))) }) })] })] }));
|
|
4629
|
+
}
|
|
4630
|
+
|
|
4631
|
+
const TimePicker = ({ column, schema, prefix }) => {
|
|
4632
|
+
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
4633
|
+
const { translate } = useSchemaContext();
|
|
4634
|
+
const { required, gridColumn, gridRow } = schema;
|
|
4635
|
+
const isRequired = required?.some((columnId) => columnId === column);
|
|
4636
|
+
const colLabel = `${prefix}${column}`;
|
|
4637
|
+
const [open, setOpen] = React.useState(false);
|
|
4638
|
+
const value = watch(colLabel);
|
|
4639
|
+
const formatedTime = dayjs(value).format("hh:mm A");
|
|
4640
|
+
// Parse the initial time parts from the ISO time string (HH:mm:ss)
|
|
4641
|
+
const parseTime = (isoTime) => {
|
|
4642
|
+
if (!isoTime)
|
|
4643
|
+
return { hour: 12, minute: 0, meridiem: "am" };
|
|
4644
|
+
const parsed = dayjs(isoTime);
|
|
4645
|
+
if (!parsed.isValid())
|
|
4646
|
+
return { hour: 12, minute: 0, meridiem: "am" };
|
|
4647
|
+
let hour = parsed.hour();
|
|
4648
|
+
const minute = parsed.minute();
|
|
4649
|
+
const meridiem = hour >= 12 ? "pm" : "am";
|
|
4650
|
+
if (hour === 0)
|
|
4651
|
+
hour = 12;
|
|
4652
|
+
else if (hour > 12)
|
|
4653
|
+
hour -= 12;
|
|
4654
|
+
return { hour, minute, meridiem };
|
|
4655
|
+
};
|
|
4656
|
+
const initialTime = parseTime(value);
|
|
4657
|
+
const [hour, setHour] = React.useState(initialTime.hour);
|
|
4658
|
+
const [minute, setMinute] = React.useState(initialTime.minute);
|
|
4659
|
+
const [meridiem, setMeridiem] = React.useState(initialTime.meridiem);
|
|
4660
|
+
React.useEffect(() => {
|
|
4661
|
+
const { hour, minute, meridiem } = parseTime(value);
|
|
4662
|
+
setHour(hour);
|
|
4663
|
+
setMinute(minute);
|
|
4664
|
+
setMeridiem(meridiem);
|
|
4665
|
+
}, [value]);
|
|
4666
|
+
// Convert hour, minute, meridiem to 24-hour ISO time string
|
|
4667
|
+
const toIsoTime = (hour, minute, meridiem) => {
|
|
4668
|
+
let h = hour;
|
|
4669
|
+
if (meridiem === "am" && hour === 12)
|
|
4670
|
+
h = 0;
|
|
4671
|
+
else if (meridiem === "pm" && hour < 12)
|
|
4672
|
+
h = hour + 12;
|
|
4673
|
+
return dayjs().hour(h).minute(minute).second(0).toISOString();
|
|
4674
|
+
};
|
|
4675
|
+
// Handle changes to time parts
|
|
4676
|
+
const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
|
|
4677
|
+
setHour(newHour);
|
|
4678
|
+
setMinute(newMinute);
|
|
4679
|
+
setMeridiem(newMeridiem);
|
|
4680
|
+
const isoTime = toIsoTime(newHour, newMinute, newMeridiem);
|
|
4681
|
+
setValue(colLabel, isoTime, { shouldValidate: true, shouldDirty: true });
|
|
4682
|
+
};
|
|
4683
|
+
const containerRef = React.useRef(null);
|
|
4684
|
+
return (jsxRuntime.jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
|
|
4685
|
+
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: () => {
|
|
4686
|
+
setOpen(true);
|
|
4687
|
+
}, 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: {
|
|
4688
|
+
am: translate.t(removeIndex(`${colLabel}.am`)),
|
|
4689
|
+
pm: translate.t(removeIndex(`${colLabel}.pm`)),
|
|
4690
|
+
} }) }) }) }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
4691
|
+
};
|
|
4692
|
+
|
|
4560
4693
|
const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
4561
4694
|
const colSchema = schema;
|
|
4562
4695
|
const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
|
|
4696
|
+
if (variant === "custom-input") {
|
|
4697
|
+
return jsxRuntime.jsx(CustomInput, { schema: colSchema, prefix, column });
|
|
4698
|
+
}
|
|
4563
4699
|
if (type === "string") {
|
|
4564
4700
|
if ((schema.enum ?? []).length > 0) {
|
|
4565
4701
|
return jsxRuntime.jsx(EnumPicker, { schema: colSchema, prefix, column });
|
|
@@ -4571,6 +4707,9 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
|
4571
4707
|
if (variant === "date-picker") {
|
|
4572
4708
|
return jsxRuntime.jsx(DatePicker, { schema: colSchema, prefix, column });
|
|
4573
4709
|
}
|
|
4710
|
+
if (variant === "time-picker") {
|
|
4711
|
+
return jsxRuntime.jsx(TimePicker, { schema: colSchema, prefix, column });
|
|
4712
|
+
}
|
|
4574
4713
|
return jsxRuntime.jsx(StringInputField, { schema: colSchema, prefix, column });
|
|
4575
4714
|
}
|
|
4576
4715
|
if (type === "number" || type === "integer") {
|
|
@@ -4674,22 +4813,15 @@ const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
|
4674
4813
|
};
|
|
4675
4814
|
|
|
4676
4815
|
const FileViewer = ({ column, schema, prefix }) => {
|
|
4677
|
-
const {
|
|
4816
|
+
const { watch } = reactHookForm.useFormContext();
|
|
4678
4817
|
const { translate } = useSchemaContext();
|
|
4679
4818
|
const { required, gridColumn, gridRow } = schema;
|
|
4680
4819
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4681
4820
|
const currentFiles = (watch(column) ?? []);
|
|
4682
4821
|
const colLabel = `${prefix}${column}`;
|
|
4683
|
-
return (jsxRuntime.
|
|
4684
|
-
|
|
4685
|
-
|
|
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`)) }))] }));
|
|
4822
|
+
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) => {
|
|
4823
|
+
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));
|
|
4824
|
+
}) }) }));
|
|
4693
4825
|
};
|
|
4694
4826
|
|
|
4695
4827
|
const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
@@ -4898,9 +5030,24 @@ const StringViewer = ({ column, schema, prefix, }) => {
|
|
|
4898
5030
|
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`)) }))] }) }));
|
|
4899
5031
|
};
|
|
4900
5032
|
|
|
5033
|
+
const CustomViewer = ({ column, schema, prefix }) => {
|
|
5034
|
+
const formContext = reactHookForm.useFormContext();
|
|
5035
|
+
const { inputViewerRender } = schema;
|
|
5036
|
+
return (inputViewerRender &&
|
|
5037
|
+
inputViewerRender({
|
|
5038
|
+
column,
|
|
5039
|
+
schema,
|
|
5040
|
+
prefix,
|
|
5041
|
+
formContext,
|
|
5042
|
+
}));
|
|
5043
|
+
};
|
|
5044
|
+
|
|
4901
5045
|
const SchemaViewer = ({ schema, prefix, column, }) => {
|
|
4902
5046
|
const colSchema = schema;
|
|
4903
5047
|
const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
|
|
5048
|
+
if (variant === "custom-input") {
|
|
5049
|
+
return jsxRuntime.jsx(CustomViewer, { schema: colSchema, prefix, column });
|
|
5050
|
+
}
|
|
4904
5051
|
if (type === "string") {
|
|
4905
5052
|
if ((schema.enum ?? []).length > 0) {
|
|
4906
5053
|
return jsxRuntime.jsx(EnumViewer, { schema: colSchema, prefix, column });
|
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, 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';
|
|
@@ -3638,6 +3638,18 @@ const BooleanPicker = ({ schema, column, prefix }) => {
|
|
|
3638
3638
|
} }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
3639
3639
|
};
|
|
3640
3640
|
|
|
3641
|
+
const CustomInput = ({ column, schema, prefix }) => {
|
|
3642
|
+
const formContext = useFormContext();
|
|
3643
|
+
const { inputRender } = schema;
|
|
3644
|
+
return (inputRender &&
|
|
3645
|
+
inputRender({
|
|
3646
|
+
column,
|
|
3647
|
+
schema,
|
|
3648
|
+
prefix,
|
|
3649
|
+
formContext,
|
|
3650
|
+
}));
|
|
3651
|
+
};
|
|
3652
|
+
|
|
3641
3653
|
const monthNamesShort = [
|
|
3642
3654
|
"Jan",
|
|
3643
3655
|
"Feb",
|
|
@@ -3735,9 +3747,9 @@ const DatePicker = ({ column, schema, prefix }) => {
|
|
|
3735
3747
|
const selectedDate = watch(colLabel);
|
|
3736
3748
|
const formatedDate = dayjs(selectedDate).format("YYYY-MM-DD");
|
|
3737
3749
|
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:
|
|
3750
|
+
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
3751
|
setOpen(true);
|
|
3740
|
-
}, children: selectedDate !== undefined ? `${formatedDate}` : "" }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1
|
|
3752
|
+
}, justifyContent: "start", children: [jsx(MdDateRange, {}), selectedDate !== undefined ? `${formatedDate}` : ""] }) }), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(PopoverTitle, {}), jsx(DatePicker$1
|
|
3741
3753
|
// @ts-expect-error TODO: find appropriate types
|
|
3742
3754
|
, {
|
|
3743
3755
|
// @ts-expect-error TODO: find appropriate types
|
|
@@ -3762,7 +3774,7 @@ function filterArray(array, searchTerm) {
|
|
|
3762
3774
|
const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
3763
3775
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
3764
3776
|
const { translate } = useSchemaContext();
|
|
3765
|
-
const { required } = schema;
|
|
3777
|
+
const { required, variant } = schema;
|
|
3766
3778
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
3767
3779
|
const { gridColumn, gridRow, renderDisplay } = schema;
|
|
3768
3780
|
const [searchText, setSearchText] = useState();
|
|
@@ -3779,6 +3791,22 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
|
3779
3791
|
setSearchText(event.target.value);
|
|
3780
3792
|
setLimit(10);
|
|
3781
3793
|
};
|
|
3794
|
+
if (variant === "radio") {
|
|
3795
|
+
return (jsx(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
|
|
3796
|
+
gridRow, children: jsx(RadioGroup$1.Root, { defaultValue: "1", children: jsx(HStack, { gap: "6", children: filterArray(dataList, searchText ?? "").map((item) => {
|
|
3797
|
+
return (jsxs(RadioGroup$1.Item, { onClick: () => {
|
|
3798
|
+
if (!isMultiple) {
|
|
3799
|
+
setOpenSearchResult(false);
|
|
3800
|
+
setValue(colLabel, item);
|
|
3801
|
+
return;
|
|
3802
|
+
}
|
|
3803
|
+
const newSet = new Set([...(watchEnums ?? []), item]);
|
|
3804
|
+
setValue(colLabel, [...newSet]);
|
|
3805
|
+
}, value: item, children: [jsx(RadioGroup$1.ItemHiddenInput, {}), jsx(RadioGroup$1.ItemIndicator, {}), jsx(RadioGroup$1.ItemText, { children: !!renderDisplay === true
|
|
3806
|
+
? renderDisplay(item)
|
|
3807
|
+
: translate.t(removeIndex(`${colLabel}.${item}`)) })] }, `${colLabel}-${item}`));
|
|
3808
|
+
}) }) }) }));
|
|
3809
|
+
}
|
|
3782
3810
|
return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
|
|
3783
3811
|
gridRow, children: [isMultiple && (jsxs(Flex, { flexFlow: "wrap", gap: 1, children: [watchEnums.map((enumValue) => {
|
|
3784
3812
|
const item = enumValue;
|
|
@@ -3794,7 +3822,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
|
3794
3822
|
setOpenSearchResult(true);
|
|
3795
3823
|
}, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
|
|
3796
3824
|
setOpenSearchResult(true);
|
|
3797
|
-
}, children: watchEnum === undefined
|
|
3825
|
+
}, justifyContent: "start", children: watchEnum === undefined
|
|
3798
3826
|
? ""
|
|
3799
3827
|
: 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
3828
|
onSearchChange(event);
|
|
@@ -4184,7 +4212,7 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
4184
4212
|
setValue(column, currentFiles.filter(({ name }) => {
|
|
4185
4213
|
return name !== file.name;
|
|
4186
4214
|
}));
|
|
4187
|
-
}, display: "flex", flexFlow: "row", alignItems: "center", padding: "2", children: [jsx(Box, { children: file.name }), jsx(TiDeleteOutline, {})] }) }, file.name));
|
|
4215
|
+
}, 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
4216
|
}) }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
4189
4217
|
};
|
|
4190
4218
|
|
|
@@ -4317,7 +4345,7 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4317
4345
|
setOpenSearchResult(true);
|
|
4318
4346
|
}, children: translate.t(removeIndex(`${colLabel}.add_more`)) })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
|
|
4319
4347
|
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) => {
|
|
4348
|
+
}, 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
4349
|
onSearchChange(event);
|
|
4322
4350
|
setOpenSearchResult(true);
|
|
4323
4351
|
}, 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 +4365,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
4337
4365
|
item[column_ref],
|
|
4338
4366
|
]);
|
|
4339
4367
|
setValue(colLabel, [...newSet]);
|
|
4340
|
-
}, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
|
|
4368
|
+
}, opacity: 0.7, _hover: { opacity: 1 }, ...(selected
|
|
4369
|
+
? { color: "colorPalette.400/50" }
|
|
4370
|
+
: {}), children: !!renderDisplay === true
|
|
4341
4371
|
? renderDisplay(item)
|
|
4342
4372
|
: item[display_column] }, item[column_ref]));
|
|
4343
4373
|
}) }), 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 +4567,115 @@ const TagPicker = ({ column, schema, prefix }) => {
|
|
|
4537
4567
|
}), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
|
|
4538
4568
|
};
|
|
4539
4569
|
|
|
4570
|
+
function TimePicker$1({ hour, setHour, minute, setMinute, meridiem, setMeridiem, meridiemLabel = {
|
|
4571
|
+
am: "am",
|
|
4572
|
+
pm: "pm",
|
|
4573
|
+
}, onChange = () => { }, }) {
|
|
4574
|
+
const hours = Array.from({ length: 12 }, (_, i) => {
|
|
4575
|
+
const hour = i + 1;
|
|
4576
|
+
return hour.toString().padStart(2, "0");
|
|
4577
|
+
});
|
|
4578
|
+
const minutes = Array.from({ length: 60 }, (_, i) => {
|
|
4579
|
+
return i.toString().padStart(2, "0");
|
|
4580
|
+
});
|
|
4581
|
+
const hoursCollection = createListCollection({
|
|
4582
|
+
items: hours.map((hour) => ({
|
|
4583
|
+
value: hour,
|
|
4584
|
+
label: hour,
|
|
4585
|
+
})),
|
|
4586
|
+
});
|
|
4587
|
+
const minutesCollection = createListCollection({
|
|
4588
|
+
items: minutes.map((hour) => ({
|
|
4589
|
+
value: hour,
|
|
4590
|
+
label: hour,
|
|
4591
|
+
})),
|
|
4592
|
+
});
|
|
4593
|
+
const meridiemsCollection = createListCollection({
|
|
4594
|
+
items: ["am", "pm"].map((hour) => ({
|
|
4595
|
+
value: hour,
|
|
4596
|
+
label: meridiemLabel[hour] ?? hour,
|
|
4597
|
+
})),
|
|
4598
|
+
});
|
|
4599
|
+
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) => {
|
|
4600
|
+
setHour(parseInt(e.value[0]));
|
|
4601
|
+
onChange({ hour: parseInt(e.value[0]), minute, meridiem });
|
|
4602
|
+
}, 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) => {
|
|
4603
|
+
setMinute(parseInt(e.value[0]));
|
|
4604
|
+
onChange({ hour, minute: parseInt(e.value[0]), meridiem });
|
|
4605
|
+
}, 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) => {
|
|
4606
|
+
setMeridiem(e.value[0]);
|
|
4607
|
+
onChange({ hour, minute, meridiem: e.value[0] });
|
|
4608
|
+
}, 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))) }) })] })] }));
|
|
4609
|
+
}
|
|
4610
|
+
|
|
4611
|
+
const TimePicker = ({ column, schema, prefix }) => {
|
|
4612
|
+
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4613
|
+
const { translate } = useSchemaContext();
|
|
4614
|
+
const { required, gridColumn, gridRow } = schema;
|
|
4615
|
+
const isRequired = required?.some((columnId) => columnId === column);
|
|
4616
|
+
const colLabel = `${prefix}${column}`;
|
|
4617
|
+
const [open, setOpen] = useState(false);
|
|
4618
|
+
const value = watch(colLabel);
|
|
4619
|
+
const formatedTime = dayjs(value).format("hh:mm A");
|
|
4620
|
+
// Parse the initial time parts from the ISO time string (HH:mm:ss)
|
|
4621
|
+
const parseTime = (isoTime) => {
|
|
4622
|
+
if (!isoTime)
|
|
4623
|
+
return { hour: 12, minute: 0, meridiem: "am" };
|
|
4624
|
+
const parsed = dayjs(isoTime);
|
|
4625
|
+
if (!parsed.isValid())
|
|
4626
|
+
return { hour: 12, minute: 0, meridiem: "am" };
|
|
4627
|
+
let hour = parsed.hour();
|
|
4628
|
+
const minute = parsed.minute();
|
|
4629
|
+
const meridiem = hour >= 12 ? "pm" : "am";
|
|
4630
|
+
if (hour === 0)
|
|
4631
|
+
hour = 12;
|
|
4632
|
+
else if (hour > 12)
|
|
4633
|
+
hour -= 12;
|
|
4634
|
+
return { hour, minute, meridiem };
|
|
4635
|
+
};
|
|
4636
|
+
const initialTime = parseTime(value);
|
|
4637
|
+
const [hour, setHour] = useState(initialTime.hour);
|
|
4638
|
+
const [minute, setMinute] = useState(initialTime.minute);
|
|
4639
|
+
const [meridiem, setMeridiem] = useState(initialTime.meridiem);
|
|
4640
|
+
useEffect(() => {
|
|
4641
|
+
const { hour, minute, meridiem } = parseTime(value);
|
|
4642
|
+
setHour(hour);
|
|
4643
|
+
setMinute(minute);
|
|
4644
|
+
setMeridiem(meridiem);
|
|
4645
|
+
}, [value]);
|
|
4646
|
+
// Convert hour, minute, meridiem to 24-hour ISO time string
|
|
4647
|
+
const toIsoTime = (hour, minute, meridiem) => {
|
|
4648
|
+
let h = hour;
|
|
4649
|
+
if (meridiem === "am" && hour === 12)
|
|
4650
|
+
h = 0;
|
|
4651
|
+
else if (meridiem === "pm" && hour < 12)
|
|
4652
|
+
h = hour + 12;
|
|
4653
|
+
return dayjs().hour(h).minute(minute).second(0).toISOString();
|
|
4654
|
+
};
|
|
4655
|
+
// Handle changes to time parts
|
|
4656
|
+
const handleTimeChange = ({ hour: newHour, minute: newMinute, meridiem: newMeridiem, }) => {
|
|
4657
|
+
setHour(newHour);
|
|
4658
|
+
setMinute(newMinute);
|
|
4659
|
+
setMeridiem(newMeridiem);
|
|
4660
|
+
const isoTime = toIsoTime(newHour, newMinute, newMeridiem);
|
|
4661
|
+
setValue(colLabel, isoTime, { shouldValidate: true, shouldDirty: true });
|
|
4662
|
+
};
|
|
4663
|
+
const containerRef = useRef(null);
|
|
4664
|
+
return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
|
|
4665
|
+
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: () => {
|
|
4666
|
+
setOpen(true);
|
|
4667
|
+
}, 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: {
|
|
4668
|
+
am: translate.t(removeIndex(`${colLabel}.am`)),
|
|
4669
|
+
pm: translate.t(removeIndex(`${colLabel}.pm`)),
|
|
4670
|
+
} }) }) }) }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
4671
|
+
};
|
|
4672
|
+
|
|
4540
4673
|
const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
4541
4674
|
const colSchema = schema;
|
|
4542
4675
|
const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
|
|
4676
|
+
if (variant === "custom-input") {
|
|
4677
|
+
return jsx(CustomInput, { schema: colSchema, prefix, column });
|
|
4678
|
+
}
|
|
4543
4679
|
if (type === "string") {
|
|
4544
4680
|
if ((schema.enum ?? []).length > 0) {
|
|
4545
4681
|
return jsx(EnumPicker, { schema: colSchema, prefix, column });
|
|
@@ -4551,6 +4687,9 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
|
4551
4687
|
if (variant === "date-picker") {
|
|
4552
4688
|
return jsx(DatePicker, { schema: colSchema, prefix, column });
|
|
4553
4689
|
}
|
|
4690
|
+
if (variant === "time-picker") {
|
|
4691
|
+
return jsx(TimePicker, { schema: colSchema, prefix, column });
|
|
4692
|
+
}
|
|
4554
4693
|
return jsx(StringInputField, { schema: colSchema, prefix, column });
|
|
4555
4694
|
}
|
|
4556
4695
|
if (type === "number" || type === "integer") {
|
|
@@ -4654,22 +4793,15 @@ const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
|
4654
4793
|
};
|
|
4655
4794
|
|
|
4656
4795
|
const FileViewer = ({ column, schema, prefix }) => {
|
|
4657
|
-
const {
|
|
4796
|
+
const { watch } = useFormContext();
|
|
4658
4797
|
const { translate } = useSchemaContext();
|
|
4659
4798
|
const { required, gridColumn, gridRow } = schema;
|
|
4660
4799
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4661
4800
|
const currentFiles = (watch(column) ?? []);
|
|
4662
4801
|
const colLabel = `${prefix}${column}`;
|
|
4663
|
-
return (
|
|
4664
|
-
|
|
4665
|
-
|
|
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`)) }))] }));
|
|
4802
|
+
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) => {
|
|
4803
|
+
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));
|
|
4804
|
+
}) }) }));
|
|
4673
4805
|
};
|
|
4674
4806
|
|
|
4675
4807
|
const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
@@ -4878,9 +5010,24 @@ const StringViewer = ({ column, schema, prefix, }) => {
|
|
|
4878
5010
|
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`)) }))] }) }));
|
|
4879
5011
|
};
|
|
4880
5012
|
|
|
5013
|
+
const CustomViewer = ({ column, schema, prefix }) => {
|
|
5014
|
+
const formContext = useFormContext();
|
|
5015
|
+
const { inputViewerRender } = schema;
|
|
5016
|
+
return (inputViewerRender &&
|
|
5017
|
+
inputViewerRender({
|
|
5018
|
+
column,
|
|
5019
|
+
schema,
|
|
5020
|
+
prefix,
|
|
5021
|
+
formContext,
|
|
5022
|
+
}));
|
|
5023
|
+
};
|
|
5024
|
+
|
|
4881
5025
|
const SchemaViewer = ({ schema, prefix, column, }) => {
|
|
4882
5026
|
const colSchema = schema;
|
|
4883
5027
|
const { type, variant, properties: innerProperties, foreign_key, items, } = schema;
|
|
5028
|
+
if (variant === "custom-input") {
|
|
5029
|
+
return jsx(CustomViewer, { schema: colSchema, prefix, column });
|
|
5030
|
+
}
|
|
4884
5031
|
if (type === "string") {
|
|
4885
5032
|
if ((schema.enum ?? []).length > 0) {
|
|
4886
5033
|
return jsx(EnumViewer, { schema: colSchema, prefix, column });
|
|
@@ -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:
|
|
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,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
|
|
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,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 {};
|