@bsol-oss/react-datatable5 12.0.0-beta.91 → 12.0.0-beta.93
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/README.md +17 -0
- package/dist/index.d.ts +12 -6
- package/dist/index.js +490 -287
- package/dist/index.mjs +490 -288
- package/dist/types/components/DataTable/context/useDataTableServerContext.d.ts +1 -1
- package/dist/types/components/DataTable/controls/ReloadButton.d.ts +1 -1
- package/dist/types/components/DataTable/display/RecordDisplay.d.ts +2 -2
- package/dist/types/components/Form/SchemaFormContext.d.ts +2 -1
- package/dist/types/components/Form/components/core/FormRoot.d.ts +3 -4
- package/dist/types/components/Form/components/fields/ArrayRenderer.d.ts +1 -1
- package/dist/types/components/Form/components/fields/StringInputField.d.ts +0 -1
- package/dist/types/components/Form/components/fields/TextAreaInput.d.ts +0 -5
- package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +8 -0
- package/dist/types/components/Form/components/viewers/ArrayViewer.d.ts +1 -1
- package/dist/types/components/Form/components/viewers/BooleanViewer.d.ts +1 -1
- package/dist/types/components/Form/components/viewers/DateTimeViewer.d.ts +1 -1
- package/dist/types/components/Form/components/viewers/DateViewer.d.ts +1 -1
- package/dist/types/components/Form/components/viewers/IdViewer.d.ts +1 -1
- package/dist/types/components/Form/components/viewers/ObjectViewer.d.ts +1 -1
- package/dist/types/components/Form/components/viewers/RecordViewer.d.ts +2 -2
- package/dist/types/components/Form/components/viewers/StringViewer.d.ts +1 -6
- package/dist/types/components/Form/components/viewers/TextAreaViewer.d.ts +1 -6
- package/dist/types/components/Form/components/viewers/TimeViewer.d.ts +1 -1
- package/dist/types/components/Form/utils/useFormI18n.d.ts +5 -3
- package/dist/types/components/ui/pagination.d.ts +10 -7
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -562,16 +562,111 @@ const { withContext } = react.createRecipeContext({ key: "button" });
|
|
|
562
562
|
const LinkButton = withContext("a");
|
|
563
563
|
|
|
564
564
|
const [RootPropsProvider, useRootProps] = react.createContext({
|
|
565
|
-
name:
|
|
565
|
+
name: 'RootPropsProvider',
|
|
566
566
|
});
|
|
567
567
|
const variantMap = {
|
|
568
|
-
outline: { default:
|
|
569
|
-
solid: { default:
|
|
570
|
-
subtle: { default:
|
|
568
|
+
outline: { default: 'ghost', ellipsis: 'plain', current: 'outline' },
|
|
569
|
+
solid: { default: 'outline', ellipsis: 'outline', current: 'solid' },
|
|
570
|
+
subtle: { default: 'ghost', ellipsis: 'plain', current: 'subtle' },
|
|
571
571
|
};
|
|
572
572
|
const PaginationRoot = React__namespace.forwardRef(function PaginationRoot(props, ref) {
|
|
573
|
-
const { size =
|
|
574
|
-
|
|
573
|
+
const { size = 'sm', variant = 'outline', getHref, siblingCount, minSiblingCount = 1, maxSiblingCount, ...rest } = props;
|
|
574
|
+
const containerRef = React__namespace.useRef(null);
|
|
575
|
+
const [calculatedSiblingCount, setCalculatedSiblingCount] = React__namespace.useState(siblingCount);
|
|
576
|
+
React__namespace.useEffect(() => {
|
|
577
|
+
if (siblingCount !== undefined || !containerRef.current) {
|
|
578
|
+
setCalculatedSiblingCount(siblingCount);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
const container = containerRef.current;
|
|
582
|
+
let rafId = null;
|
|
583
|
+
const calculateSiblingCount = () => {
|
|
584
|
+
if (!container)
|
|
585
|
+
return;
|
|
586
|
+
const width = container.offsetWidth;
|
|
587
|
+
if (width === 0)
|
|
588
|
+
return;
|
|
589
|
+
// Estimate button width based on size
|
|
590
|
+
// These are approximate widths including padding for different button sizes
|
|
591
|
+
const buttonWidthMap = {
|
|
592
|
+
xs: 28,
|
|
593
|
+
sm: 36,
|
|
594
|
+
md: 40,
|
|
595
|
+
lg: 44,
|
|
596
|
+
};
|
|
597
|
+
let buttonWidth = buttonWidthMap[size] || 36;
|
|
598
|
+
// Try to measure actual button if available (for more accuracy)
|
|
599
|
+
const buttons = container.querySelectorAll('button');
|
|
600
|
+
if (buttons.length > 0) {
|
|
601
|
+
const firstButton = buttons[0];
|
|
602
|
+
if (firstButton.offsetWidth > 0) {
|
|
603
|
+
// Use measured width, but account for text content variation
|
|
604
|
+
const measuredWidth = firstButton.offsetWidth;
|
|
605
|
+
// Page number buttons might be slightly wider due to text, use measured width
|
|
606
|
+
buttonWidth = Math.max(buttonWidth, measuredWidth);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
// Account for prev/next buttons and gaps
|
|
610
|
+
// HStack gap is typically 8px in Chakra UI
|
|
611
|
+
const gap = 8;
|
|
612
|
+
const prevNextWidth = buttonWidth * 2 + gap;
|
|
613
|
+
const availableWidth = Math.max(0, width - prevNextWidth);
|
|
614
|
+
// Each page button takes buttonWidth + gap
|
|
615
|
+
const buttonWithGap = buttonWidth + gap;
|
|
616
|
+
const maxButtons = Math.floor(availableWidth / buttonWithGap);
|
|
617
|
+
// Calculate sibling count
|
|
618
|
+
// Minimum structure: [prev] [1] [current] [last] [next] = 5 buttons
|
|
619
|
+
// With siblings: [prev] [1] [...] [current-N] ... [current] ... [current+N] [...] [last] [next]
|
|
620
|
+
// We need: prev(1) + first(1) + ellipsis(1) + siblings*2 + current(1) + ellipsis(1) + last(1) + next(1)
|
|
621
|
+
// Minimum: 5 buttons (prev, first, current, last, next)
|
|
622
|
+
// With siblings: 5 + siblings*2 + ellipsis*2 (if needed)
|
|
623
|
+
const minRequired = 5;
|
|
624
|
+
const extraButtons = Math.max(0, maxButtons - minRequired);
|
|
625
|
+
// Calculate sibling count
|
|
626
|
+
// If we have enough space for ellipsis (2 buttons), account for that
|
|
627
|
+
let calculated = minSiblingCount;
|
|
628
|
+
if (extraButtons >= 4) {
|
|
629
|
+
// Space for ellipsis (2) + siblings
|
|
630
|
+
calculated = Math.floor((extraButtons - 2) / 2);
|
|
631
|
+
}
|
|
632
|
+
else if (extraButtons >= 2) {
|
|
633
|
+
// Space for some siblings but not ellipsis
|
|
634
|
+
calculated = Math.floor(extraButtons / 2);
|
|
635
|
+
}
|
|
636
|
+
// Apply max limit if provided
|
|
637
|
+
if (maxSiblingCount !== undefined) {
|
|
638
|
+
calculated = Math.min(calculated, maxSiblingCount);
|
|
639
|
+
}
|
|
640
|
+
setCalculatedSiblingCount(Math.max(minSiblingCount, calculated));
|
|
641
|
+
};
|
|
642
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
643
|
+
// Use requestAnimationFrame to debounce and ensure DOM is updated
|
|
644
|
+
if (rafId !== null) {
|
|
645
|
+
cancelAnimationFrame(rafId);
|
|
646
|
+
}
|
|
647
|
+
rafId = requestAnimationFrame(calculateSiblingCount);
|
|
648
|
+
});
|
|
649
|
+
resizeObserver.observe(container);
|
|
650
|
+
// Initial calculation after a short delay to ensure buttons are rendered
|
|
651
|
+
const timeoutId = setTimeout(calculateSiblingCount, 100);
|
|
652
|
+
return () => {
|
|
653
|
+
resizeObserver.disconnect();
|
|
654
|
+
if (rafId !== null) {
|
|
655
|
+
cancelAnimationFrame(rafId);
|
|
656
|
+
}
|
|
657
|
+
clearTimeout(timeoutId);
|
|
658
|
+
};
|
|
659
|
+
}, [size, siblingCount, minSiblingCount, maxSiblingCount]);
|
|
660
|
+
const mergedRef = React__namespace.useCallback((node) => {
|
|
661
|
+
if (typeof ref === 'function') {
|
|
662
|
+
ref(node);
|
|
663
|
+
}
|
|
664
|
+
else if (ref) {
|
|
665
|
+
ref.current = node;
|
|
666
|
+
}
|
|
667
|
+
containerRef.current = node;
|
|
668
|
+
}, [ref]);
|
|
669
|
+
return (jsxRuntime.jsx(RootPropsProvider, { value: { size, variantMap: variantMap[variant], getHref }, children: jsxRuntime.jsx(react.Pagination.Root, { ref: mergedRef, type: getHref ? 'link' : 'button', siblingCount: calculatedSiblingCount, ...rest }) }));
|
|
575
670
|
});
|
|
576
671
|
const PaginationEllipsis = React__namespace.forwardRef(function PaginationEllipsis(props, ref) {
|
|
577
672
|
const { size, variantMap } = useRootProps();
|
|
@@ -605,16 +700,16 @@ const PaginationNextTrigger = React__namespace.forwardRef(function PaginationNex
|
|
|
605
700
|
});
|
|
606
701
|
const PaginationItems = (props) => {
|
|
607
702
|
return (jsxRuntime.jsx(react.Pagination.Context, { children: ({ pages }) => pages.map((page, index) => {
|
|
608
|
-
return page.type ===
|
|
703
|
+
return page.type === 'ellipsis' ? (jsxRuntime.jsx(PaginationEllipsis, { index: index, ...props }, index)) : (jsxRuntime.jsx(PaginationItem, { type: "page", value: page.value, ...props }, index));
|
|
609
704
|
}) }));
|
|
610
705
|
};
|
|
611
706
|
React__namespace.forwardRef(function PaginationPageText(props, ref) {
|
|
612
|
-
const { format =
|
|
707
|
+
const { format = 'compact', ...rest } = props;
|
|
613
708
|
const { page, totalPages, pageRange, count } = react.usePaginationContext();
|
|
614
709
|
const content = React__namespace.useMemo(() => {
|
|
615
|
-
if (format ===
|
|
710
|
+
if (format === 'short')
|
|
616
711
|
return `${page} / ${totalPages}`;
|
|
617
|
-
if (format ===
|
|
712
|
+
if (format === 'compact')
|
|
618
713
|
return `${page} / ${totalPages}`;
|
|
619
714
|
return `${pageRange.start + 1} - ${Math.min(pageRange.end, count)} / ${count}`;
|
|
620
715
|
}, [format, page, totalPages, pageRange, count]);
|
|
@@ -2753,23 +2848,28 @@ const DataTableServerContext = React.createContext({
|
|
|
2753
2848
|
const useDataTableServerContext = () => {
|
|
2754
2849
|
const context = React.useContext(DataTableServerContext);
|
|
2755
2850
|
const { query } = context;
|
|
2756
|
-
const isEmpty = (query.data?.count ?? 0) <= 0;
|
|
2851
|
+
const isEmpty = query ? (query.data?.count ?? 0) <= 0 : false;
|
|
2757
2852
|
return { ...context, isEmpty };
|
|
2758
2853
|
};
|
|
2759
2854
|
|
|
2760
|
-
const ReloadButton = ({ variant =
|
|
2761
|
-
const
|
|
2855
|
+
const ReloadButton = ({ variant = 'icon' }) => {
|
|
2856
|
+
const serverContext = useDataTableServerContext();
|
|
2857
|
+
const { url, query } = serverContext;
|
|
2762
2858
|
const queryClient = reactQuery.useQueryClient();
|
|
2763
2859
|
const { tableLabel } = useDataTableContext();
|
|
2764
2860
|
const { reloadTooltip, reloadButtonText } = tableLabel;
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
}, "aria-label": "refresh", children: jsxRuntime.jsx(io5.IoReload, {}) }) }));
|
|
2769
|
-
}
|
|
2770
|
-
return (jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
|
|
2861
|
+
const handleReload = () => {
|
|
2862
|
+
// Only invalidate queries for server-side tables (when query exists)
|
|
2863
|
+
if (query && url) {
|
|
2771
2864
|
queryClient.invalidateQueries({ queryKey: [url] });
|
|
2772
|
-
}
|
|
2865
|
+
}
|
|
2866
|
+
// For client-side tables, reload button doesn't need to do anything
|
|
2867
|
+
// as the data is already in memory
|
|
2868
|
+
};
|
|
2869
|
+
if (variant === 'icon') {
|
|
2870
|
+
return (jsxRuntime.jsx(Tooltip, { showArrow: true, content: reloadTooltip, children: jsxRuntime.jsx(Button, { variant: 'ghost', onClick: handleReload, "aria-label": 'refresh', children: jsxRuntime.jsx(io5.IoReload, {}) }) }));
|
|
2871
|
+
}
|
|
2872
|
+
return (jsxRuntime.jsxs(Button, { variant: 'ghost', onClick: handleReload, children: [jsxRuntime.jsx(io5.IoReload, {}), " ", reloadButtonText] }));
|
|
2773
2873
|
};
|
|
2774
2874
|
|
|
2775
2875
|
const InputGroup = React__namespace.forwardRef(function InputGroup(props, ref) {
|
|
@@ -3102,14 +3202,14 @@ const DefaultCardTitle = () => {
|
|
|
3102
3202
|
const TableCards = ({ isSelectable = false, showDisplayNameOnly = false, renderTitle = DefaultCardTitle, cardBodyProps = {}, }) => {
|
|
3103
3203
|
const { table, rowSelection, setRowSelection } = useDataTableContext();
|
|
3104
3204
|
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: table.getRowModel().rows.map((row) => {
|
|
3105
|
-
return (jsxRuntime.jsx(react.Card.Root, { flex: '1 0 20rem', children: jsxRuntime.jsxs(react.Card.Body, { display: 'flex', flexFlow: 'column', gap: '0.5rem', ...cardBodyProps, children: [isSelectable && (jsxRuntime.jsx(Checkbox, {
|
|
3205
|
+
return (jsxRuntime.jsx(react.Card.Root, { flex: '1 0 20rem', children: jsxRuntime.jsxs(react.Card.Body, { display: 'flex', flexFlow: 'column', gap: '0.5rem', ...cardBodyProps, children: [isSelectable && (jsxRuntime.jsx(Checkbox, { checked: isRowSelected(row.id, rowSelection),
|
|
3106
3206
|
disabled: !canRowSelect(row),
|
|
3107
3207
|
// indeterminate: row.getIsSomeSelected(),
|
|
3108
3208
|
onChange: createRowToggleHandler(row, rowSelection, setRowSelection) })), renderTitle(row), jsxRuntime.jsx(react.Grid, { templateColumns: 'auto 1fr', gap: '1rem', children: row.getVisibleCells().map((cell) => {
|
|
3109
|
-
return (jsxRuntime.jsxs(
|
|
3209
|
+
return (jsxRuntime.jsxs(react.Box, { display: "contents", children: [jsxRuntime.jsxs(react.Box, { children: [showDisplayNameOnly && (jsxRuntime.jsx(react.Text, { fontWeight: 'bold', children: cell.column.columnDef.meta?.displayName ??
|
|
3110
3210
|
cell.column.id })), !showDisplayNameOnly && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactTable.flexRender(cell.column.columnDef.header,
|
|
3111
3211
|
// @ts-expect-error Assuming the CellContext interface is the same as HeaderContext
|
|
3112
|
-
cell.getContext()) }))] }
|
|
3212
|
+
cell.getContext()) }))] }), jsxRuntime.jsx(react.Box, { justifySelf: 'end', children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) })] }, `chakra-table-cardcell-${cell.id}`));
|
|
3113
3213
|
}) })] }) }, `chakra-table-card-${row.id}`));
|
|
3114
3214
|
}) }));
|
|
3115
3215
|
};
|
|
@@ -3140,9 +3240,13 @@ const TableFooter = ({ showSelector = false, alwaysShowSelector = true, }) => {
|
|
|
3140
3240
|
}
|
|
3141
3241
|
return false;
|
|
3142
3242
|
};
|
|
3143
|
-
return (jsxRuntime.jsx(react.Table.Footer, { children: table.getFooterGroups().map((footerGroup) => (jsxRuntime.jsxs(react.Table.Row, { display: 'flex', children: [showSelector && (jsxRuntime.
|
|
3144
|
-
|
|
3145
|
-
|
|
3243
|
+
return (jsxRuntime.jsx(react.Table.Footer, { children: table.getFooterGroups().map((footerGroup) => (jsxRuntime.jsxs(react.Table.Row, { display: 'flex', children: [showSelector && (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: 'grid', justifyItems: 'center', alignItems: 'center', color: {
|
|
3244
|
+
base: 'colorPalette.900',
|
|
3245
|
+
_dark: 'colorPalette.100',
|
|
3246
|
+
},
|
|
3247
|
+
bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, children: isCheckBoxVisible() ? (jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: areAllRowsSelected(table, rowSelection),
|
|
3248
|
+
// indeterminate: areSomeRowsSelected(table, rowSelection),
|
|
3249
|
+
onChange: createToggleAllRowsHandler(table, rowSelection, setRowSelection) })) : (jsxRuntime.jsx(react.Box, { as: "span", width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` })) })), footerGroup.headers.map((header) => (jsxRuntime.jsx(react.Table.Cell, { padding: '0', columnSpan: `${header.colSpan}`,
|
|
3146
3250
|
// styling resize and pinning start
|
|
3147
3251
|
maxWidth: `${header.getSize()}px`, width: `${header.getSize()}px`, display: 'grid', children: jsxRuntime.jsx(react.MenuRoot, { children: jsxRuntime.jsx(react.MenuTrigger, { asChild: true, children: jsxRuntime.jsx(react.Box, { padding: `${table.getDensityValue()}px`, display: 'flex', alignItems: 'center', justifyContent: 'start', borderRadius: '0rem', children: jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: 'center', children: [header.isPlaceholder
|
|
3148
3252
|
? null
|
|
@@ -3374,7 +3478,7 @@ const TextWithCopy = ({ text, globalFilter, highlightedText, }) => {
|
|
|
3374
3478
|
const displayText = highlightedText !== undefined
|
|
3375
3479
|
? highlightedText
|
|
3376
3480
|
: highlightText$1(textValue, globalFilter);
|
|
3377
|
-
return (jsxRuntime.jsxs(react.HStack, { gap: 2, alignItems: "center", children: [jsxRuntime.jsx(react.Text, { as: "span", children: displayText }), jsxRuntime.jsx(react.Clipboard.Root, { value: textValue, children: jsxRuntime.jsx(react.Clipboard.Trigger, { asChild: true, children: jsxRuntime.jsx(react.IconButton, { size: "xs", variant: "ghost", "aria-label": "Copy", children: jsxRuntime.jsx(react.Clipboard.Indicator, { copied: jsxRuntime.jsx(lu.LuCheck, {}), children: jsxRuntime.jsx(lu.LuCopy, {}) }) }) }) })] }));
|
|
3481
|
+
return (jsxRuntime.jsxs(react.HStack, { gap: 2, alignItems: "center", children: [jsxRuntime.jsx(react.Text, { as: "span", children: displayText }), jsxRuntime.jsx(react.Clipboard.Root, { value: textValue, children: jsxRuntime.jsx(react.Clipboard.Trigger, { asChild: true, children: jsxRuntime.jsx(react.IconButton, { size: "xs", variant: "ghost", "aria-label": "Copy", fontSize: "1em", children: jsxRuntime.jsx(react.Clipboard.Indicator, { copied: jsxRuntime.jsx(lu.LuCheck, {}), children: jsxRuntime.jsx(lu.LuCopy, {}) }) }) }) })] }));
|
|
3378
3482
|
};
|
|
3379
3483
|
|
|
3380
3484
|
// Helper function to highlight matching text
|
|
@@ -3628,7 +3732,7 @@ const snakeToLabel = (str) => {
|
|
|
3628
3732
|
.join(" "); // Join with space
|
|
3629
3733
|
};
|
|
3630
3734
|
|
|
3631
|
-
const RecordDisplay = ({ object, boxProps, translate, prefix =
|
|
3735
|
+
const RecordDisplay = ({ object, boxProps, translate, prefix = '', }) => {
|
|
3632
3736
|
const getColumn = ({ field }) => {
|
|
3633
3737
|
if (translate !== undefined) {
|
|
3634
3738
|
return translate.t(`${prefix}${field}`);
|
|
@@ -3638,8 +3742,9 @@ const RecordDisplay = ({ object, boxProps, translate, prefix = "", }) => {
|
|
|
3638
3742
|
if (object === null) {
|
|
3639
3743
|
return jsxRuntime.jsx(jsxRuntime.Fragment, { children: "null" });
|
|
3640
3744
|
}
|
|
3641
|
-
return (jsxRuntime.jsx(react.Grid, { rowGap: 1, padding: 1, overflow:
|
|
3642
|
-
|
|
3745
|
+
return (jsxRuntime.jsx(react.Grid, { rowGap: 1, padding: 1, overflow: 'auto', ...boxProps, children: Object.entries(object).map(([field, value], index) => {
|
|
3746
|
+
const uniqueKey = `${prefix}${field}-${index}`;
|
|
3747
|
+
return (jsxRuntime.jsxs(react.Grid, { columnGap: 2, gridTemplateColumns: 'auto 1fr', children: [jsxRuntime.jsx(react.Text, { color: 'colorPalette.400', children: getColumn({ field }) }), typeof value === 'object' && value !== null ? (jsxRuntime.jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsxRuntime.jsx(react.Text, { children: JSON.stringify(value) }))] }, uniqueKey));
|
|
3643
3748
|
}) }));
|
|
3644
3749
|
};
|
|
3645
3750
|
|
|
@@ -3930,13 +4035,10 @@ const idPickerSanityCheck = (column, foreign_key) => {
|
|
|
3930
4035
|
if (!!foreign_key == false) {
|
|
3931
4036
|
throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
|
|
3932
4037
|
}
|
|
3933
|
-
const { table, column: foreignKeyColumn
|
|
4038
|
+
const { table, column: foreignKeyColumn } = foreign_key;
|
|
3934
4039
|
if (!!table == false) {
|
|
3935
4040
|
throw new Error(`The key table does not exist in properties of column ${table} when using id-picker.`);
|
|
3936
4041
|
}
|
|
3937
|
-
if (!!display_column == false) {
|
|
3938
|
-
throw new Error(`The key display_column does not exist in properties of column ${column} when using id-picker.`);
|
|
3939
|
-
}
|
|
3940
4042
|
if (!!foreignKeyColumn == false) {
|
|
3941
4043
|
throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
|
|
3942
4044
|
}
|
|
@@ -3945,7 +4047,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
3945
4047
|
showSubmitButton: true,
|
|
3946
4048
|
showResetButton: true,
|
|
3947
4049
|
showTitle: true,
|
|
3948
|
-
}, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, insideDialog = false, }) => {
|
|
4050
|
+
}, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, insideDialog = false, }) => {
|
|
3949
4051
|
const [isSuccess, setIsSuccess] = React.useState(false);
|
|
3950
4052
|
const [isError, setIsError] = React.useState(false);
|
|
3951
4053
|
const [isSubmiting, setIsSubmiting] = React.useState(false);
|
|
@@ -4035,6 +4137,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
4035
4137
|
idPickerLabels,
|
|
4036
4138
|
enumPickerLabels,
|
|
4037
4139
|
filePickerLabels,
|
|
4140
|
+
formButtonLabels,
|
|
4038
4141
|
ajvResolver: ajvResolver(schema),
|
|
4039
4142
|
insideDialog,
|
|
4040
4143
|
}, children: jsxRuntime.jsx(reactHookForm.FormProvider, { ...form, children: children }) }));
|
|
@@ -4044,40 +4147,107 @@ function removeIndex(str) {
|
|
|
4044
4147
|
return str.replace(/\.\d+\./g, ".");
|
|
4045
4148
|
}
|
|
4046
4149
|
|
|
4150
|
+
/**
|
|
4151
|
+
* Custom hook to simplify i18n translation for form fields.
|
|
4152
|
+
* Automatically handles colLabel construction and removeIndex logic.
|
|
4153
|
+
*
|
|
4154
|
+
* @param column - The column name
|
|
4155
|
+
* @param prefix - The prefix for the field (usually empty string or parent path)
|
|
4156
|
+
* @returns Object with translation helper functions
|
|
4157
|
+
*
|
|
4158
|
+
* @example
|
|
4159
|
+
* ```tsx
|
|
4160
|
+
* const formI18n = useFormI18n(column, prefix);
|
|
4161
|
+
*
|
|
4162
|
+
* // Get field label
|
|
4163
|
+
* <Field label={formI18n.label()} />
|
|
4164
|
+
*
|
|
4165
|
+
* // Get error message
|
|
4166
|
+
* <Text>{formI18n.required()}</Text>
|
|
4167
|
+
*
|
|
4168
|
+
* // Get custom translation key
|
|
4169
|
+
* <Text>{formI18n.t('add_more')}</Text>
|
|
4170
|
+
*
|
|
4171
|
+
* // Access the raw colLabel
|
|
4172
|
+
* const colLabel = formI18n.colLabel;
|
|
4173
|
+
* ```
|
|
4174
|
+
*/
|
|
4175
|
+
const useFormI18n$1 = (column, prefix = '', schema) => {
|
|
4176
|
+
const { translate } = useSchemaContext();
|
|
4177
|
+
const colLabel = `${prefix}${column}`;
|
|
4178
|
+
return {
|
|
4179
|
+
/**
|
|
4180
|
+
* The constructed column label (prefix + column)
|
|
4181
|
+
*/
|
|
4182
|
+
colLabel,
|
|
4183
|
+
/**
|
|
4184
|
+
* Get the field label from schema title prop, or fall back to translation
|
|
4185
|
+
* Uses schema.title if available, otherwise: translate.t(removeIndex(`${colLabel}.field_label`))
|
|
4186
|
+
*/
|
|
4187
|
+
label: (options) => {
|
|
4188
|
+
if (schema?.title) {
|
|
4189
|
+
return schema.title;
|
|
4190
|
+
}
|
|
4191
|
+
return translate.t(removeIndex(`${colLabel}.field_label`), options);
|
|
4192
|
+
},
|
|
4193
|
+
/**
|
|
4194
|
+
* Get the required error message translation
|
|
4195
|
+
* Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
|
|
4196
|
+
*/
|
|
4197
|
+
required: (options) => {
|
|
4198
|
+
return translate.t(removeIndex(`${colLabel}.field_required`), options);
|
|
4199
|
+
},
|
|
4200
|
+
/**
|
|
4201
|
+
* Get a translation for any custom key relative to the field
|
|
4202
|
+
* Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
|
|
4203
|
+
*
|
|
4204
|
+
* @param key - The translation key suffix (e.g., 'add_more', 'total', etc.)
|
|
4205
|
+
* @param options - Optional translation options (e.g., defaultValue, interpolation variables)
|
|
4206
|
+
*/
|
|
4207
|
+
t: (key, options) => {
|
|
4208
|
+
return translate.t(removeIndex(`${colLabel}.${key}`), options);
|
|
4209
|
+
},
|
|
4210
|
+
/**
|
|
4211
|
+
* Access to the original translate object for edge cases
|
|
4212
|
+
*/
|
|
4213
|
+
translate,
|
|
4214
|
+
};
|
|
4215
|
+
};
|
|
4216
|
+
|
|
4047
4217
|
const ArrayRenderer = ({ schema, column, prefix, }) => {
|
|
4048
|
-
const { gridRow, gridColumn =
|
|
4218
|
+
const { gridRow, gridColumn = '1/span 12', required, items } = schema;
|
|
4049
4219
|
// @ts-expect-error TODO: find suitable types
|
|
4050
4220
|
const { type } = items;
|
|
4051
|
-
const { translate } = useSchemaContext();
|
|
4052
4221
|
const colLabel = `${prefix}${column}`;
|
|
4053
4222
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4223
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
4054
4224
|
const { formState: { errors }, setValue, watch, } = reactHookForm.useFormContext();
|
|
4055
4225
|
const fields = (watch(colLabel) ?? []);
|
|
4056
|
-
return (jsxRuntime.jsxs(react.Flex, { gridRow, gridColumn, flexFlow:
|
|
4057
|
-
base:
|
|
4058
|
-
_dark:
|
|
4059
|
-
}, children: [jsxRuntime.jsx(react.Grid, { gridTemplateColumns:
|
|
4226
|
+
return (jsxRuntime.jsxs(react.Flex, { gridRow, gridColumn, flexFlow: 'column', gap: 2, children: [jsxRuntime.jsxs(react.Box, { as: "label", children: [formI18n.label(), isRequired && jsxRuntime.jsx("span", { children: "*" })] }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 2, children: fields.map((field, index) => (jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: '1fr auto', gap: 2, bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
|
|
4227
|
+
base: 'colorPalette.200',
|
|
4228
|
+
_dark: 'colorPalette.800',
|
|
4229
|
+
}, children: [jsxRuntime.jsx(react.Grid, { gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: jsxRuntime.jsx(SchemaRenderer, { column: `${index}`,
|
|
4060
4230
|
prefix: `${colLabel}.`,
|
|
4061
4231
|
// @ts-expect-error find suitable types
|
|
4062
|
-
schema: { showLabel: false, ...(items ?? {}) } }) }), jsxRuntime.jsx(react.Flex, { justifyContent:
|
|
4232
|
+
schema: { showLabel: false, ...(items ?? {}) } }) }), jsxRuntime.jsx(react.Flex, { justifyContent: 'end', children: jsxRuntime.jsx(react.Button, { variant: 'ghost', onClick: () => {
|
|
4063
4233
|
setValue(colLabel, fields.filter((_, curIndex) => {
|
|
4064
4234
|
return curIndex !== index;
|
|
4065
4235
|
}));
|
|
4066
4236
|
}, children: jsxRuntime.jsx(react.Icon, { children: jsxRuntime.jsx(cg.CgTrash, {}) }) }) })] }, `${colLabel}.${index}`))) }), jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
4067
|
-
if (type ===
|
|
4237
|
+
if (type === 'number') {
|
|
4068
4238
|
setValue(colLabel, [...fields, 0]);
|
|
4069
4239
|
return;
|
|
4070
4240
|
}
|
|
4071
|
-
if (type ===
|
|
4072
|
-
setValue(colLabel, [...fields,
|
|
4241
|
+
if (type === 'string') {
|
|
4242
|
+
setValue(colLabel, [...fields, '']);
|
|
4073
4243
|
return;
|
|
4074
4244
|
}
|
|
4075
|
-
if (type ===
|
|
4245
|
+
if (type === 'boolean') {
|
|
4076
4246
|
setValue(colLabel, [...fields, false]);
|
|
4077
4247
|
return;
|
|
4078
4248
|
}
|
|
4079
4249
|
setValue(colLabel, [...fields, {}]);
|
|
4080
|
-
}, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color:
|
|
4250
|
+
}, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
4081
4251
|
};
|
|
4082
4252
|
|
|
4083
4253
|
const Field = React__namespace.forwardRef(function Field(props, ref) {
|
|
@@ -4087,15 +4257,13 @@ const Field = React__namespace.forwardRef(function Field(props, ref) {
|
|
|
4087
4257
|
|
|
4088
4258
|
const BooleanPicker = ({ schema, column, prefix }) => {
|
|
4089
4259
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
4090
|
-
const { translate } = useSchemaContext();
|
|
4091
4260
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
4092
4261
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4093
4262
|
const colLabel = `${prefix}${column}`;
|
|
4094
4263
|
const value = watch(colLabel);
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
: undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
|
|
4264
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
4265
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4266
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
|
|
4099
4267
|
setValue(colLabel, !value);
|
|
4100
4268
|
} }) }));
|
|
4101
4269
|
};
|
|
@@ -4211,76 +4379,12 @@ let DatePicker$1 = class DatePicker extends React.Component {
|
|
|
4211
4379
|
}
|
|
4212
4380
|
};
|
|
4213
4381
|
|
|
4214
|
-
/**
|
|
4215
|
-
* Custom hook to simplify i18n translation for form fields.
|
|
4216
|
-
* Automatically handles colLabel construction and removeIndex logic.
|
|
4217
|
-
*
|
|
4218
|
-
* @param column - The column name
|
|
4219
|
-
* @param prefix - The prefix for the field (usually empty string or parent path)
|
|
4220
|
-
* @returns Object with translation helper functions
|
|
4221
|
-
*
|
|
4222
|
-
* @example
|
|
4223
|
-
* ```tsx
|
|
4224
|
-
* const formI18n = useFormI18n(column, prefix);
|
|
4225
|
-
*
|
|
4226
|
-
* // Get field label
|
|
4227
|
-
* <Field label={formI18n.label()} />
|
|
4228
|
-
*
|
|
4229
|
-
* // Get error message
|
|
4230
|
-
* <Text>{formI18n.required()}</Text>
|
|
4231
|
-
*
|
|
4232
|
-
* // Get custom translation key
|
|
4233
|
-
* <Text>{formI18n.t('add_more')}</Text>
|
|
4234
|
-
*
|
|
4235
|
-
* // Access the raw colLabel
|
|
4236
|
-
* const colLabel = formI18n.colLabel;
|
|
4237
|
-
* ```
|
|
4238
|
-
*/
|
|
4239
|
-
const useFormI18n = (column, prefix = "") => {
|
|
4240
|
-
const { translate } = useSchemaContext();
|
|
4241
|
-
const colLabel = `${prefix}${column}`;
|
|
4242
|
-
return {
|
|
4243
|
-
/**
|
|
4244
|
-
* The constructed column label (prefix + column)
|
|
4245
|
-
*/
|
|
4246
|
-
colLabel,
|
|
4247
|
-
/**
|
|
4248
|
-
* Get the field label translation
|
|
4249
|
-
* Equivalent to: translate.t(removeIndex(`${colLabel}.field_label`))
|
|
4250
|
-
*/
|
|
4251
|
-
label: (options) => {
|
|
4252
|
-
return translate.t(removeIndex(`${colLabel}.field_label`), options);
|
|
4253
|
-
},
|
|
4254
|
-
/**
|
|
4255
|
-
* Get the required error message translation
|
|
4256
|
-
* Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
|
|
4257
|
-
*/
|
|
4258
|
-
required: (options) => {
|
|
4259
|
-
return translate.t(removeIndex(`${colLabel}.field_required`), options);
|
|
4260
|
-
},
|
|
4261
|
-
/**
|
|
4262
|
-
* Get a translation for any custom key relative to the field
|
|
4263
|
-
* Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
|
|
4264
|
-
*
|
|
4265
|
-
* @param key - The translation key suffix (e.g., 'add_more', 'total', etc.)
|
|
4266
|
-
* @param options - Optional translation options (e.g., defaultValue, interpolation variables)
|
|
4267
|
-
*/
|
|
4268
|
-
t: (key, options) => {
|
|
4269
|
-
return translate.t(removeIndex(`${colLabel}.${key}`), options);
|
|
4270
|
-
},
|
|
4271
|
-
/**
|
|
4272
|
-
* Access to the original translate object for edge cases
|
|
4273
|
-
*/
|
|
4274
|
-
translate,
|
|
4275
|
-
};
|
|
4276
|
-
};
|
|
4277
|
-
|
|
4278
4382
|
dayjs.extend(utc);
|
|
4279
4383
|
dayjs.extend(timezone);
|
|
4280
4384
|
const DatePicker = ({ column, schema, prefix }) => {
|
|
4281
4385
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
4282
4386
|
const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
|
|
4283
|
-
const formI18n = useFormI18n(column, prefix);
|
|
4387
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
4284
4388
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
|
|
4285
4389
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4286
4390
|
const colLabel = formI18n.colLabel;
|
|
@@ -4398,7 +4502,7 @@ dayjs.extend(timezone);
|
|
|
4398
4502
|
const DateRangePicker = ({ column, schema, prefix, }) => {
|
|
4399
4503
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
4400
4504
|
const { timezone, insideDialog } = useSchemaContext();
|
|
4401
|
-
const formI18n = useFormI18n(column, prefix);
|
|
4505
|
+
const formI18n = useFormI18n$1(column, prefix);
|
|
4402
4506
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
|
|
4403
4507
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4404
4508
|
const colLabel = formI18n.colLabel;
|
|
@@ -4496,7 +4600,7 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
|
|
|
4496
4600
|
const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
|
|
4497
4601
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
4498
4602
|
const { enumPickerLabels, insideDialog } = useSchemaContext();
|
|
4499
|
-
const formI18n = useFormI18n(column, prefix);
|
|
4603
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
4500
4604
|
const { required, variant } = schema;
|
|
4501
4605
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4502
4606
|
const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
|
|
@@ -5140,7 +5244,7 @@ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly =
|
|
|
5140
5244
|
const FilePicker = ({ column, schema, prefix }) => {
|
|
5141
5245
|
const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
|
|
5142
5246
|
const { filePickerLabels } = useSchemaContext();
|
|
5143
|
-
const formI18n = useFormI18n(column, prefix);
|
|
5247
|
+
const formI18n = useFormI18n$1(column, prefix);
|
|
5144
5248
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', type, } = schema;
|
|
5145
5249
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5146
5250
|
const isSingleSelect = type === 'string';
|
|
@@ -5216,7 +5320,7 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
5216
5320
|
const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
5217
5321
|
const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
|
|
5218
5322
|
const { filePickerLabels } = useSchemaContext();
|
|
5219
|
-
const formI18n = useFormI18n(column, prefix);
|
|
5323
|
+
const formI18n = useFormI18n$1(column, prefix);
|
|
5220
5324
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, type, } = schema;
|
|
5221
5325
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5222
5326
|
const isSingleSelect = type === 'string';
|
|
@@ -5357,13 +5461,18 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
|
|
|
5357
5461
|
}
|
|
5358
5462
|
};
|
|
5359
5463
|
|
|
5464
|
+
// Default renderDisplay function that stringifies JSON
|
|
5465
|
+
const defaultRenderDisplay = (item) => {
|
|
5466
|
+
return JSON.stringify(item);
|
|
5467
|
+
};
|
|
5468
|
+
|
|
5360
5469
|
const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
5361
5470
|
const { watch, getValues, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
5362
5471
|
const { serverUrl, idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
|
|
5363
|
-
const formI18n = useFormI18n(column, prefix);
|
|
5472
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5364
5473
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
|
|
5365
5474
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5366
|
-
const { table, column: column_ref,
|
|
5475
|
+
const { table, column: column_ref, customQueryFn, } = foreign_key;
|
|
5367
5476
|
const [searchText, setSearchText] = React.useState('');
|
|
5368
5477
|
const [debouncedSearchText, setDebouncedSearchText] = React.useState('');
|
|
5369
5478
|
const [limit] = React.useState(50); // Increased limit for combobox
|
|
@@ -5398,6 +5507,69 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5398
5507
|
}, 300);
|
|
5399
5508
|
return () => clearTimeout(timer);
|
|
5400
5509
|
}, [searchText]);
|
|
5510
|
+
// Find IDs that are in currentValue but missing from idMap
|
|
5511
|
+
const missingIds = React.useMemo(() => {
|
|
5512
|
+
return currentValue.filter((id) => !idMap[id]);
|
|
5513
|
+
}, [currentValue, idMap]);
|
|
5514
|
+
// Stable key for query based on sorted missing IDs
|
|
5515
|
+
const missingIdsKey = React.useMemo(() => {
|
|
5516
|
+
return JSON.stringify([...missingIds].sort());
|
|
5517
|
+
}, [missingIds]);
|
|
5518
|
+
// Query to fetch initial values that are missing from idMap
|
|
5519
|
+
// This query runs automatically when missingIds.length > 0 and updates idMap
|
|
5520
|
+
const initialValuesQuery = reactQuery.useQuery({
|
|
5521
|
+
queryKey: [`idpicker-initial`, column, missingIdsKey],
|
|
5522
|
+
queryFn: async () => {
|
|
5523
|
+
if (missingIds.length === 0) {
|
|
5524
|
+
return { data: [], count: 0 };
|
|
5525
|
+
}
|
|
5526
|
+
if (customQueryFn) {
|
|
5527
|
+
const { data, idMap } = await customQueryFn({
|
|
5528
|
+
searching: '',
|
|
5529
|
+
limit: missingIds.length,
|
|
5530
|
+
offset: 0,
|
|
5531
|
+
where: [
|
|
5532
|
+
{
|
|
5533
|
+
id: column_ref,
|
|
5534
|
+
value: missingIds.length === 1 ? missingIds[0] : missingIds,
|
|
5535
|
+
},
|
|
5536
|
+
],
|
|
5537
|
+
});
|
|
5538
|
+
setIdMap((state) => {
|
|
5539
|
+
return { ...state, ...idMap };
|
|
5540
|
+
});
|
|
5541
|
+
return data;
|
|
5542
|
+
}
|
|
5543
|
+
const data = await getTableData({
|
|
5544
|
+
serverUrl,
|
|
5545
|
+
searching: '',
|
|
5546
|
+
in_table: table,
|
|
5547
|
+
limit: missingIds.length,
|
|
5548
|
+
offset: 0,
|
|
5549
|
+
where: [
|
|
5550
|
+
{
|
|
5551
|
+
id: column_ref,
|
|
5552
|
+
value: missingIds.length === 1 ? missingIds[0] : missingIds,
|
|
5553
|
+
},
|
|
5554
|
+
],
|
|
5555
|
+
});
|
|
5556
|
+
const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
|
|
5557
|
+
return [
|
|
5558
|
+
item[column_ref],
|
|
5559
|
+
{
|
|
5560
|
+
...item,
|
|
5561
|
+
},
|
|
5562
|
+
];
|
|
5563
|
+
}));
|
|
5564
|
+
setIdMap((state) => {
|
|
5565
|
+
return { ...state, ...newMap };
|
|
5566
|
+
});
|
|
5567
|
+
return data;
|
|
5568
|
+
},
|
|
5569
|
+
enabled: missingIds.length > 0, // Only fetch if there are missing IDs
|
|
5570
|
+
staleTime: 300000,
|
|
5571
|
+
});
|
|
5572
|
+
const { isLoading: isLoadingInitialValues, isFetching: isFetchingInitialValues, } = initialValuesQuery;
|
|
5401
5573
|
// Query for search results (async loading)
|
|
5402
5574
|
const query = reactQuery.useQuery({
|
|
5403
5575
|
queryKey: [`idpicker`, { column, searchText: debouncedSearchText, limit }],
|
|
@@ -5440,16 +5612,60 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5440
5612
|
const dataList = data?.data ?? [];
|
|
5441
5613
|
// Check if we're currently searching (user typed but debounce hasn't fired yet)
|
|
5442
5614
|
const isSearching = searchText !== debouncedSearchText;
|
|
5615
|
+
// Extract items from idMap for currentValue IDs
|
|
5616
|
+
// Use useMemo with a stable dependency to minimize recalculations
|
|
5617
|
+
const currentValueKey = React.useMemo(() => JSON.stringify([...currentValue].sort()), [currentValue]);
|
|
5618
|
+
// Serialize the relevant part of idMap to detect when items we care about change
|
|
5619
|
+
const idMapKey = React.useMemo(() => {
|
|
5620
|
+
const relevantItems = currentValue
|
|
5621
|
+
.map((id) => {
|
|
5622
|
+
const item = idMap[id];
|
|
5623
|
+
return item ? JSON.stringify({ id, hasItem: true }) : null;
|
|
5624
|
+
})
|
|
5625
|
+
.filter(Boolean)
|
|
5626
|
+
.sort()
|
|
5627
|
+
.join('|');
|
|
5628
|
+
return relevantItems;
|
|
5629
|
+
}, [currentValue, idMap]);
|
|
5630
|
+
const idMapItems = React.useMemo(() => {
|
|
5631
|
+
return currentValue
|
|
5632
|
+
.map((id) => idMap[id])
|
|
5633
|
+
.filter((item) => item !== undefined);
|
|
5634
|
+
// Depend on idMapKey which only changes when items we care about change
|
|
5635
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5636
|
+
}, [currentValueKey, idMapKey]);
|
|
5443
5637
|
// Transform data for combobox collection
|
|
5444
5638
|
// label is used for filtering/searching (must be a string)
|
|
5445
5639
|
// raw item is stored for custom rendering
|
|
5640
|
+
// Also include items from idMap that match currentValue (for initial values display)
|
|
5446
5641
|
const comboboxItems = React.useMemo(() => {
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5642
|
+
const renderFn = renderDisplay || defaultRenderDisplay;
|
|
5643
|
+
const itemsFromDataList = dataList.map((item) => {
|
|
5644
|
+
const rendered = renderFn(item);
|
|
5645
|
+
return {
|
|
5646
|
+
label: typeof rendered === 'string' ? rendered : JSON.stringify(item), // Use string for filtering
|
|
5647
|
+
value: String(item[column_ref]),
|
|
5648
|
+
raw: item,
|
|
5649
|
+
};
|
|
5650
|
+
});
|
|
5651
|
+
// Add items from idMap that match currentValue but aren't in dataList
|
|
5652
|
+
// This ensures initial values are displayed correctly in the combobox
|
|
5653
|
+
const itemsFromIdMap = idMapItems
|
|
5654
|
+
.map((item) => {
|
|
5655
|
+
// Check if this item is already in itemsFromDataList
|
|
5656
|
+
const alreadyIncluded = itemsFromDataList.some((i) => i.value === String(item[column_ref]));
|
|
5657
|
+
if (alreadyIncluded)
|
|
5658
|
+
return null;
|
|
5659
|
+
const rendered = renderFn(item);
|
|
5660
|
+
return {
|
|
5661
|
+
label: typeof rendered === 'string' ? rendered : JSON.stringify(item),
|
|
5662
|
+
value: String(item[column_ref]),
|
|
5663
|
+
raw: item,
|
|
5664
|
+
};
|
|
5665
|
+
})
|
|
5666
|
+
.filter((item) => item !== null);
|
|
5667
|
+
return [...itemsFromIdMap, ...itemsFromDataList];
|
|
5668
|
+
}, [dataList, column_ref, renderDisplay, idMapItems]);
|
|
5453
5669
|
// Use filter hook for combobox
|
|
5454
5670
|
const { contains } = react.useFilter({ sensitivity: 'base' });
|
|
5455
5671
|
// Create collection for combobox
|
|
@@ -5473,31 +5689,54 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5473
5689
|
setValue(colLabel, details.value[0] || '');
|
|
5474
5690
|
}
|
|
5475
5691
|
};
|
|
5692
|
+
// Track previous comboboxItems to avoid unnecessary updates
|
|
5693
|
+
const prevComboboxItemsRef = React.useRef('');
|
|
5694
|
+
const prevSearchTextRef = React.useRef('');
|
|
5476
5695
|
// Update collection and filter when data changes
|
|
5696
|
+
// This includes both search results and initial values from idMap
|
|
5477
5697
|
React.useEffect(() => {
|
|
5478
|
-
|
|
5698
|
+
// Create a stable string representation to compare (only value and label, not raw)
|
|
5699
|
+
const currentItemsKey = JSON.stringify(comboboxItems.map((item) => ({ value: item.value, label: item.label })));
|
|
5700
|
+
const itemsChanged = prevComboboxItemsRef.current !== currentItemsKey;
|
|
5701
|
+
const searchChanged = prevSearchTextRef.current !== searchText;
|
|
5702
|
+
// Only update if items or search actually changed
|
|
5703
|
+
if (!itemsChanged && !searchChanged) {
|
|
5704
|
+
return;
|
|
5705
|
+
}
|
|
5706
|
+
if (comboboxItems.length > 0 && itemsChanged) {
|
|
5479
5707
|
set(comboboxItems);
|
|
5480
|
-
|
|
5708
|
+
prevComboboxItemsRef.current = currentItemsKey;
|
|
5709
|
+
}
|
|
5710
|
+
// Apply filter to the collection using the immediate searchText for UI responsiveness
|
|
5711
|
+
if (searchChanged) {
|
|
5481
5712
|
if (searchText) {
|
|
5482
5713
|
filter(searchText);
|
|
5483
5714
|
}
|
|
5715
|
+
prevSearchTextRef.current = searchText;
|
|
5484
5716
|
}
|
|
5485
|
-
// Only depend on dataList and searchText, not comboboxItems (which is derived from dataList)
|
|
5486
5717
|
// set and filter are stable functions from useListCollection
|
|
5718
|
+
// comboboxItems and searchText are the only dependencies we care about
|
|
5487
5719
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5488
|
-
}, [
|
|
5720
|
+
}, [comboboxItems, searchText]);
|
|
5489
5721
|
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5490
5722
|
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
|
|
5491
5723
|
const item = idMap[id];
|
|
5724
|
+
// Show loading skeleton while fetching initial values
|
|
5725
|
+
if (item === undefined &&
|
|
5726
|
+
(isLoadingInitialValues || isFetchingInitialValues) &&
|
|
5727
|
+
missingIds.includes(id)) {
|
|
5728
|
+
return (jsxRuntime.jsx(react.Skeleton, { height: "24px", width: "100px", borderRadius: "md" }, id));
|
|
5729
|
+
}
|
|
5730
|
+
// Only show "not found" if we're not loading and item is still missing
|
|
5492
5731
|
if (item === undefined) {
|
|
5493
5732
|
return (jsxRuntime.jsx(react.Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
|
|
5494
5733
|
}
|
|
5495
5734
|
return (jsxRuntime.jsx(Tag, { closable: true, onClick: () => {
|
|
5496
5735
|
const newValue = currentValue.filter((itemId) => itemId !== id);
|
|
5497
5736
|
setValue(colLabel, newValue);
|
|
5498
|
-
}, children:
|
|
5737
|
+
}, children: renderDisplay
|
|
5499
5738
|
? renderDisplay(item)
|
|
5500
|
-
: item
|
|
5739
|
+
: defaultRenderDisplay(item) }, id));
|
|
5501
5740
|
}) })), jsxRuntime.jsxs(react.Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
|
|
5502
5741
|
? { strategy: 'fixed', hideWhenDetached: true }
|
|
5503
5742
|
: undefined, children: [jsxRuntime.jsxs(react.Combobox.Control, { children: [jsxRuntime.jsx(react.Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? formI18n.t('type_to_search') }), jsxRuntime.jsxs(react.Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsxRuntime.jsx(react.Spinner, { size: "xs" }), isError && (jsxRuntime.jsx(react.Icon, { color: "fg.error", children: jsxRuntime.jsx(bi.BiError, {}) })), !isMultiple && currentValue.length > 0 && (jsxRuntime.jsx(react.Combobox.ClearTrigger, { onClick: () => {
|
|
@@ -5586,15 +5825,15 @@ const extractErrorMessage = (error) => {
|
|
|
5586
5825
|
|
|
5587
5826
|
const NumberInputField = ({ schema, column, prefix, }) => {
|
|
5588
5827
|
const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
|
|
5589
|
-
const { translate } = useSchemaContext();
|
|
5590
5828
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', numberStorageType = 'number', } = schema;
|
|
5591
5829
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5592
5830
|
const colLabel = `${prefix}${column}`;
|
|
5593
5831
|
const value = watch(`${colLabel}`);
|
|
5594
5832
|
const fieldError = getFieldError(errors, colLabel);
|
|
5595
|
-
|
|
5833
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5834
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError
|
|
5596
5835
|
? fieldError.includes('required')
|
|
5597
|
-
?
|
|
5836
|
+
? formI18n.required()
|
|
5598
5837
|
: fieldError
|
|
5599
5838
|
: undefined, invalid: !!fieldError, children: jsxRuntime.jsx(NumberInputRoot, { value: value, onValueChange: (details) => {
|
|
5600
5839
|
// Store as string or number based on configuration, default to number
|
|
@@ -5607,14 +5846,14 @@ const NumberInputField = ({ schema, column, prefix, }) => {
|
|
|
5607
5846
|
|
|
5608
5847
|
const ObjectInput = ({ schema, column, prefix }) => {
|
|
5609
5848
|
const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
|
|
5610
|
-
const { translate } = useSchemaContext();
|
|
5611
5849
|
const colLabel = `${prefix}${column}`;
|
|
5612
5850
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5851
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5613
5852
|
const { formState: { errors }, } = reactHookForm.useFormContext();
|
|
5614
5853
|
if (properties === undefined) {
|
|
5615
5854
|
throw new Error(`properties is undefined when using ObjectInput`);
|
|
5616
5855
|
}
|
|
5617
|
-
return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [showLabel && (jsxRuntime.jsxs(react.Box, { as: "label", children: [
|
|
5856
|
+
return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [showLabel && (jsxRuntime.jsxs(react.Box, { as: "label", children: [formI18n.label(), isRequired && jsxRuntime.jsx("span", { children: "*" })] })), jsxRuntime.jsx(react.Grid, { bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
|
|
5618
5857
|
base: 'colorPalette.200',
|
|
5619
5858
|
_dark: 'colorPalette.800',
|
|
5620
5859
|
}, gap: "4", padding: '4', gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: Object.keys(properties ?? {}).map((key) => {
|
|
@@ -5624,10 +5863,10 @@ const ObjectInput = ({ schema, column, prefix }) => {
|
|
|
5624
5863
|
prefix: `${prefix}${column}.`,
|
|
5625
5864
|
properties,
|
|
5626
5865
|
parentRequired: required }, `form-${colLabel}-${key}`));
|
|
5627
|
-
}) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children:
|
|
5866
|
+
}) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
5628
5867
|
};
|
|
5629
5868
|
|
|
5630
|
-
const RecordInput
|
|
5869
|
+
const RecordInput = ({ column, schema, prefix }) => {
|
|
5631
5870
|
const { formState: { errors }, setValue, getValues, } = reactHookForm.useFormContext();
|
|
5632
5871
|
const { translate } = useSchemaContext();
|
|
5633
5872
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
@@ -5636,9 +5875,8 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
|
|
|
5636
5875
|
const [showNewEntries, setShowNewEntries] = React.useState(false);
|
|
5637
5876
|
const [newKey, setNewKey] = React.useState();
|
|
5638
5877
|
const [newValue, setNewValue] = React.useState();
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
: undefined, invalid: !!errors[column], children: [entries.map(([key, value]) => {
|
|
5878
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5879
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: errors[`${column}`] ? formI18n.required() : undefined, invalid: !!errors[column], children: [entries.map(([key, value]) => {
|
|
5642
5880
|
return (jsxRuntime.jsxs(react.Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
|
|
5643
5881
|
const filtered = entries.filter(([target]) => {
|
|
5644
5882
|
return target !== key;
|
|
@@ -5683,12 +5921,12 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
|
|
|
5683
5921
|
|
|
5684
5922
|
const StringInputField = ({ column, schema, prefix, }) => {
|
|
5685
5923
|
const { register, formState: { errors }, } = reactHookForm.useFormContext();
|
|
5686
|
-
const { translate } = useSchemaContext();
|
|
5687
5924
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
5688
5925
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5689
5926
|
const colLabel = `${prefix}${column}`;
|
|
5690
5927
|
const fieldError = getFieldError(errors, colLabel);
|
|
5691
|
-
|
|
5928
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5929
|
+
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: fieldError, invalid: !!fieldError, children: jsxRuntime.jsx(react.Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
|
|
5692
5930
|
};
|
|
5693
5931
|
|
|
5694
5932
|
const RadioCardItem = React__namespace.forwardRef(function RadioCardItem(props, ref) {
|
|
@@ -5873,17 +6111,17 @@ Textarea.displayName = "Textarea";
|
|
|
5873
6111
|
|
|
5874
6112
|
const TextAreaInput = ({ column, schema, prefix, }) => {
|
|
5875
6113
|
const { register, formState: { errors }, } = reactHookForm.useFormContext();
|
|
5876
|
-
const { translate } = useSchemaContext();
|
|
5877
6114
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
5878
6115
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5879
6116
|
const colLabel = `${prefix}${column}`;
|
|
5880
6117
|
const form = reactHookForm.useFormContext();
|
|
5881
6118
|
const { setValue, watch } = form;
|
|
5882
6119
|
const fieldError = getFieldError(errors, colLabel);
|
|
6120
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5883
6121
|
const watchValue = watch(colLabel);
|
|
5884
|
-
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label:
|
|
6122
|
+
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
|
|
5885
6123
|
? fieldError.includes('required')
|
|
5886
|
-
?
|
|
6124
|
+
? formI18n.required()
|
|
5887
6125
|
: fieldError
|
|
5888
6126
|
: undefined, invalid: !!fieldError, children: jsxRuntime.jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
|
|
5889
6127
|
};
|
|
@@ -6205,10 +6443,11 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
|
|
|
6205
6443
|
dayjs.extend(timezone);
|
|
6206
6444
|
const TimePicker = ({ column, schema, prefix }) => {
|
|
6207
6445
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
6208
|
-
const {
|
|
6446
|
+
const { timezone, insideDialog } = useSchemaContext();
|
|
6209
6447
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
|
|
6210
6448
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
6211
6449
|
const colLabel = `${prefix}${column}`;
|
|
6450
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
6212
6451
|
const [open, setOpen] = React.useState(false);
|
|
6213
6452
|
const value = watch(colLabel);
|
|
6214
6453
|
const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
|
|
@@ -6263,10 +6502,8 @@ const TimePicker = ({ column, schema, prefix }) => {
|
|
|
6263
6502
|
const timeString = getTimeString(newHour, newMinute, newMeridiem);
|
|
6264
6503
|
setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
|
|
6265
6504
|
};
|
|
6266
|
-
return (jsxRuntime.jsx(Field, { label:
|
|
6267
|
-
gridRow, errorText: errors[`${colLabel}`]
|
|
6268
|
-
? translate.t(removeIndex(`${colLabel}.field_required`))
|
|
6269
|
-
: undefined, invalid: !!errors[colLabel], 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: () => {
|
|
6505
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
6506
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], 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: () => {
|
|
6270
6507
|
setOpen(true);
|
|
6271
6508
|
}, justifyContent: 'start', children: [jsxRuntime.jsx(io.IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsx(react.Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsxRuntime.jsx(react.Popover.Body, { overflow: "visible", children: jsxRuntime.jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
|
|
6272
6509
|
am: translate.t(`common.am`, { defaultValue: 'AM' }),
|
|
@@ -7156,7 +7393,7 @@ dayjs.extend(timezone);
|
|
|
7156
7393
|
const DateTimePicker = ({ column, schema, prefix, }) => {
|
|
7157
7394
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
7158
7395
|
const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
|
|
7159
|
-
const formI18n = useFormI18n(column, prefix);
|
|
7396
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7160
7397
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
|
|
7161
7398
|
// with timezone
|
|
7162
7399
|
dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
|
|
@@ -7298,7 +7535,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
|
7298
7535
|
if (innerProperties) {
|
|
7299
7536
|
return jsxRuntime.jsx(ObjectInput, { schema: colSchema, prefix, column });
|
|
7300
7537
|
}
|
|
7301
|
-
return jsxRuntime.jsx(RecordInput
|
|
7538
|
+
return jsxRuntime.jsx(RecordInput, { schema: colSchema, prefix, column });
|
|
7302
7539
|
}
|
|
7303
7540
|
if (type === 'array') {
|
|
7304
7541
|
if (variant === 'id-picker') {
|
|
@@ -7352,32 +7589,30 @@ const ColumnRenderer = ({ column, properties, prefix, parentRequired, }) => {
|
|
|
7352
7589
|
};
|
|
7353
7590
|
|
|
7354
7591
|
const ArrayViewer = ({ schema, column, prefix }) => {
|
|
7355
|
-
const { gridColumn =
|
|
7356
|
-
const { translate } = useSchemaContext();
|
|
7592
|
+
const { gridColumn = 'span 12', gridRow = 'span 1', required, items, } = schema;
|
|
7357
7593
|
const colLabel = `${prefix}${column}`;
|
|
7358
7594
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7595
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7359
7596
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7360
7597
|
const values = watch(colLabel) ?? [];
|
|
7361
|
-
return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [jsxRuntime.jsxs(react.Box, { as: "label", gridColumn:
|
|
7362
|
-
base:
|
|
7363
|
-
_dark:
|
|
7364
|
-
}, children: jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns:
|
|
7598
|
+
return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [jsxRuntime.jsxs(react.Box, { as: "label", gridColumn: '1/span12', children: [formI18n.label(), isRequired && jsxRuntime.jsx("span", { children: "*" })] }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: values.map((field, index) => (jsxRuntime.jsx(react.Flex, { flexFlow: 'column', bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: '2', borderRadius: 'md', borderWidth: 'thin', borderColor: {
|
|
7599
|
+
base: 'colorPalette.200',
|
|
7600
|
+
_dark: 'colorPalette.800',
|
|
7601
|
+
}, children: jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: jsxRuntime.jsx(SchemaViewer, { column: `${index}`,
|
|
7365
7602
|
prefix: `${colLabel}.`,
|
|
7366
7603
|
// @ts-expect-error find suitable types
|
|
7367
|
-
schema: { showLabel: false, ...(items ?? {}) } }) }) }, `form-${prefix}${column}.${index}`))) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color:
|
|
7604
|
+
schema: { showLabel: false, ...(items ?? {}) } }) }) }, `form-${prefix}${column}.${index}`))) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7368
7605
|
};
|
|
7369
7606
|
|
|
7370
7607
|
const BooleanViewer = ({ schema, column, prefix, }) => {
|
|
7371
7608
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7372
|
-
const {
|
|
7373
|
-
const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
|
|
7609
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7374
7610
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7375
7611
|
const colLabel = `${prefix}${column}`;
|
|
7376
7612
|
const value = watch(colLabel);
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
: translate.t(removeIndex(`${colLabel}.false`)) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
7613
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7614
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7615
|
+
gridRow, children: [jsxRuntime.jsx(react.Text, { children: value ? formI18n.t('true') : formI18n.t('false') }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7381
7616
|
};
|
|
7382
7617
|
|
|
7383
7618
|
const CustomViewer = ({ column, schema, prefix }) => {
|
|
@@ -7394,19 +7629,22 @@ const CustomViewer = ({ column, schema, prefix }) => {
|
|
|
7394
7629
|
|
|
7395
7630
|
const DateViewer = ({ column, schema, prefix }) => {
|
|
7396
7631
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7397
|
-
const {
|
|
7398
|
-
const { required, gridColumn =
|
|
7632
|
+
const { timezone } = useSchemaContext();
|
|
7633
|
+
const { required, gridColumn = 'span 4', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', } = schema;
|
|
7399
7634
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7400
7635
|
const colLabel = `${prefix}${column}`;
|
|
7401
7636
|
const selectedDate = watch(colLabel);
|
|
7402
|
-
const
|
|
7403
|
-
|
|
7404
|
-
|
|
7637
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7638
|
+
const displayDate = dayjs(selectedDate)
|
|
7639
|
+
.tz(timezone)
|
|
7640
|
+
.format(displayDateFormat);
|
|
7641
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7642
|
+
gridRow, children: [jsxRuntime.jsxs(react.Text, { children: [" ", selectedDate !== undefined ? displayDate : ''] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7405
7643
|
};
|
|
7406
7644
|
|
|
7407
7645
|
const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
7408
7646
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7409
|
-
const formI18n = useFormI18n(column, prefix);
|
|
7647
|
+
const formI18n = useFormI18n$1(column, prefix);
|
|
7410
7648
|
const { required } = schema;
|
|
7411
7649
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7412
7650
|
const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
|
|
@@ -7427,54 +7665,56 @@ const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
|
7427
7665
|
|
|
7428
7666
|
const FileViewer = ({ column, schema, prefix }) => {
|
|
7429
7667
|
const { watch } = reactHookForm.useFormContext();
|
|
7430
|
-
const {
|
|
7431
|
-
const { required, gridColumn = "span 12", gridRow = "span 1", } = schema;
|
|
7668
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
|
|
7432
7669
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7433
7670
|
const currentFiles = (watch(column) ?? []);
|
|
7434
|
-
const
|
|
7435
|
-
return (jsxRuntime.jsx(Field, { label:
|
|
7436
|
-
return (jsxRuntime.jsx(react.Card.Root, { variant:
|
|
7671
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7672
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, display: 'grid', gridTemplateRows: 'auto 1fr auto', alignItems: 'stretch', children: jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file) => {
|
|
7673
|
+
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));
|
|
7437
7674
|
}) }) }));
|
|
7438
7675
|
};
|
|
7439
7676
|
|
|
7440
7677
|
const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
7441
7678
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7442
7679
|
const { idMap, translate } = useSchemaContext();
|
|
7443
|
-
const { required, gridColumn =
|
|
7680
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
|
|
7444
7681
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7445
|
-
const
|
|
7682
|
+
const formI18n = useFormI18n(column, prefix, schema);
|
|
7446
7683
|
const colLabel = `${prefix}${column}`;
|
|
7447
7684
|
const watchId = watch(colLabel);
|
|
7448
7685
|
const watchIds = (watch(colLabel) ?? []);
|
|
7449
7686
|
const getPickedValue = () => {
|
|
7450
7687
|
if (Object.keys(idMap).length <= 0) {
|
|
7451
|
-
return
|
|
7688
|
+
return '';
|
|
7452
7689
|
}
|
|
7453
7690
|
const record = idMap[watchId];
|
|
7454
7691
|
if (record === undefined) {
|
|
7455
|
-
return
|
|
7692
|
+
return '';
|
|
7456
7693
|
}
|
|
7457
|
-
|
|
7694
|
+
const rendered = renderDisplay
|
|
7695
|
+
? renderDisplay(record)
|
|
7696
|
+
: defaultRenderDisplay(record);
|
|
7697
|
+
return typeof rendered === 'string' ? rendered : JSON.stringify(record);
|
|
7458
7698
|
};
|
|
7459
|
-
return (jsxRuntime.jsxs(Field, { label:
|
|
7460
|
-
gridRow, children: [isMultiple && (jsxRuntime.jsx(react.Flex, { flexFlow:
|
|
7699
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7700
|
+
gridRow, children: [isMultiple && (jsxRuntime.jsx(react.Flex, { flexFlow: 'wrap', gap: 1, children: watchIds.map((id) => {
|
|
7461
7701
|
const item = idMap[id];
|
|
7462
7702
|
if (item === undefined) {
|
|
7463
7703
|
return (jsxRuntime.jsx(react.Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
|
|
7464
7704
|
}
|
|
7465
|
-
return (jsxRuntime.jsx(Tag, { closable: true, children:
|
|
7705
|
+
return (jsxRuntime.jsx(Tag, { closable: true, children: renderDisplay
|
|
7466
7706
|
? renderDisplay(item)
|
|
7467
|
-
: item
|
|
7468
|
-
}) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color:
|
|
7707
|
+
: defaultRenderDisplay(item) }, id));
|
|
7708
|
+
}) })), !isMultiple && jsxRuntime.jsx(react.Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
7469
7709
|
};
|
|
7470
7710
|
|
|
7471
7711
|
const NumberViewer = ({ schema, column, prefix, }) => {
|
|
7472
7712
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7473
|
-
const { translate } = useSchemaContext();
|
|
7474
7713
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7475
7714
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7476
7715
|
const colLabel = `${prefix}${column}`;
|
|
7477
7716
|
const value = watch(colLabel);
|
|
7717
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7478
7718
|
// Format the value for display if formatOptions are provided
|
|
7479
7719
|
const formatValue = (val) => {
|
|
7480
7720
|
if (val === undefined || val === null || val === '')
|
|
@@ -7493,90 +7733,49 @@ const NumberViewer = ({ schema, column, prefix, }) => {
|
|
|
7493
7733
|
}
|
|
7494
7734
|
return String(val);
|
|
7495
7735
|
};
|
|
7496
|
-
return (jsxRuntime.jsxs(Field, { label:
|
|
7736
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, children: [jsxRuntime.jsx(react.Text, { children: formatValue(value) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7497
7737
|
};
|
|
7498
7738
|
|
|
7499
7739
|
const ObjectViewer = ({ schema, column, prefix }) => {
|
|
7500
|
-
const { properties, gridColumn =
|
|
7501
|
-
const { translate } = useSchemaContext();
|
|
7740
|
+
const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
|
|
7502
7741
|
const colLabel = `${prefix}${column}`;
|
|
7503
7742
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7743
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7504
7744
|
const { formState: { errors }, } = reactHookForm.useFormContext();
|
|
7505
7745
|
if (properties === undefined) {
|
|
7506
7746
|
throw new Error(`properties is undefined when using ObjectInput`);
|
|
7507
7747
|
}
|
|
7508
|
-
return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [showLabel && (jsxRuntime.jsxs(react.Box, { as: "label", children: [
|
|
7509
|
-
base:
|
|
7510
|
-
_dark:
|
|
7748
|
+
return (jsxRuntime.jsxs(react.Box, { gridRow, gridColumn, children: [showLabel && (jsxRuntime.jsxs(react.Box, { as: "label", children: [formI18n.label(), isRequired && jsxRuntime.jsx("span", { children: "*" })] })), jsxRuntime.jsx(react.Grid, { gap: "4", padding: '4', gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: '1', borderRadius: 'md', borderWidth: 'thin', borderColor: {
|
|
7749
|
+
base: 'colorPalette.200',
|
|
7750
|
+
_dark: 'colorPalette.800',
|
|
7511
7751
|
}, children: Object.keys(properties ?? {}).map((key) => {
|
|
7512
7752
|
return (
|
|
7513
7753
|
// @ts-expect-error find suitable types
|
|
7514
7754
|
jsxRuntime.jsx(ColumnViewer, { column: `${key}`,
|
|
7515
7755
|
prefix: `${prefix}${column}.`,
|
|
7516
7756
|
properties }, `form-objectviewer-${colLabel}-${key}`));
|
|
7517
|
-
}) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color:
|
|
7757
|
+
}) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7518
7758
|
};
|
|
7519
7759
|
|
|
7520
|
-
const
|
|
7521
|
-
const { formState: { errors },
|
|
7522
|
-
const {
|
|
7523
|
-
const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
|
|
7760
|
+
const RecordViewer = ({ column, schema, prefix }) => {
|
|
7761
|
+
const { formState: { errors }, getValues, } = reactHookForm.useFormContext();
|
|
7762
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7524
7763
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7525
7764
|
const entries = Object.entries(getValues(column) ?? {});
|
|
7526
|
-
const
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
return (jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsxRuntime.jsx(react.Input, { value: key, onChange: (e) => {
|
|
7531
|
-
const filtered = entries.filter(([target]) => {
|
|
7532
|
-
return target !== key;
|
|
7533
|
-
});
|
|
7534
|
-
setValue(column, Object.fromEntries([...filtered, [e.target.value, value]]));
|
|
7535
|
-
}, autoComplete: "off" }), jsxRuntime.jsx(react.Input, { value: value, onChange: (e) => {
|
|
7536
|
-
setValue(column, {
|
|
7537
|
-
...getValues(column),
|
|
7538
|
-
[key]: e.target.value,
|
|
7539
|
-
});
|
|
7540
|
-
}, autoComplete: "off" }), jsxRuntime.jsx(react.IconButton, { variant: "ghost", onClick: () => {
|
|
7541
|
-
const filtered = entries.filter(([target]) => {
|
|
7542
|
-
return target !== key;
|
|
7543
|
-
});
|
|
7544
|
-
setValue(column, Object.fromEntries([...filtered]));
|
|
7545
|
-
}, children: jsxRuntime.jsx(cg.CgClose, {}) })] }));
|
|
7546
|
-
}), jsxRuntime.jsx(react.Show, { when: showNewEntries, children: jsxRuntime.jsxs(react.Card.Root, { children: [jsxRuntime.jsx(react.Card.Body, { gap: "2", children: jsxRuntime.jsxs(react.Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsxRuntime.jsx(react.Input, { value: newKey, onChange: (e) => {
|
|
7547
|
-
setNewKey(e.target.value);
|
|
7548
|
-
}, autoComplete: "off" }), jsxRuntime.jsx(react.Input, { value: newValue, onChange: (e) => {
|
|
7549
|
-
setNewValue(e.target.value);
|
|
7550
|
-
}, autoComplete: "off" })] }) }), jsxRuntime.jsxs(react.Card.Footer, { justifyContent: "flex-end", children: [jsxRuntime.jsx(react.IconButton, { variant: "subtle", onClick: () => {
|
|
7551
|
-
setShowNewEntries(false);
|
|
7552
|
-
setNewKey(undefined);
|
|
7553
|
-
setNewValue(undefined);
|
|
7554
|
-
}, children: jsxRuntime.jsx(cg.CgClose, {}) }), jsxRuntime.jsx(Button, { onClick: () => {
|
|
7555
|
-
if (!!newKey === false) {
|
|
7556
|
-
setShowNewEntries(false);
|
|
7557
|
-
setNewKey(undefined);
|
|
7558
|
-
setNewValue(undefined);
|
|
7559
|
-
return;
|
|
7560
|
-
}
|
|
7561
|
-
setValue(column, Object.fromEntries([...entries, [newKey, newValue]]));
|
|
7562
|
-
setShowNewEntries(false);
|
|
7563
|
-
setNewKey(undefined);
|
|
7564
|
-
setNewValue(undefined);
|
|
7565
|
-
}, children: translate.t(`${column}.save`) })] })] }) }), jsxRuntime.jsx(Button, { onClick: () => {
|
|
7566
|
-
setShowNewEntries(true);
|
|
7567
|
-
setNewKey(undefined);
|
|
7568
|
-
setNewValue(undefined);
|
|
7569
|
-
}, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
|
|
7765
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7766
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, children: [entries.length === 0 ? (jsxRuntime.jsx(react.Text, { color: "gray.500", children: "No entries" })) : (jsxRuntime.jsx(react.Grid, { templateColumns: '1fr 1fr', gap: 2, children: entries.map(([key, value]) => {
|
|
7767
|
+
return (jsxRuntime.jsxs(react.Grid, { templateColumns: '1fr 1fr', gap: 2, children: [jsxRuntime.jsxs(react.Text, { fontWeight: "medium", children: [key, ":"] }), jsxRuntime.jsx(react.Text, { children: String(value ?? '') })] }, key));
|
|
7768
|
+
}) })), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7570
7769
|
};
|
|
7571
7770
|
|
|
7572
7771
|
const StringViewer = ({ column, schema, prefix, }) => {
|
|
7573
7772
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7574
|
-
const {
|
|
7575
|
-
const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
|
|
7773
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7576
7774
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7577
7775
|
const colLabel = `${prefix}${column}`;
|
|
7578
7776
|
const value = watch(colLabel);
|
|
7579
|
-
|
|
7777
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7778
|
+
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: formI18n.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: formI18n.required() }))] }) }));
|
|
7580
7779
|
};
|
|
7581
7780
|
|
|
7582
7781
|
const TagViewer = ({ column, schema, prefix }) => {
|
|
@@ -7666,40 +7865,44 @@ const TagViewer = ({ column, schema, prefix }) => {
|
|
|
7666
7865
|
|
|
7667
7866
|
const TextAreaViewer = ({ column, schema, prefix, }) => {
|
|
7668
7867
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7669
|
-
const {
|
|
7670
|
-
const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
|
|
7868
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7671
7869
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7672
7870
|
const colLabel = `${prefix}${column}`;
|
|
7673
7871
|
const value = watch(colLabel);
|
|
7674
|
-
|
|
7872
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7873
|
+
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsxRuntime.jsx(react.Text, { whiteSpace: "pre-wrap", children: value }), ' ', errors[colLabel] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }) }));
|
|
7675
7874
|
};
|
|
7676
7875
|
|
|
7677
7876
|
const TimeViewer = ({ column, schema, prefix }) => {
|
|
7678
7877
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7679
|
-
const {
|
|
7680
|
-
const { required, gridColumn =
|
|
7878
|
+
const { timezone } = useSchemaContext();
|
|
7879
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayTimeFormat = 'hh:mm A', } = schema;
|
|
7681
7880
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7682
7881
|
const colLabel = `${prefix}${column}`;
|
|
7683
7882
|
const selectedDate = watch(colLabel);
|
|
7883
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7684
7884
|
const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
|
|
7685
7885
|
.tz(timezone)
|
|
7686
7886
|
.isValid()
|
|
7687
7887
|
? dayjs(`1970-01-01T${selectedDate}`).tz(timezone).format(displayTimeFormat)
|
|
7688
|
-
:
|
|
7689
|
-
return (jsxRuntime.jsxs(Field, { label:
|
|
7690
|
-
gridRow, children: [jsxRuntime.jsx(react.Text, { children: displayedTime }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color:
|
|
7888
|
+
: '';
|
|
7889
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7890
|
+
gridRow, children: [jsxRuntime.jsx(react.Text, { children: displayedTime }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7691
7891
|
};
|
|
7692
7892
|
|
|
7693
7893
|
const DateTimeViewer = ({ column, schema, prefix }) => {
|
|
7694
7894
|
const { watch, formState: { errors }, } = reactHookForm.useFormContext();
|
|
7695
|
-
const {
|
|
7696
|
-
const { required, gridColumn =
|
|
7895
|
+
const { timezone } = useSchemaContext();
|
|
7896
|
+
const { required, gridColumn = 'span 4', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss', } = schema;
|
|
7697
7897
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7698
7898
|
const colLabel = `${prefix}${column}`;
|
|
7699
7899
|
const selectedDate = watch(colLabel);
|
|
7700
|
-
const
|
|
7701
|
-
|
|
7702
|
-
|
|
7900
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7901
|
+
const displayDate = dayjs(selectedDate)
|
|
7902
|
+
.tz(timezone)
|
|
7903
|
+
.format(displayDateFormat);
|
|
7904
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7905
|
+
gridRow, children: [jsxRuntime.jsxs(react.Text, { children: [" ", selectedDate !== undefined ? displayDate : ''] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7703
7906
|
};
|
|
7704
7907
|
|
|
7705
7908
|
const SchemaViewer = ({ schema, prefix, column, }) => {
|
|
@@ -7740,7 +7943,7 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
|
|
|
7740
7943
|
if (innerProperties) {
|
|
7741
7944
|
return jsxRuntime.jsx(ObjectViewer, { schema: colSchema, prefix, column });
|
|
7742
7945
|
}
|
|
7743
|
-
return jsxRuntime.jsx(
|
|
7946
|
+
return jsxRuntime.jsx(RecordViewer, { schema: colSchema, prefix, column });
|
|
7744
7947
|
}
|
|
7745
7948
|
if (type === 'array') {
|
|
7746
7949
|
if (variant === 'id-picker') {
|
|
@@ -7788,7 +7991,7 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
|
|
|
7788
7991
|
};
|
|
7789
7992
|
|
|
7790
7993
|
const SubmitButton = () => {
|
|
7791
|
-
const { translate, setValidatedData, setIsError, setIsConfirming,
|
|
7994
|
+
const { translate, setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
|
|
7792
7995
|
const methods = reactHookForm.useFormContext();
|
|
7793
7996
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7794
7997
|
const onValid = (data) => {
|
|
@@ -7817,11 +8020,11 @@ const SubmitButton = () => {
|
|
|
7817
8020
|
};
|
|
7818
8021
|
return (jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
7819
8022
|
methods.handleSubmit(onValid)();
|
|
7820
|
-
}, formNoValidate: true, children: translate.t('submit') }));
|
|
8023
|
+
}, formNoValidate: true, children: formButtonLabels?.submit ?? translate.t('submit') }));
|
|
7821
8024
|
};
|
|
7822
8025
|
|
|
7823
8026
|
const FormBody = () => {
|
|
7824
|
-
const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, } = useSchemaContext();
|
|
8027
|
+
const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
|
|
7825
8028
|
const { showSubmitButton, showResetButton } = displayConfig;
|
|
7826
8029
|
const methods = reactHookForm.useFormContext();
|
|
7827
8030
|
const { properties } = schema;
|
|
@@ -7851,7 +8054,7 @@ const FormBody = () => {
|
|
|
7851
8054
|
if (customSuccessRenderer) {
|
|
7852
8055
|
return customSuccessRenderer(resetHandler);
|
|
7853
8056
|
}
|
|
7854
|
-
return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Title, { children: translate.t('submit_success') }) })] }), jsxRuntime.jsx(react.Flex, { justifyContent: 'end', children: jsxRuntime.jsx(react.Button, { onClick: resetHandler, formNoValidate: true, children: translate.t('submit_again') }) })] }));
|
|
8057
|
+
return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "2", children: [jsxRuntime.jsxs(react.Alert.Root, { status: "success", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsx(react.Alert.Content, { children: jsxRuntime.jsx(react.Alert.Title, { children: translate.t('submit_success') }) })] }), jsxRuntime.jsx(react.Flex, { justifyContent: 'end', children: jsxRuntime.jsx(react.Button, { onClick: resetHandler, formNoValidate: true, children: formButtonLabels?.submitAgain ?? translate.t('submit_again') }) })] }));
|
|
7855
8058
|
}
|
|
7856
8059
|
if (isConfirming) {
|
|
7857
8060
|
return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: 4, gridTemplateColumns: 'repeat(12, 1fr)', gridTemplateRows: 'repeat(12, max-content)', autoFlow: 'row', children: ordered.map((column) => {
|
|
@@ -7862,9 +8065,9 @@ const FormBody = () => {
|
|
|
7862
8065
|
properties: properties, prefix: ``, column }, `form-viewer-${column}`));
|
|
7863
8066
|
}) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: '2', children: [jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
7864
8067
|
setIsConfirming(false);
|
|
7865
|
-
}, variant: 'subtle', children: translate.t('cancel') }), jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
8068
|
+
}, variant: 'subtle', children: formButtonLabels?.cancel ?? translate.t('cancel') }), jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
7866
8069
|
onFormSubmit(validatedData);
|
|
7867
|
-
}, children: translate.t('confirm') })] }), isSubmiting && (jsxRuntime.jsx(react.Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsxRuntime.jsx(react.Center, { h: "full", children: jsxRuntime.jsx(react.Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
|
|
8070
|
+
}, children: formButtonLabels?.confirm ?? translate.t('confirm') })] }), isSubmiting && (jsxRuntime.jsx(react.Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsxRuntime.jsx(react.Center, { h: "full", children: jsxRuntime.jsx(react.Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
|
|
7868
8071
|
}
|
|
7869
8072
|
return (jsxRuntime.jsxs(react.Flex, { flexFlow: 'column', gap: "2", children: [jsxRuntime.jsx(react.Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
|
|
7870
8073
|
return (jsxRuntime.jsx(ColumnRenderer
|
|
@@ -7874,7 +8077,7 @@ const FormBody = () => {
|
|
|
7874
8077
|
properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
|
|
7875
8078
|
}) }), jsxRuntime.jsxs(react.Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsxRuntime.jsx(react.Button, { onClick: () => {
|
|
7876
8079
|
methods.reset();
|
|
7877
|
-
}, variant: 'subtle', children: translate.t('reset') })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
|
|
8080
|
+
}, variant: 'subtle', children: formButtonLabels?.reset ?? translate.t('reset') })), showSubmitButton && jsxRuntime.jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
|
|
7878
8081
|
};
|
|
7879
8082
|
|
|
7880
8083
|
const FormTitle = () => {
|
|
@@ -8193,7 +8396,6 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
|
|
|
8193
8396
|
return `minmax(${size}px, ${(size / totalWidths) * 100}%)`;
|
|
8194
8397
|
})
|
|
8195
8398
|
.join(' ');
|
|
8196
|
-
console.log({ columnWidths }, 'hadfg');
|
|
8197
8399
|
const cellProps = {
|
|
8198
8400
|
flex: '1 0 0%',
|
|
8199
8401
|
overflow: 'auto',
|
|
@@ -8210,22 +8412,22 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
|
|
|
8210
8412
|
}
|
|
8211
8413
|
return (jsxRuntime.jsxs(react.Grid, { templateColumns: `${columnWidths}`, overflow: 'auto', borderWidth: '1px', color: { base: 'colorPalette.900', _dark: 'colorPalette.100' }, borderColor: { base: 'colorPalette.200', _dark: 'colorPalette.800' }, colorPalette, children: [jsxRuntime.jsx(react.Grid, { templateColumns: `${columnWidths}`, column: `1/span ${columns.length}`, bg: { base: 'colorPalette.200', _dark: 'colorPalette.800' }, colorPalette, children: columnHeaders.map((header) => {
|
|
8212
8414
|
const columnDef = columnsMap[header];
|
|
8213
|
-
return (jsxRuntime.jsx(react.Box, { flex: '1 0 0%', paddingX: '2', py: '1', overflow: 'auto', textOverflow: 'ellipsis', children: columnDef?.meta?.displayName ?? header }));
|
|
8214
|
-
}) }), data.map((record) => {
|
|
8215
|
-
return (jsxRuntime.jsx(
|
|
8415
|
+
return (jsxRuntime.jsx(react.Box, { flex: '1 0 0%', paddingX: '2', py: '1', overflow: 'auto', textOverflow: 'ellipsis', children: columnDef?.meta?.displayName ?? header }, `chakra-table-header-${header}`));
|
|
8416
|
+
}) }), data.map((record, recordIndex) => {
|
|
8417
|
+
return (jsxRuntime.jsx(react.Box, { display: "contents", children: columnHeaders.map((header) => {
|
|
8216
8418
|
const { cell } = columnsMap[header];
|
|
8217
8419
|
const value = record[header];
|
|
8218
8420
|
if (!!record === false) {
|
|
8219
|
-
return (jsxRuntime.jsx(react.Box, { ...cellProps }));
|
|
8421
|
+
return (jsxRuntime.jsx(react.Box, { ...cellProps }, `chakra-table-cell-${recordIndex}-${header}`));
|
|
8220
8422
|
}
|
|
8221
8423
|
if (cell) {
|
|
8222
|
-
return (jsxRuntime.jsx(react.Box, { ...cellProps, children: cell({ row: { original: record } }) }));
|
|
8424
|
+
return (jsxRuntime.jsx(react.Box, { ...cellProps, children: cell({ row: { original: record } }) }, `chakra-table-cell-${recordIndex}-${header}`));
|
|
8223
8425
|
}
|
|
8224
8426
|
if (typeof value === 'object') {
|
|
8225
|
-
return (jsxRuntime.jsx(react.Box, { ...cellProps, children: jsxRuntime.jsx(RecordDisplay, { object: value }) }));
|
|
8427
|
+
return (jsxRuntime.jsx(react.Box, { ...cellProps, children: jsxRuntime.jsx(RecordDisplay, { object: value }) }, `chakra-table-cell-${recordIndex}-${header}`));
|
|
8226
8428
|
}
|
|
8227
|
-
return jsxRuntime.jsx(react.Box, { ...cellProps, children: value });
|
|
8228
|
-
}) }));
|
|
8429
|
+
return (jsxRuntime.jsx(react.Box, { ...cellProps, children: value }, `chakra-table-cell-${recordIndex}-${header}`));
|
|
8430
|
+
}) }, `chakra-table-record-${recordIndex}`));
|
|
8229
8431
|
})] }));
|
|
8230
8432
|
};
|
|
8231
8433
|
|
|
@@ -8378,19 +8580,19 @@ const DataDisplay = ({ variant = '' }) => {
|
|
|
8378
8580
|
return cell.id === `${rowId}_${column.id}`;
|
|
8379
8581
|
});
|
|
8380
8582
|
if (column.columns.length > 0) {
|
|
8381
|
-
return (jsxRuntime.jsxs(react.Card.Root, { margin: '1', gridColumn: 'span 12', children: [jsxRuntime.jsx(react.Card.Header, { color: 'gray.400', children: column.columnDef.meta?.displayName ?? column.id }), jsxRuntime.jsx(react.Card.Body, { display: 'grid', gap: '4', gridTemplateColumns: 'repeat(12, 1fr)', children: column.columns.map((
|
|
8382
|
-
if (!
|
|
8383
|
-
return
|
|
8583
|
+
return (jsxRuntime.jsxs(react.Card.Root, { margin: '1', gridColumn: 'span 12', children: [jsxRuntime.jsx(react.Card.Header, { color: 'gray.400', children: column.columnDef.meta?.displayName ?? column.id }), jsxRuntime.jsx(react.Card.Body, { display: 'grid', gap: '4', gridTemplateColumns: 'repeat(12, 1fr)', children: column.columns.map((subColumn) => {
|
|
8584
|
+
if (!subColumn.getIsVisible()) {
|
|
8585
|
+
return null;
|
|
8384
8586
|
}
|
|
8385
8587
|
const foundCell = row
|
|
8386
8588
|
.getVisibleCells()
|
|
8387
8589
|
.find((cell) => {
|
|
8388
|
-
return cell.id === `${rowId}_${
|
|
8590
|
+
return cell.id === `${rowId}_${subColumn.id}`;
|
|
8389
8591
|
});
|
|
8390
|
-
return jsxRuntime.jsx(CellRenderer, { cell: foundCell });
|
|
8391
|
-
}) })] }, `chakra-table-card-${
|
|
8592
|
+
return (jsxRuntime.jsx(CellRenderer, { cell: foundCell }, `chakra-table-cell-${rowId}-${subColumn.id}`));
|
|
8593
|
+
}) })] }, `chakra-table-card-${rowId}-${column.id}`));
|
|
8392
8594
|
}
|
|
8393
|
-
return jsxRuntime.jsx(CellRenderer, { cell: childCell });
|
|
8595
|
+
return (jsxRuntime.jsx(CellRenderer, { cell: childCell }, `chakra-table-cell-${rowId}-${column.id}`));
|
|
8394
8596
|
}) }) }, `chakra-table-card-${rowId}`));
|
|
8395
8597
|
}) }));
|
|
8396
8598
|
};
|
|
@@ -8735,6 +8937,7 @@ exports.buildFieldErrors = buildFieldErrors;
|
|
|
8735
8937
|
exports.buildRequiredErrors = buildRequiredErrors;
|
|
8736
8938
|
exports.convertToAjvErrorsFormat = convertToAjvErrorsFormat;
|
|
8737
8939
|
exports.createErrorMessage = createErrorMessage;
|
|
8940
|
+
exports.defaultRenderDisplay = defaultRenderDisplay;
|
|
8738
8941
|
exports.getColumns = getColumns;
|
|
8739
8942
|
exports.getMultiDates = getMultiDates;
|
|
8740
8943
|
exports.getRangeDates = getRangeDates;
|